Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions samples/machine-learning/half-moons/HalfMoons.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.10.1911.307" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.10.1911.2204-alpha" />
<PackageReference Include="Microsoft.Quantum.MachineLearning" Version="0.10.1911.2204-alpha" />
<PackageReference Include="System.Text.Json" Version="4.6.0" />
</ItemGroup>
</Project>
90 changes: 90 additions & 0 deletions samples/machine-learning/half-moons/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;
using System;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Threading.Tasks;
using static System.Math;

namespace Microsoft.Quantum.Samples
{
using Microsoft.Quantum.MachineLearning;
using Microsoft.Quantum.MachineLearning.Interop;

class Program
{
static async Task Main()
{
// We start by loading the training and validation data from our JSON
// data file.
var data = await LoadData("data.json");

// We then define the classifier parameters where we want to start our
// training iterations from. Since gradient descent is good at finding
// local optima, it's helpful to have a variety of different starting
// points.
var parameterStartingPoints = new []
{
new [] {0.060057, 3.00522, 2.03083, 0.63527, 1.03771, 1.27881, 4.10186, 5.34396},
new [] {0.586514, 3.371623, 0.860791, 2.92517, 1.14616, 2.99776, 2.26505, 5.62137},
new [] {1.69704, 1.13912, 2.3595, 4.037552, 1.63698, 1.27549, 0.328671, 0.302282},
new [] {5.21662, 6.04363, 0.224184, 1.53913, 1.64524, 4.79508, 1.49742, 1.5455}
};

// Next, we initialize a full state-vector simulator as our target machine.
using var targetMachine = new QuantumSimulator();

// Once we have the data loaded and have initialized our target machine,
// we can then use that target machine to train a QCC classifier.
var (optimizedParameters, optimizedBias) = await TrainHalfMoonModel.Run(
targetMachine,
new QArray<QArray<double>>(data.TrainingData.Features.Select(vector => new QArray<double>(vector))),
new QArray<long>(data.TrainingData.Labels),
new QArray<QArray<double>>(parameterStartingPoints.Select(parameterSet => new QArray<double>(parameterSet)))
);

// After training, we can use the validation data to test the accuracy
// of our new classifier.
var testMisses = await ValidateHalfMoonModel.Run(
targetMachine,
new QArray<QArray<double>>(data.ValidationData.Features.Select(vector => new QArray<double>(vector))),
new QArray<long>(data.ValidationData.Labels),
optimizedParameters,
optimizedBias
);
System.Console.WriteLine($"Observed {testMisses} misclassifications out of {data.ValidationData.Labels.Count} validation samples.");
}

class LabeledData
{
public List<double[]> Features { get; set; }
public List<long> Labels { get; set; }
}

class DataSet
{
public LabeledData TrainingData { get; set; }
public LabeledData ValidationData { get; set; }
}

static async Task<DataSet> LoadData(string dataPath, double offset = 0.0, double filler = 1.0)
{
using var dataReader = File.OpenRead(dataPath);
return await JsonSerializer.DeserializeAsync<DataSet>(
dataReader,
new JsonSerializerOptions
{
ReadCommentHandling = JsonCommentHandling.Skip
}
);
}

}
}
111 changes: 111 additions & 0 deletions samples/machine-learning/half-moons/Training.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace Microsoft.Quantum.Samples {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.MachineLearning;
open Microsoft.Quantum.Math;

function WithOffset(offset : Double, sample : Double[]) : Double[] {
return Mapped(TimesD(offset, _), sample);
}

function WithProductKernel(scale : Double, sample : Double[]) : Double[] {
return sample + [scale * Fold(TimesD, 1.0, sample)];
}

function Preprocessed(samples : Double[][]) : Double[][] {
let offset = 0.75;
let scale = 1.0;

return Mapped(
Compose(
WithOffset(offset, _),
WithProductKernel(scale, _)
),
samples
);
}

function DefaultSchedule(samples : Double[][]) : SamplingSchedule {
return SamplingSchedule([
0..Length(samples) - 1
]);
}

// FIXME: This needs to return a GateSequence value, but that requires adapting
// TrainQcccSequential.
function ClassifierStructure() : GateSequence {
let (x, y, z) = (1, 2, 3);
return GateSequence([
ControlledRotation(GateSpan(0, new Int[0]), PauliX, 4),
ControlledRotation(GateSpan(0, new Int[0]), PauliZ, 5),
ControlledRotation(GateSpan(1, new Int[0]), PauliX, 6),
ControlledRotation(GateSpan(1, new Int[0]), PauliZ, 7),
ControlledRotation(GateSpan(0, [1]), PauliX, 0),
ControlledRotation(GateSpan(1, [0]), PauliX, 1),
ControlledRotation(GateSpan(1, new Int[0]), PauliZ, 2),
ControlledRotation(GateSpan(1, new Int[0]), PauliX, 3)
]);
}

operation TrainHalfMoonModel(
trainingVectors : Double[][],
trainingLabels : Int[],
initialParameters : Double[][]
) : (Double[], Double) {
let samples = Mapped(
LabeledSample,
Zip(Preprocessed(trainingVectors), trainingLabels)
);
let nQubits = 2;
let learningRate = 0.1;
let minibatchSize = 15;
let tolerance = 0.005;
let nMeasurements = 10000;
let maxEpochs = 16;
Message("Ready to train.");
let (optimizedParameters, optimialBias) = TrainSequentialClassifier(
nQubits,
ClassifierStructure(),
initialParameters,
samples,
DefaultSchedule(trainingVectors),
DefaultSchedule(trainingVectors),
learningRate, tolerance, minibatchSize,
maxEpochs,
nMeasurements
);
Message($"Training complete, found optimal parameters: {optimizedParameters}");
return (optimizedParameters, optimialBias);
}

operation ValidateHalfMoonModel(
validationVectors : Double[][],
validationLabels : Int[],
parameters : Double[],
bias : Double
) : Int {
let samples = Mapped(
LabeledSample,
Zip(Preprocessed(validationVectors), validationLabels)
);
let nQubits = 2;
let tolerance = 0.005;
let nMeasurements = 10000;
let results = ValidateModel(
tolerance,
nQubits,
samples,
DefaultSchedule(validationVectors),
ClassifierStructure(),
parameters,
bias,
nMeasurements
);
return results::NMisclassifications;
}

}
167 changes: 167 additions & 0 deletions samples/machine-learning/half-moons/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

