Я разрабатываю проект, в котором мне нужно распознавать жесты. После поиска способа сделать это я наткнулся на динамическую деформацию времени. Чтобы попробовать эту идею, а так как мой проект на C#, я решил попробовать Accord.NET. Прежде чем я попробовал это в своем проекте, я создал чистый проект и изменил пример в документации Accord.NET, который можно найти здесь:
http://accord-framework.net/docs/html/T_Accord_Statistics_Kernels_DynamicTimeWarping.htm
Итак, прямо сейчас я пытаюсь обучить свой алгоритм набору обучающих данных (состоящих из жестов пролистывания вправо, пролистывания влево и двойного касания), а затем использовать те же примеры в обучающих данных, чтобы увидеть, Алгоритм определяет правильный жест. Значения являются просто примером, а не реальной сделкой.
В документации не очень ясно, как это сделать, поскольку метод Decide, использованный в примере, возвращает только логическое значение. Я искал в документации способ определить правильный класс, но безрезультатно.
Единственное, что я нашел, это следующую строку, но она возвращает целочисленное значение 0 или 1 вместо логического значения:
var res1 = ((IClassifier)svm.ToMulticlass()).Решить(последовательности[0]);
Может ли кто-нибудь указать мне в правильном направлении, как правильно идентифицировать жест? Это моя первая попытка машинного обучения и Accord.NET, так что все это для меня абсолютно ново. Пример кода можно найти ниже.
namespace DynamicTimeWarpingExample
{
public class Program
{
public static void Main(string[] args)
{
double[][][] sequences =
{
new double[][] // Swipe left
{
new double[] { 1, 1, 1 },
new double[] { 1, 2, 1 },
new double[] { 1, 2, 2 },
new double[] { 2, 2, 2 },
},
new double[][] // Swipe right
{
new double[] { 1, 10, 6 },
new double[] { 1, 5, 6 },
new double[] { 6, 7, 1 },
},
new double[][] // Double tap
{
new double[] { 8, 2, 5 },
new double[] { 1, 50, 4 },
}
};
int[] outputs =
{
0, // Swipe left
1, // Swipe right
2 // Double tap
};
var smo = new SequentialMinimalOptimization<DynamicTimeWarping, double[][]>()
{
Complexity = 1.5,
Kernel = new DynamicTimeWarping(alpha: 1, degree: 1)
};
var svm = smo.Learn(sequences, outputs);
bool[] predicted = svm.Decide(sequences);
double error = new ZeroOneLoss(outputs).Loss(predicted); // error will be 0.0
var res1 = ((IClassifier<double[][], int>)svm.ToMulticlass()).Decide(sequences[0]); // returns 0
var res2 = ((IClassifier<double[][], int>)svm.ToMulticlass()).Decide(sequences[1]); // returns 1
var res3 = ((IClassifier<double[][], int>)svm.ToMulticlass()).Decide(sequences[2]); // returns 1
}
}
}
***************** Новая версия *****************
public static void Main(string[] args)
{
double[][][] sequences =
{
new double[][] // Swipe left
{
new double[] { 1, 1, 1 },
new double[] { 1, 2, 1 },
new double[] { 1, 2, 2 },
new double[] { 2, 2, 2 },
},
new double[][] // Swipe right
{
new double[] { 1, 10, 6 },
new double[] { 1, 5, 6 },
new double[] { 6, 7, 1 },
},
new double[][] // Double tap
{
new double[] { 8, 2, 5 },
new double[] { 1, 50, 4 },
}
};
int[] outputs =
{
0, // Swipe left
1, // Swipe right
2 // Double tap
};
var teacher = new MulticlassSupportVectorLearning<DynamicTimeWarping, double[][]>()
{
// Configure the learning algorithm to use SMO to train the
// underlying SVMs in each of the binary class subproblems.
Learner = (param) => new SequentialMinimalOptimization<DynamicTimeWarping, double[][]>
{
Complexity = 1.5,
Kernel = new DynamicTimeWarping(alpha: 1, degree: 1),
//UseKernelEstimation = true
}
};
// Learn a machine
var machine = teacher.Learn(sequences, outputs);
// Create the multi-class learning algorithm for the machine
var calibration = new MulticlassSupportVectorLearning<DynamicTimeWarping, double[][]>()
{
Model = machine, // We will start with an existing machine
// Configure the learning algorithm to use Platt's calibration
Learner = (param) => new ProbabilisticOutputCalibration<DynamicTimeWarping, double[][]>()
{
Model = param.Model // Start with an existing machine
}
};
// Configure parallel execution options
calibration.ParallelOptions.MaxDegreeOfParallelism = 1;
// Learn a machine
calibration.Learn(sequences, outputs);
double decision1, decision2, decision3, decision4, decision5, decision6;
var res1 = machine.Probability(sequences[0], out decision1); // decision 0 - Probability 0.78698604216159851 - Score 1
var res2 = machine.Probability(sequences[1], out decision2); // decision 1 - Probability 0.67246889837875257 - Score 1
var res3 = machine.Probability(sequences[2], out decision3); // decision 2 - Probability 0.78698604216159851 - Score 1
var newGesture1 = new double[][]
{
new double[] { 1, 1, 1 },
new double[] { 1, 2, 1 },
new double[] { 1, 2, 2 },
new double[] { 2, 2, 2 },
};
var newGesture2 = new double[][]
{
new double[] { 1, 10, 6 },
new double[] { 1, 5, 6 },
new double[] { 6, 7, 1 },
};
var newGesture3 = new double[][]
{
new double[] { 8, 2, 5 },
new double[] { 1, 50, 4 },
};
var res5 = machine.Score(newGesture1, out decision5); // decision 0 - Probability 0.35577588944247057 - Score 0.051251948605637254
var res6 = machine.Score(newGesture2, out decision6); // decision 1 - Probability 0.40733908994050544 - Score 0.19912250476931792
var res4 = machine.Score(newGesture3, out decision4); // decision 2 - Probability 0.71853321355842836 - Score 0.816934034911964
}