【问题标题】:Getting the class label using DynamicTimeWarping using Accord.NET使用 Accord.NET 使用 DynamicTimeWarping 获取类标签
【发布时间】:2017-09-01 13:34:19
【问题描述】:

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

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

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

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

我发现的唯一内容是以下行,但它返回的是 0 或 1 的 int 值,而不是布尔值:

var res1 = ((IClassifier)svm.ToMulticlass()).Decide(sequences[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
}

【问题讨论】:

标签: machine-learning accord.net


【解决方案1】:

问题是您正在为实际上涉及多个类的问题创建一个二元分类器。

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

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

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

您可能希望将这个二元学习问题包装成一个多类学习使用

// 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);

【讨论】:

  • 感谢 wou Cesar,Accord.Net 的创建者本人的回应 :) 这再合适不过了。这周我会试一试,如果可行,将其标记为已接受的答案。
  • 这是正确的解决方案。必须更改的另一行是: bool[] predicted = svm.Decide(sequences);对此:int[] 预测 = svm.Decide(sequences);
  • 您好,Ceaser,只是一个简单的问题。假设我有一个触摸板,我想拒绝意外的手势。有没有办法知道一个决定的“确定性”?例如,在 kNN 分类器中,可以通过在 Compute 方法上传递一个变量来获得它: var computedExerciseClass = knn.Compute(inputs, out certainty);如果确定性高于某个阈值,我可以使用类似的方法接受 Decide 方法的结果。
  • 您可以使用 SVM 的 .Probability 或 .Score 方法。如果您使用 SequentialMinimalOptimization,您必须先使用 ProbabilisticOutputCalibration 校准机器(请参阅链接页面中的第二个示例)。之后,您将能够使用方法Probability(input_vector, out decided_class) 获得决策和该决策的概率。
  • 由于响应太大,我将不得不在几篇文章中打破它。我已尝试在您的文档页面上使用第二个示例,但如果我使用“UseKernelEstimation = true”,则会收到异常“内核类型不支持估计”。在 var machine = teacher.Learn(序列,输出)上;我正在使用 DynamicTimeWarping 内核。如果我删除该行,异常就消失了,问题是我会得到一些奇怪的结果,我认为这些结果可能与此无关。为了帮助我更好地解释发生了什么,我编辑了我的原始帖子并在其底部添加了新版本的代码。
猜你喜欢
  • 2017-10-10
  • 1970-01-01
  • 1970-01-01
  • 2019-11-14
  • 1970-01-01
  • 1970-01-01
  • 2020-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多