【问题标题】:Precomputed Kernels with LibSVM in Python在 Python 中使用 LibSVM 预计算内核
【发布时间】: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 帮助和预计算内核示例。

【问题讨论】:

    标签: python machine-learning 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 上的文档。

          【讨论】:

            猜你喜欢
            • 2012-06-14
            • 2011-12-04
            • 2014-04-11
            • 2012-04-11
            • 2014-04-28
            • 2013-06-24
            • 2014-03-16
            • 2014-06-21
            • 2011-11-02
            相关资源
            最近更新 更多