{
"TrainingData": {
"Features": [
[
0.883898709935946,
0.0
],
[
1.1793893456320759,
0.3748347849076317
],
[
0.5231831310352743,
0.900818803609586
],
[
0.30081607582696224,
0.9615554053041235
],
[
-0.06340157706002579,
1.224735863277014
],
[
-0.5382643095868677,
1.0133143141607128
],
[
-0.5975208094029268,
0.561438878658366
],
[
-0.766231190604878,
0.19526118857958627
],
[
0.14060021668138722,
0.4
],
[
0.05239183271831849,
-0.008592101868396151
],
[
0.36087228857768316,
-0.3470962748964499
],
[
0.7371834528946137,
-0.3046817236779634
],
[
1.0706889634601606,
-0.7207038198913537
],
[
1.487876633223481,
-0.37571084836184543
],
[
1.8726657414770358,
-0.16558447370672003
]
],
"Labels": [
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
0,
0,
0,
0
]
},
"ValidationData": {
"Features": [
[
0.883898709935946,
0.0
],
[
1.1793893456320759,
0.3748347849076317
],
[
0.5231831310352743,
0.900818803609586
],
[
0.30081607582696224,
0.9615554053041235
],
[
-0.06340157706002579,
1.224735863277014
],
[
-0.5382643095868677,
1.0133143141607128
],
[
-0.5975208094029268,
0.561438878658366
],
[
-0.766231190604878,
0.19526118857958627
],
[
0.14060021668138722,
0.4
],
[
0.05239183271831849,
-0.008592101868396151
],
[
0.36087228857768316,
-0.3470962748964499
],
[
0.7371834528946137,
-0.3046817236779634
],
[
1.0706889634601606,
-0.7207038198913537
],
[
1.487876633223481,
-0.37571084836184543
],
[
1.8726657414770358,
-0.16558447370672003
]
],
"Labels": [
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
0,
0,
0,
0
]
}
}