使用Python中的LibSVM预先计算的内核

问题描述 投票:9回答:4

我一直在网上搜索约3个小时,但我找不到解决方案了。我想给libsvm提供一个预先计算的内核并对数据集进行分类,但是:

  • 如何生成预先计算的内核? (例如,Iris data的基本预先计算内核是什么?)
  • 在libsvm文档中,声明: 对于预先计算的内核,每个实例的第一个元素必须是ID。例如, samples = [[1, 0, 0, 0, 0], [2, 0, 1, 0, 1], [3, 0, 0, 1, 1], [4, 0, 1, 1, 2]] problem = svm_problem(labels, samples) param = svm_parameter(kernel_type=PRECOMPUTED)

我所说?没有进一步的细节。我可以按顺序分配ID吗?

任何libsvm帮助和预先计算的内核的例子都非常感激。

python machine-learning libsvm
4个回答
16
投票

首先,内核和SVM的一些背景......

如果要为n向量(任何维度)预先计算内核,需要做的是计算每对示例之间的内核函数。内核函数采用两个向量并给出一个标量,因此您可以将预先计算的内核视为标量的nxn矩阵。它通常被称为核矩阵,或者有时称为Gram矩阵。

有许多不同的内核,最简单的是线性内核(也称为点积):

sum(x_i * y_i) for i in [1..N] where (x_1,...,x_N) (y_1,..,y_N) are vectors

其次,试着回答你的问题......

关于libsvm中预先计算的内核的文档实际上非常好......

Assume the original training data has three four-feature instances 
and testing data has one instance:

15  1:1 2:1 3:1 4:1
45      2:3     4:3
25          3:1
15  1:1     3:1

If the linear kernel is used, we have the following 
new training/testing sets:

15  0:1 1:4 2:6  3:1
45  0:2 1:6 2:18 3:0 
25  0:3 1:1 2:0  3:1

15  0:? 1:2 2:0  3:1

第二个例子中的每个向量是内核矩阵中的一行。索引零处的值是ID值,它似乎只是一个顺序计数。第一个向量的索引1处的值是来自第一个示例的第一个向量的核函数的值(即(1x1)+(1x1)+(1x1)+(1x1) = 4),第二个是第一个向量与第二个向量的核函数的值(即(1x3)+(1x3)=6) )。对于该示例的其余部分,它也是如此。你可以看到核矩阵是对称的,因为它应该是,因为K(x,y)= K(y,x)。

值得指出的是,第一组向量以稀疏格式表示(即缺失值为零),但核矩阵不是也不应该是稀疏的。我不知道为什么会这样,它似乎只是一个libsvm的东西。


6
投票

scikit-learn在处理自定义内核时隐藏了libsvm的大部分细节。您可以将任意函数作为内核传递,它将为您计算克矩阵或传递内核的预先计算的Gram矩阵。

对于第一个,语法是:

   >>> from scikits.learn import svm
   >>> clf = svm.SVC(kernel=my_kernel)

其中my_kernel是你的内核函数,然后你可以调用clf.fit(X,y),它会为你计算内核矩阵。在第二种情况下,语法是:

   >>> from scikits.learn import svm
   >>> clf = svm.SVC(kernel="precomputed")

当你调用clf.fit(X,y)时,X必须是矩阵k(X,X),其中k是你的内核。有关更多详细信息,请参阅此示例:

http://scikit-learn.org/stable/auto_examples/svm/plot_custom_kernel.html


4
投票

这是一个简单的两个3类矢量自定义内核输入文件,可以正常工作。我会解释这些部分(虽然你也应该看到StompChicken的答案):

1 0:1 1:10 2:12 3:21
2 0:2 1:12 2:19 3:30
1 0:3 1:21 2:30 3:130

每行的第一个数字是它所属的类别。每行的下一个条目的形式为0:n,它必须是顺序的,即 第一次进入时0:1 第二次进入时0:2 在thrid条目上0:3

一个可能的原因是libsvm返回与输出文件中的向量一致的值alpha_i,但是对于预先计算的内核,不显示向量(这可能是真正巨大的)而是显示与该向量一起使用的索引0:n使您的输出更容易与您的输入相匹配。特别是因为输出的顺序不同,所以按类别分组。因此,在读取输入文件时能够将libsvm的输出与您自己的输入匹配以获得那些0:n值非常有用。在这里你可以看到输出

svm_type c_svc kernel_type预先计算好 nr_class 2 total_sv 3 rho -1.53​​951 标签1 2 nr_sv 2 1 SV 0.4126650675419768 0:1 0.03174528241667363 0:3 -0.4444103499586504 0:2

重要的是要注意,对于预先计算的内核,您不能像所有其他内核一样省略零条目。必须明确包括它们。


3
投票

我相信scikit-learn的libSVM的python绑定应该解决这个问题。

有关更多信息,请参阅http://scikit-learn.sourceforge.net/modules/svm.html#kernel-functions上的文档。

© www.soinside.com 2019 - 2024. All rights reserved.