Python中带LibSVM的预计算内核

Python中带LibSVM的预计算内核,python,machine-learning,libsvm,Python,Machine Learning,Libsvm,我在网上搜索了大约3个小时,但还没有找到解决办法。我想为libsvm提供一个预计算内核并对数据集进行分类,但是: 如何生成预计算内核?(例如,什么是基本的预计算内核?) 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

我在网上搜索了大约3个小时,但还没有找到解决办法。我想为libsvm提供一个预计算内核并对数据集进行分类,但是:

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

  • 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帮助和预计算内核示例。

首先,了解内核和支持向量机的一些背景知识

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

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

[1..N]中i的和(x_i*y_i),其中(x_1,…,x_N)(y_1,…,y_N)是向量

其次,尝试回答您的问题

关于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 假设原始训练数据有三个四个特征实例 测试数据有一个实例: 15 1:1 2:1 3:1 4:1 45 2:3 4:3 25 3:1 15 1:1 3:1 如果使用线性核,我们有以下内容 新的培训/测试集: 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 第二个示例中的每个向量都是内核矩阵中的一行。索引0处的值是ID值,它似乎只是一个顺序计数。第一个向量的索引1处的值是来自第一个示例的第一个向量的核函数的值(即
(1x1)+(1x1)+(1x1)+(1x1)+(1x1)+(1x1)=4
),第二个是第一个向量与第二个向量的核函数的值(即
(1x3)+(1x3)=6
)。在本例的其余部分,它将继续这样做。可以看出,内核矩阵是对称的,因为K(x,y)=K(y,x)

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

我认为libsvm的python绑定应该解决这个问题


有关更多信息,请参阅中的文档。

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


10:11:10 2:12 3:21
20:21:12 2:19 3:30
10:31:21 2:30 3:130

每行的第一个数字是它所属的类别。 每行上的下一个条目的格式为0:n,并且必须是连续的,即
第一次输入时0:1
第二次输入时0:2
第三次输入时0:3

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

svm_类型c_svc
预计算的内核类型
nr_第2类
总容积3
rho-1.53951
标签12
nr_sv 2 1
SV
0.4126650675419768 0:1
0.03174528241667363 0:3
-0.4444103499586504 0:2


需要注意的是,对于预计算的内核,不能像对所有其他内核一样忽略零项。必须明确包含它们。

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

对于第一个,语法是:

   >>> from scikits.learn import svm
   >>> clf = svm.SVC(kernel=my_kernel)
   >>> from scikits.learn import svm
   >>> clf = svm.SVC(kernel="precomputed")
其中my_kernel是您的内核函数,然后您可以调用clf.fit(X,y),它将为您计算内核矩阵。在第二种情况下,语法为:

   >>> from scikits.learn import svm
   >>> clf = svm.SVC(kernel=my_kernel)
   >>> from scikits.learn import svm
   >>> clf = svm.SVC(kernel="precomputed")
当您调用clf.fit(X,y)时,X必须是矩阵k(X,X),其中k是您的内核。有关更多详细信息,请参见此示例: