在 Python 中使用 LibSVM 预计算内核

Posted

技术标签:

【中文标题】在 Python 中使用 LibSVM 预计算内核【英文标题】:Precomputed Kernels with LibSVM in Python 【发布时间】:2011-01-29 06:55:54 【问题描述】:

我已经在网上搜索了大约 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 帮助和预计算内核示例。

【问题讨论】:

【参考方案1】:

首先,内核和 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 中预计算内核的文档其实还不错...

假设原始训练数据有三个四特征实例
并且测试数据有一个实例:

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

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

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

【讨论】:

【参考方案2】:

scikit-learn 在处理自定义内核时隐藏了 libsvm 的大部分细节。您可以将任意函数作为内核传递,它会为您计算 gram 矩阵,也可以传递内核的预先计算的 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

【讨论】:

【参考方案3】:

这是一个简单的 2 类 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 第二次进入 第三次进入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

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

【讨论】:

【参考方案4】:

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

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

【讨论】:

以上是关于在 Python 中使用 LibSVM 预计算内核的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 matlab 中使用带有 libsvm 的预计算内核

Libsvm 预计算内核

libsvm 交叉验证与 matlab 中的预计算内核

将置换后的数据放入 LibSVM 预计算内核

带有预计算内核的 libsvm:如何计算分类分数?

将预计算的 chi2 内核与 libsvm (matlab) 一起使用时结果不佳