Scikit学习SVC decision_function并做出预测

Pet*_*eng 54 python numpy svm scikit-learn

我试图理解decision_function和predict之间的关系,它们是SVC的实例方法(http://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html).到目前为止,我已经收集到决策函数返回类之间的成对分数.我的印象是预测选择最大化其成对分数的类,但我测试了它并得到了不同的结果.这是我用来尝试理解两者之间关系的代码.首先我生成了成对分数矩阵,然后我打印出了具有最大配对分数的类,该分数与clf.predict预测的类不同.

        result = clf.decision_function(vector)[0]
        counter = 0
        num_classes = len(clf.classes_)
        pairwise_scores = np.zeros((num_classes, num_classes))
        for r in xrange(num_classes):
            for j in xrange(r + 1, num_classes):
                pairwise_scores[r][j] = result[counter]
                pairwise_scores[j][r] = -result[counter]
                counter += 1

        index = np.argmax(pairwise_scores)
        class = index_star / num_classes
        print class
        print clf.predict(vector)[0]
Run Code Online (Sandbox Code Playgroud)

有谁知道这些预测和决策功能之间的关系?

Mar*_*hen 28

我不完全理解您的代码,但让我们通过您引用的文档页面的示例:

import numpy as np
X = np.array([[-1, -1], [-2, -1], [1, 1], [2, 1]])
y = np.array([1, 1, 2, 2])
from sklearn.svm import SVC
clf = SVC()
clf.fit(X, y) 
Run Code Online (Sandbox Code Playgroud)

现在让我们将决策函数和预测应用于样本:

clf.decision_function(X)
clf.predict(X)
Run Code Online (Sandbox Code Playgroud)

我们得到的输出是:

array([[-1.00052254],
       [-1.00006594],
       [ 1.00029424],
       [ 1.00029424]])
array([1, 1, 2, 2])
Run Code Online (Sandbox Code Playgroud)

这很容易理解:desion函数告诉我们分类器生成的超平面的哪一侧(以及我们离它多远).然后,基于该信息,估计器用相应的标签标记示例.

  • 它很容易解释,因为这是一个二进制的例子.在多类情况下,`SVC.decision_function`变得更加复杂. (15认同)

bco*_*rso 16

对于那些感兴趣的人,我将发布一个predict从C++(这里)翻译成python 的函数的快速示例:

# I've only implemented the linear and rbf kernels
def kernel(params, sv, X):
    if params.kernel == 'linear':
        return [np.dot(vi, X) for vi in sv]
    elif params.kernel == 'rbf':
        return [math.exp(-params.gamma * np.dot(vi - X, vi - X)) for vi in sv]

# This replicates clf.decision_function(X)
def decision_function(params, sv, nv, a, b, X):
    # calculate the kernels
    k = kernel(params, sv, X)

    # define the start and end index for support vectors for each class
    start = [sum(nv[:i]) for i in range(len(nv))]
    end = [start[i] + nv[i] for i in range(len(nv))]

    # calculate: sum(a_p * k(x_p, x)) between every 2 classes
    c = [ sum(a[ i ][p] * k[p] for p in range(start[j], end[j])) +
          sum(a[j-1][p] * k[p] for p in range(start[i], end[i]))
                for i in range(len(nv)) for j in range(i+1,len(nv))]

    # add the intercept
    return [sum(x) for x in zip(c, b)]

# This replicates clf.predict(X)
def predict(params, sv, nv, a, b, cs, X):
    ''' params = model parameters
        sv = support vectors
        nv = # of support vectors per class
        a  = dual coefficients
        b  = intercepts 
        cs = list of class names
        X  = feature to predict       
    '''
    decision = decision_function(params, sv, nv, a, b, X)
    votes = [(i if decision[p] > 0 else j) for p,(i,j) in enumerate((i,j) 
                                           for i in range(len(cs))
                                           for j in range(i+1,len(cs)))]

    return cs[max(set(votes), key=votes.count)]
Run Code Online (Sandbox Code Playgroud)

有许多输入参数predictdecision_function,但请注意,这些都是在调用时由模型内部使用predict(X).实际上,在拟合之后,模型内的所有参数都可以访问:

# Create model
clf = svm.SVC(gamma=0.001, C=100.)

# Fit model using features, X, and labels, Y.
clf.fit(X, y)

# Get parameters from model
params = clf.get_params()
sv = clf.support_vectors
nv = clf.n_support_
a  = clf.dual_coef_
b  = clf._intercept_
cs = clf.classes_

# Use the functions to predict
print(predict(params, sv, nv, a, b, cs, X))

# Compare with the builtin predict
print(clf.predict(X))
Run Code Online (Sandbox Code Playgroud)


小智 14

当您调用时decision_function(),您将获得每个成对分类器的输出(总共n*(n-1)/ 2个数字).参见"用于模式分类的支持向量机"的第127和128页.

每个分类器对正确答案是什么进行投票(基于该分类器输出的符号); predict()返回投票最多的班级.

  • 谢谢罗曼!我对此进行了测试,在大多数情况下,预测似乎是选择获得最多选票的班级。我最初做错的是选择了累积边际分数最好的班级。 (2认同)

ser*_*inc 14

对于datascience.sx中的多类one-vs-one场景,有一个非常好的问答:

我有一个多类SVM分类器,标签为'A','B','C','D'.

这是我正在运行的代码:

>>>print clf.predict([predict_this])
['A']
>>>print clf.decision_function([predict_this])
[[ 185.23220833   43.62763596  180.83305074  -93.58628288   62.51448055  173.43335293]]
Run Code Online (Sandbox Code Playgroud)

如何使用决策函数的输出以最高概率预测类(A/B/C/D),如果可能,它的值是多少?我访问了/sf/answers/1408022101/,但是它用于二进制分类器,找不到一个很好的资源,它解释了具有形状ovo(one-vs-one)的多类分类器的decision_function输出.

编辑:

以上示例适用于"A"类.对于另一个输入,分类器预测'C'并在decision_function中给出以下结果

[[ 96.42193513 -11.13296606 111.47424538 -88.5356536 44.29272494 141.0069203 ]]
Run Code Online (Sandbox Code Playgroud)

对于分类器预测为"C"的另一个不同输入,给出了来自decision_function的以下结果,

[[ 290.54180354 -133.93467605  116.37068951 -392.32251314 -130.84421412   284.87653043]]
Run Code Online (Sandbox Code Playgroud)

如果它是ovr(一对一休息),通过选择具有更高值的那个将变得更容易,但是在卵内(一对一)(n * (n - 1)) / 2,结果列表中有值.

如何推断基于决策函数选择哪个类?

回答

您的链接有足够的资源,所以让我们通过:

当您调用decision_function()时,您将获得每个成对分类器的输出(总共n*(n-1)/ 2个数字).参见"用于模式分类的支持向量机"的第127和128页.

单击"第127和128页"链接(此处未显示,但在Stackoverflow答案中).你应该看到:

在此输入图像描述

  • Python的SVM实现使用one-vs-one.这正是本书所谈论的内容.
  • 对于每个成对比较,我们测量决策函数
  • 决策函数只是常规二进制SVM决策边界

这与你的问题有什么关系?

  • clf.decision_function()会为每个成对比较提供$ D $
  • 获得最多选票的班级获胜

例如,

[[96.42193513 -11.13296606 111.47424538 -88.5356536 44.29272494 141.0069203]]

正在比较:

[AB,AC,AD,BC,BD,CD]

我们用标志标记每一个.我们得到:

[A,C,A,C,B,C]

例如,96.42193513是正的,因此A是AB的标签.

现在我们有三个C,C将是你的预测.如果您对其他两个示例重复我的过程,您将获得Python的预测.试试吧!