在 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.53951 标签 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 预计算内核的主要内容,如果未能解决你的问题,请参考以下文章