numpy Scikit学习SVC decision_function和predict

u91tlkcl  于 2023-10-19  发布在  其他
关注(0)|答案(6)|浏览(106)

我试图理解decision_function和predict之间的关系,它们是SVC(http://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html)的示例方法。到目前为止,我已经知道decision函数返回类之间的两两得分。我的印象是预测选择最大化其成对得分的类,但我测试了一下,得到了不同的结果。这是我用来尝试理解两者之间关系的代码。首先,我生成了成对得分矩阵,然后打印出具有最大成对得分的类,它与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]

有谁知道predict和decision_function之间的关系吗?

nfzehxib

nfzehxib1#

我不完全理解你的代码,但让我们来看看你引用的文档页面中的示例:

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)

现在让我们将decision_function()和predict()应用于样本:

clf.decision_function(X)
clf.predict(X)

我们得到的输出是:

array([[-1.00052254],
       [-1.00006594],
       [ 1.00029424],
       [ 1.00029424]])
array([1, 1, 2, 2])

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

ljsrvy3e

ljsrvy3e2#

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

# 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)]

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_ #added missing underscore
nv = clf.n_support_
#a  = clf.dual_coef_
a  = clf._dual_coef_ #use complementary dual coefficients
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))
f87krz0w

f87krz0w3#

在datascience.sx上有一个really nice Q&A用于多类一对一的场景:

提问

我有一个多类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]]

我如何使用决策函数的输出来预测具有最高概率的类(A/B/C/D),如果可能的话,它的值?我访问过https://stackoverflow.com/a/20114601/7760998,但它是针对二进制分类器的,找不到一个好的资源来解释decision_function对于具有形状ovo(one-vs-one)的多类分类器的输出。

编辑:

上面的例子是针对“A”类的。对于另一个输入,分类器预测'C'并在decision_function中给出以下结果

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

对于分类器预测为“C”的另一个不同输入,从decision_function给出以下结果,

[[ 290.54180354 -133.93467605  116.37068951 -392.32251314 -130.84421412   284.87653043]]

如果它是ovr(one-vs-rest),那么通过选择具有更高值的值会变得更容易,但是在ovo(one-vs-one)中,结果列表中有(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的预测。试试看!

2sbarzqh

2sbarzqh4#

当你调用decision_function()时,你会得到每个成对分类器的输出(总共n*(n-1)/2个数字)。参见“模式分类的支持向量机”的第127和128页。
每个分类器都对正确答案进行投票(基于该分类器输出的符号); predict()返回得票最多的类。

nbewdwxp

nbewdwxp5#

它们之间的数学关系可能有点复杂。但是如果你在LinearSVC分类器中使用decision_function,这两者之间的关系会更加清晰!因为然后decision_function将为每个类标签(与SVC不同)给予分数,并预测将给给予分数最好的类。

t30tvxxf

t30tvxxf6#

Predict()遵循一个成对投票方案,该方案返回在所有成对比较中投票最多的类。当两个类的得分相同时,返回索引最低的类。
下面是一个Python示例,它将此投票方案应用于由一对一decision_function()返回的(n*(n-1)/2)成对分数。

from sklearn import svm
from sklearn import datasets
from numpy import argmax, zeros
from itertools import combinations

# do pairwise comparisons, return class with most +1 votes
def ovo_vote(classes, decision_function):
    combos = list(combinations(classes, 2))
    votes = zeros(len(classes))
    for i in range(len(decision_function[0])):
        if decision_function[0][i] > 0:
            votes[combos[i][0]] = votes[combos[i][0]] + 1
        else:
            votes[combos[i][1]] = votes[combos[i][1]] + 1
    winner = argmax(votes)
    return classes[winner]

# load the digits data set
digits = datasets.load_digits()

X, y = digits.data, digits.target

# set the SVC's decision function shape to "ovo"
estimator = svm.SVC(gamma=0.001, C=100., decision_function_shape='ovo')

# train SVC on all but the last digit
estimator.fit(X.data[:-1], y[:-1])

# print the value of the last digit
print("To be classified digit: ", y[-1:][0])

# print the predicted class
pred = estimator.predict(X[-1:])
print("Perform classification using predict: ", pred[0])

# get decision function
df = estimator.decision_function(X[-1:])

# print the decision function itself
print("Decision function consists of",len(df[0]),"elements:")
print(df)

# get classes, here, numbers 0 to 9
digits = estimator.classes_

# print which class has most votes
vote = ovo_vote(digits, df)
print("Perform classification using decision function: ", vote)

相关问题