使用 Accord.NET 使用 DynamicTimeWarping 获取 class 标签

Getting the class label using DynamicTimeWarping using Accord.NET

我正在开发一个需要进行手势识别的项目。 在寻找一种方法来做到这一点后,我遇到了动态时间扭曲。 为了尝试这个想法,并且由于我的项目是在 C# 中,所以我决定尝试 Accord.NET。 在我的项目中尝试这个之前,我创建了一个干净的项目并修改了 Accord.NET 文档中的示例,可以在这里找到:

http://accord-framework.net/docs/html/T_Accord_Statistics_Kernels_DynamicTimeWarping.htm

所以,我现在正在尝试的是用一组学习数据(由手势向右滑动、向左滑动和双击组成)来训练我的算法,然后在学习中使用相同的示例数据以查看算法是否识别出正确的手势。这些值只是一个例子,不是真正的交易。

关于如何执行此操作的文档不是很清楚,因为示例中使用的 Decide 方法仅 returns 一个布尔值。 我在文档中搜索了一种方法来识别正确的 class 但无济于事。

我唯一发现的是下面这行,但它 returns 是 0 或 1 的 int 值,而不是布尔值:

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
}

问题是您正在为实际上涉及多个 classes 的问题创建二进制 classifier。

在你的情况下,而不是做:

var smo = new SequentialMinimalOptimization<DynamicTimeWarping, double[][]>()      
{
    Complexity = 1.5,
    Kernel = new DynamicTimeWarping(alpha: 1, degree: 1)
};

var svm = smo.Learn(sequences, outputs);

您可能希望使用

将这个二元学习问题包装成一个多class 学习
// Create the multi-class learning algorithm for the machine
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)
    };
}

// Learn a  machine
var svm = teacher.Learn(inputs, outputs);