我在研究中使用了Accord.net。我的输入是一组大小可变的向量序列,因此我使用DynamicTimeWarping作为MulticlassSupportVectorMachine的核函数。
IKernel kernel = new DynamicTimeWarping(dimension); var machine = new MulticlassSupportVectorMachine(0, kernel, 2); // 为机器创建多类学习算法 var teacher = new MulticlassSupportVectorLearning(machine, inputs.ToArray(), outputs.ToArray()); // 配置学习算法使用SMO来训练 // 每个二元类子问题中的底层SVMs。 teacher.Algorithm = (svm, classInputs, classOutputs, i, j) => new SequentialMinimalOptimization(svm, classInputs, classOutputs) { Complexity = 1.5 }; // 运行学习算法 double error = teacher.Run();
输入和输出看起来像这样:
?inputs.ToArray(){double[22][]} [0]: {double[10656]} [1]: {double[9360]} [2]: {double[9216]} [3]: {double[9864]} [4]: {double[10296]} [5]: {double[10152]} [6]: {double[9936]} [7]: {double[9216]} [8]: {double[10944]} [9]: {double[9504]} [10]: {double[11880]} [11]: {double[22752]} [12]: {double[23688]} [13]: {double[29880]} [14]: {double[32328]} [15]: {double[37224]} [16]: {double[30024]} [17]: {double[27288]} [18]: {double[26064]} [19]: {double[22032]} [20]: {double[21672]} [21]: {double[22680]}?inputs[0]{double[10656]} [0]: 7.6413027545068823 [1]: -61.607203372756942 [2]: 7.7375128997886513 [3]: -25.704529598536471 [4]: -0.4124927191531238 [5]: 9.6820255661415011 [6]: 3.0674374003781861 [7]: 4.6364653722537668 [8]: 3.3559314278499177 [9]: 0.93969394152714925 [10]: -6.3800159552064146 [11]: 1.4239779356781062 [12]: -2.25349154655782 [13]: -1.5457194406236221 [14]: -0.7612541874802764 [15]: -3.3364791133985348 [16]: 0.67816801816804861 [17]: -3.4117217877592343 [18]: 1.5785492543017225 [19]: 0.31091690789261689 [20]: -2.5526646739208712 [21]: -1.0550268575680164 [22]: -0.9598271201088191 [23]: -1.1797916101998056 [24]: 0.56157735657438412 [25]: -0.16309890421998655 [26]: 0.29765136770064271 [27]: -0.35684735108472643 [28]: -0.52382117896006564 [29]: -0.052087258844925849 [30]: -0.45363669419489172 [31]: -0.16216259086709361 [32]: -0.25958480481802632 [33]: 0.081248839173330589 [34]: -0.019783293216956807 [35]: 0.14139773316964666 [36]: 0.088466551256948273 [37]: -0.019528343614348152 [38]: 0.087073343332064762 [39]: 0.048432068369313144 [40]: -0.0069171431858626713 [41]: -0.0095272766950126042 [42]: 0.016639887499893875 [43]: -0.009108847017642599 [44]: 0.0017424263597747487 [45]: 0.0042160613810267641 [46]: -0.002793626734247919 [47]: 0.00092130299196750763 [48]: 0.0024488939699103319 [49]: 0.0021684669072286468 [50]: 0.000000000000010673294119695543 [51]: -0.000000000000014072530108313123 [52]: 0.000000000000000069063495074940116 [53]: 8.73342598612937E-17 [54]: 0.000000000000000030048643853749834 [55]: -6.95380121971215E-17 [56]: 0.00000000000000010093927767292201 [57]: 0.000000000000000046158366228268829 [58]: 0.000000000000000039070100378142324 [59]: 0.00000000000000010492059540665321 [60]: -0.000000000000000014254591247067773 [61]: -0.0000000000000000015902697756329909 [62]: 0.0000000000000000017024249964704589 [63]: 0.0000000000000000010277956708903136 [64]: 3.5875442986020568E-28 [65]: -2.215158998843094E-31 [66]: 1.041379591973569E-31 [67]: -4.3897715186113276E-31 [68]: 4.248432864156974E-34 [69]: 4.3718530099471368E-47 [70]: 1.4551856970655856E-50 [71]: 0.0 [72]: 11.031182384920639 [73]: -63.434486026723626 [74]: 1.7731679007864651 [75]: -23.968196466652273 [76]: 2.2753564408666507 [77]: 9.5492641110324534 [78]: 3.4465209481281054 [79]: 4.7979691924966161 [80]: 2.0147801482840508 [81]: 1.1858337013571998 [82]: -4.607944757859336 [83]: 0.75637871318664485 [84]: -3.8397810581420115 [85]: -2.1276086210477514 [86]: -0.4060620782117581 [87]: -2.9313848427777227 [88]: 0.052605148372525556 [89]: -1.5948208186863277 [90]: 0.36061926783486992 [91]: -0.12623742266247567 [92]: -1.1889713301479885 [93]: -0.33299631607409635 [94]: -0.00912650336180437 [95]: -0.52707950657313729 [96]: 0.52115933681848092 [97]: 0.46870463636533816 [98]: -0.18482093982467213 [99]: -0.49350561475314514 < More... (The first 100 of 10656 items were displayed.) >?outputsCount = 22 [0]: 0 [1]: 0 [2]: 0 [3]: 0 [4]: 0 [5]: 0 [6]: 0 [7]: 0 [8]: 0 [9]: 0 [10]: 0 [11]: 1 [12]: 1 [13]: 1 [14]: 1 [15]: 1 [16]: 1 [17]: 1 [18]: 1 [19]: 1 [20]: 1 [21]: 1
使用这段代码,返回的错误率为0.5。
问题:
-
这是否意味着我的训练数据有问题?
-
对于我的大小可变的序列,还有其他可以使用的核函数吗?
谢谢。
回答:
我将展示如何使用结合高斯核的动态时间规整核来进行序列分类,这应该可以得到更好的结果。
序列分类问题的首要任务是正确组织序列以供学习算法使用。每个序列可以由多元向量组成,因此必须相应地组织输入数据(这是使用序列机器时最可能出现错误的来源,请花点时间理解以下代码的作用)。
// 假设你有由多元观测值组成的序列,这些序列可以是任意长度的。另一方面,// 每个观测值具有固定的、有限的维数。在这个例子中,我们有3维观测值的序列。// 每个序列可以有任意长度,但每个观测值始终具有3个长度:double[][][] sequences ={ new double[][] // 第一序列 { new double[] { 1, 1, 1 }, // 第一序列的第一个观测值 new double[] { 1, 2, 1 }, // 第一序列的第二个观测值 new double[] { 1, 4, 2 }, // 第一序列的第三个观测值 new double[] { 2, 2, 2 }, // 第一序列的第四个观测值 }, new double[][] // 第二序列(注意这个序列长度不同) { new double[] { 1, 1, 1 }, // 第二序列的第一个观测值 new double[] { 1, 5, 6 }, // 第二序列的第二个观测值 new double[] { 2, 7, 1 }, // 第二序列的第三个观测值 }, new double[][] // 第三序列 { new double[] { 8, 2, 1 }, // 第三序列的第一个观测值 }, new double[][] // 第四序列 { new double[] { 8, 2, 5 }, // 第四序列的第一个观测值 new double[] { 1, 5, 4 }, // 第四序列的第二个观测值 }};
这些是我们的输入序列。现在,由于我们试图进行分类问题,我们必须为每个序列关联一个输出类标签。如果我们有4个序列,那么我们将需要4个类标签:
// 现在,我们还将为每个序列关联不同的类标签。我们将为以{1,1,1}开头的序列分配-1,// 对于不以{1,1,1}开头的序列分配+1:int[] outputs ={ -1,-1, // 前两个序列属于类别-1(那些以{1,1,1}开头) 1, 1, // 后两个序列属于类别+1(不以{1,1,1}开头)};
现在问题已经定义好了,需要稍作转换,以便它们可以被DTW-SVMs处理:
// 此时,我们需要将输入序列从double[][][]“平展”为double[][],以便SVMs可以正确理解。问题是,// 通常SVMs期望数据由固定长度的输入向量和关联的类标签组成。但在这种情况下,我们将提供// 任意长度的输入向量序列和与每个序列关联的类标签,而不是每个向量。double[][] inputs = new double[sequences.Length][];for (int i = 0; i < sequences.Length; i++) inputs[i] = Matrix.Concatenate(sequences[i]);// 现在我们需要设置动态时间规整核。我们需要告知每个// 任意长度序列中包含的固定长度观测值的长度:// var kernel = new Gaussian<DynamicTimeWarping>(new DynamicTimeWarping(length: 3));// 现在我们可以创建机器。当使用可变长度// 核时,我们需要将输入长度设为零:var svm = new KernelSupportVectorMachine(kernel, inputs: 0);// 创建顺序最小优化学习算法var smo = new SequentialMinimalOptimization(svm, inputs, outputs);// 开始学习它!double error = smo.Run(); // 错误率将为0.0
在这一点之后,机器应该已经创建好了。参数C应该已经被机器自动猜测,但你可以在之后进行微调,以尝试提高机器的泛化性能。在任何情况下,
// 此时,我们应该已经获得了一个有用的机器。让我们// 看看它是否能理解一些它之前没见过的例子:double[][] a = { new double[] { 1, 1, 1 }, new double[] { 7, 2, 5 }, new double[] { 2, 5, 1 },};double[][] b ={ new double[] { 7, 5, 2 }, new double[] { 4, 2, 5 }, new double[] { 1, 1, 1 },};// 按照上述逻辑,序列(a)应被// 分类为-1,序列(b)应被分类为+1。int resultA = System.Math.Sign(svm.Compute(Matrix.Concatenate(a))); // -1int resultB = System.Math.Sign(svm.Compute(Matrix.Concatenate(b))); // +1