public void multiclass_precomputed_matrix_smo()
{
#region doc_precomputed
// Let's say we have the following data to be classified
// into three possible classes. Those are the samples:
//
double[][] trainInputs =
{
// input output
new double[] { 0, 1, 1, 0 }, // 0
new double[] { 0, 1, 0, 0 }, // 0
new double[] { 0, 0, 1, 0 }, // 0
new double[] { 0, 1, 1, 0 }, // 0
new double[] { 0, 1, 0, 0 }, // 0
new double[] { 1, 0, 0, 0 }, // 1
new double[] { 1, 0, 0, 0 }, // 1
new double[] { 1, 0, 0, 1 }, // 1
new double[] { 0, 0, 0, 1 }, // 1
new double[] { 0, 0, 0, 1 }, // 1
new double[] { 1, 1, 1, 1 }, // 2
new double[] { 1, 0, 1, 1 }, // 2
new double[] { 1, 1, 0, 1 }, // 2
new double[] { 0, 1, 1, 1 }, // 2
new double[] { 1, 1, 1, 1 }, // 2
};
int[] trainOutputs = // those are the training set class labels
{
0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
2, 2, 2, 2, 2,
};
// Let's chose a kernel function
Polynomial kernel = new Polynomial(2);
// Get the kernel matrix for the training set
double[][] K = kernel.ToJagged(trainInputs);
// Create a pre-computed kernel
var pre = new Precomputed(K);
// Create a one-vs-one learning algorithm using SMO
var teacher = new MulticlassSupportVectorLearning<Precomputed, int>()
{
Learner = (p) => new SequentialMinimalOptimization<Precomputed, int>()
{
Kernel = pre
}
};
#if DEBUG
teacher.ParallelOptions.MaxDegreeOfParallelism = 1;
#endif
// Learn a machine
var machine = teacher.Learn(pre.Indices, trainOutputs);
// Compute the machine's prediction for the training set
int[] trainPrediction = machine.Decide(pre.Indices);
// Evaluate prediction error for the training set using mean accuracy (mAcc)
double trainingError = new ZeroOneLoss(trainOutputs).Loss(trainPrediction);
// Now let's compute the machine's prediction for a test set
double[][] testInputs = // test-set inputs
{
// input output
new double[] { 0, 1, 1, 0 }, // 0
new double[] { 0, 1, 0, 0 }, // 0
new double[] { 0, 0, 0, 1 }, // 1
new double[] { 1, 1, 1, 1 }, // 2
};
int[] testOutputs = // those are the test set class labels
{
0, 0, 1, 2,
};
// Compute precomputed matrix between train and testing
pre.Values = kernel.ToJagged2(trainInputs, testInputs);
// Update the kernel
machine.Kernel = pre;
// Compute the machine's prediction for the test set
int[] testPrediction = machine.Decide(pre.Indices);
// Evaluate prediction error for the training set using mean accuracy (mAcc)
double testError = new ZeroOneLoss(testOutputs).Loss(testPrediction);
#endregion
Assert.AreEqual(0, trainingError);
Assert.AreEqual(0, testError);
// Create a one-vs-one learning algorithm using SMO
var teacher2 = new MulticlassSupportVectorLearning<Polynomial>()
{
Learner = (p) => new SequentialMinimalOptimization<Polynomial>()
{
Kernel = kernel
}
};
#if DEBUG
teacher.ParallelOptions.MaxDegreeOfParallelism = 1;
#endif
// Learn a machine
var expected = teacher2.Learn(trainInputs, trainOutputs);
Assert.AreEqual(4, expected.NumberOfInputs);
Assert.AreEqual(3, expected.NumberOfOutputs);
Assert.AreEqual(0, machine.NumberOfInputs);
Assert.AreEqual(3, machine.NumberOfOutputs);
var machines = Enumerable.Zip(machine, expected, (a,b) => Tuple.Create(a.Value, b.Value));
foreach (var pair in machines)
{
var a = pair.Item1;
var e = pair.Item2;
Assert.AreEqual(0, a.NumberOfInputs);
Assert.AreEqual(2, a.NumberOfOutputs);
Assert.AreEqual(4, e.NumberOfInputs);
Assert.AreEqual(2, e.NumberOfOutputs);
Assert.IsTrue(a.Weights.IsEqual(e.Weights));
}
}