web-dev-qa-db-ja.com

Scikit SVCのdecision_functionを学習して予測する

SVCのインスタンスメソッドであるdecision_functionとpredictの関係を理解し​​ようとしています( http://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html )。これまでのところ、決定関数がクラス間のペアワイズスコアを返すことを収集しました。私は、predictはペアワイズスコアを最大化するクラスを選択するという印象を受けていましたが、これをテストしてさまざまな結果を得ました。以下は、2つの関係を理解するために使用していたコードです。まず、ペアワイズスコアマトリックスを生成し、次に、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]

誰もこれらの予測と決定関数の関係を知っていますか?

53
Peter Tseng

私はあなたのコードを完全には理解していませんが、あなたが参照したドキュメントページの例を見てみましょう。

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) 

次に、決定関数と予測の両方をサンプルに適用します。

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

得られる出力は次のとおりです。

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

そして、それは簡単に解釈できます。desion関数は、分類器によって生成された超平面のどちら側にいるか(および、そこからどれだけ離れているか)を示します。その情報に基づいて、推定器は対応するラベルで例をラベル付けします。

26
Martin Böschen

decision_function()を呼び出すと、ペアワイズ分類器のそれぞれから出力が得られます(n *(n-1)/ 2個の合計数)。 「パターン分類のサポートベクターマシン」の127ページと128ページ を参照してください。

各分類子は、(その分類子の出力の符号に基づいて)正解が何であるかについて投票を行います。 predict()は、投票数が最も多いクラスを返します。

14
RomanCobra

興味がある人のために、C++( here )から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)]
_

predictと_decision_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))
_
13
bcorso

Datascience.sxのマルチクラスone-vs-oneシナリオには 本当に素晴らしいQ&A があります:

質問

ラベル「A」、「B」、「C」、「D」のマルチクラスSVM分類器があります。

これは私が実行しているコードです:

>>>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 を訪れましたが、それはバイナリ分類器用であり、形状ovo(1つ-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の回答に表示されます)。見るべき:

enter image description here

  • 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のラベルです。

これで3つのCがあります。Cはあなたの予測です。他の2つの例に対して私の手順を繰り返すと、Pythonの予測が得られます。それを試してみてください!

12
serv-inc

それらはおそらく少し複雑な数学的関係を持っています。ただし、decision_functionLinearSVC分類子では、これら2つの間の関係がより明確になります。なぜならdecision_functionは各クラスラベル(SVCとは異なります)のスコアを提供し、predictはクラスに最高のスコアを提供します。

0
Bilal Dadanlar