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

时间:2010-03-19 01:32:13

标签: python machine-learning libsvm

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

  • 如何生成预先计算的内核? (例如,Iris data的基本预先计算内核是什么?)

  • 在libsvm文档中,声明:

    对于预先计算的内核,每个实例的第一个元素必须是 身份证。例如,

            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帮助和预先计算的内核的示例都非常感激。

4 个答案:

答案 0 :(得分: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。

答案 1 :(得分: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

答案 2 :(得分: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 entry上的0:3

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

svm_type c_svc
kernel_type precomputed
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 :(得分:3)

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

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