在scikit-learn中,是否可以从使用预先计算的内核的SVM生成ROC曲线?

4
我正在使用这个例子从SVM分类结果创建ROC曲线:http://scikit-learn.org/0.13/auto_examples/plot_roc.html 然而,每个数据点实际上由4个长度为d的特征向量组成,使用一个不符合特定K(X,X)范例的自定义核函数进行组合。因此,我必须向scikit-learn提供一个预计算的核以进行分类。它看起来像这样:
K = numpy.zeros(shape = (n, n))

# w1 + w2 + w3 + w4 = 1.0

# v1: array, shape (n, d)
# w1: float in [0, 1)
chi = sklearn.metrics.pairwise.chi2_kernel(v1, v1)
mu = 1.0 / numpy.mean(chi)
K += w1 * numpy.exp(-mu * chi)

# v2: array, shape (n, d)
# w2: float in [0, 1)
chi = sklearn.metrics.pairwise.chi2_kernel(v2, v2)
mu = 1.0 / numpy.mean(chi)
K += w2 * numpy.exp(-mu * chi)

# v3: array, shape (n, d)
# w3: float in [0, 1)
chi = sklearn.metrics.pairwise.chi2_kernel(v3, v3)
mu = 1.0 / numpy.mean(chi)
K += w3 * numpy.exp(-mu * chi)

# v4: array, shape (n, d)
# w4: float in [0, 1)
chi = sklearn.metrics.pairwise.chi2_kernel(v4, v4)
mu = 1.0 / numpy.mean(chi)
K += w4 * numpy.exp(-mu * chi)

return K

从上面的链接中生成ROC图的主要障碍似乎是将数据分成两组,然后在测试集上调用predict_proba()的过程。 在scikit-learn中是否可以使用预计算的核来实现这一点?

1个回答

1
短期内的答案可能是“也许不需要”。 你是否尝试过像下面这样的方法? 根据http://scikit-learn.org/stable/modules/svm.html上的示例,你需要像这样做:
    import numpy as np

    from sklearn import svm
    X = np.array([[0, 0], [1, 1]])
    y = [0, 1]
    clf = svm.SVC(kernel='precomputed')

    # kernel computation
    K = numpy.zeros(shape = (n, n))

    # "At the moment, the kernel values between all training vectors 
    #  and the test vectors must be provided." 
    #  according to scikit learn web page. 
    #  -- This is the problem!
    # v1: array, shape (n, d)
    # w1: float in [0, 1)
    chi = sklearn.metrics.pairwise.chi2_kernel(v1, v1)
    mu = 1.0 / numpy.mean(chi)
    K += w1 * numpy.exp(-mu * chi)

    # v2: array, shape (n, d)
    # w2: float in [0, 1)
    chi = sklearn.metrics.pairwise.chi2_kernel(v2, v2)
    mu = 1.0 / numpy.mean(chi)
    K += w2 * numpy.exp(-mu * chi)

    # v3: array, shape (n, d)
    # w3: float in [0, 1)
    chi = sklearn.metrics.pairwise.chi2_kernel(v3, v3)
    mu = 1.0 / numpy.mean(chi)
    K += w3 * numpy.exp(-mu * chi)

    # v4: array, shape (n, d)
    # w4: float in [0, 1)
    chi = sklearn.metrics.pairwise.chi2_kernel(v4, v4)
    mu = 1.0 / numpy.mean(chi)
    K += w4 * numpy.exp(-mu * chi)

    # scikit-learn is a wrapper LIBSVM and looking at the LIBSVM Readme file
    # it seems you need kernel values for test data something like this:    

    Kt = numpy.zeros(shape = (nt, n))
    # t1: array, shape (nt, d)
    # w1: float in [0, 1)
    chi = sklearn.metrics.pairwise.chi2_kernel(t1, v1)
    mu = 1.0 / numpy.mean(chi)
    Kt += w1 * numpy.exp(-mu * chi)

    # v2: array, shape (n, d)
    # w2: float in [0, 1)
    chi = sklearn.metrics.pairwise.chi2_kernel(t2, v2)
    mu = 1.0 / numpy.mean(chi)
    Kt += w2 * numpy.exp(-mu * chi)

    # v3: array, shape (n, d)
    # w3: float in [0, 1)
    chi = sklearn.metrics.pairwise.chi2_kernel(t3, v3)
    mu = 1.0 / numpy.mean(chi)
    Kt += w3 * numpy.exp(-mu * chi)

    # v4: array, shape (n, d)
    # w4: float in [0, 1)
    chi = sklearn.metrics.pairwise.chi2_kernel(t4, v4)
    mu = 1.0 / numpy.mean(chi)
    Kt += w4 * numpy.exp(-mu * chi)

    clf.fit(K, y) 

    # predict on testing examples
    probas_ = clf.predict_proba(Kt)

从这里开始只需复制http://scikit-learn.org/0.13/auto_examples/plot_roc.html底部的内容。

没错,但问题是你使用了X_test,而由于每个数据点包含4个不同的n维特征向量组合在核函数中,我无法创建它。除非你提倡创建两个格拉姆矩阵,否则我不能将数据分成训练和测试,而scikit-learn实际上禁止这样做(“结果会出乎意料”)。 - Magsol
如果我理解正确的话,那么在predict_proba()中提供一个与训练SVM时使用的Gram矩阵K不同的Gram矩阵Kt是完全可以接受的吗?(但需要注意的是,在Kt中的测试向量需要与训练向量进行比较) - Magsol
如果它们是基于相同的核函数进行计算的,则其中一个必须是K(train,train),另一个则为K(test,train)。但上面的一些计算让我感到担忧,例如所有那些mu是否正确处理了。 - Bull
我没有意识到这点!我仅仅是假设——从scikit-learn的文档中也可以看出——你只能在相同的gram矩阵上进行测试/训练。至于计算,我使用的公式(来自Nilsback等人2008年)是:K(i, j) = SUM_f {w_f * exp {-mu_f * chi^2{x_f(i), x_f(j)} } }。 “f”范围为1-4,每个特征集合一个。严格来说,它是一个Mercer核或一组Mercer核的总和,这些核被加权(w_f)以总和为1。 mu_f是该特征集合中所有chi ^ 2距离的平均值的倒数。我在实现中有遗漏吗? - Magsol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接