web-dev-qa-db-fra.com

Scikit Learn SVC decision_function et prédire

J'essaie de comprendre la relation entre decision_function et Predict, qui sont des méthodes d'instance de SVC ( http://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html ). Jusqu'à présent, j'ai compris que la fonction de décision renvoie des scores par paires entre les classes. J'avais l'impression que Predict choisit la classe qui maximise son score par paires, mais j'ai testé cela et obtenu des résultats différents. Voici le code que j'utilisais pour essayer de comprendre la relation entre les deux. Tout d'abord, j'ai généré la matrice de score par paires, puis j'ai imprimé la classe ayant le score maximal par paire différent de la classe prédite par 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]

Est-ce que quelqu'un sait la relation entre ces prédire et decision_function?

44
Peter Tseng

Je ne comprends pas bien votre code, mais examinons l'exemple de la page de documentation que vous avez citée:

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) 

Appliquons maintenant les fonctions de décision et de prédiction aux échantillons:

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

Le résultat obtenu est:

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

Et cela est facile à interpréter: la fonction desion nous indique de quel côté de l’hyperplan généré par le classificateur nous sommes (et à quelle distance nous en sommes éloignés). Sur la base de cette information, l’estimateur étiquette ensuite les exemples avec l’étiquette correspondante.

23
Martin Böschen

Lorsque vous appelez decision_function(), vous obtenez la sortie de chacun des classificateurs par paires (n * (n-1)/2 nombres au total). Voir pages 127 et 128 de "Machines à vecteurs de support pour la classification des motifs" .

Chaque classificateur soumet à un vote la réponse correcte (en fonction du signe de la sortie de ce classificateur); predict() renvoie la classe avec le plus de votes.

14
RomanCobra

Pour ceux que ça intéresse, je posterai un exemple rapide de la fonction predict traduite de C++ ( ici ) en 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)]

Il existe beaucoup d'arguments d'entrée pour predict et decision_function, mais notez qu'ils sont tous utilisés en interne par le modèle lors de l'appel de predict(X). En fait, tous les arguments vous sont accessibles à l'intérieur du modèle après ajustement:

# 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))
12
bcorso

Il y a un vraiment sympa Q & A pour le scénario multi-classes un-contre-un à datascience.sx:

Question

J'ai un classificateur SVM multiclass avec les étiquettes "A", "B", "C", "D".

C'est le code que je lance:

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

Comment puis-je utiliser la sortie de la fonction de décision pour prédire la classe (A/B/C/D) avec la probabilité la plus élevée et si possible, sa valeur? JE ont visité https://stackoverflow.com/a/20114601/7760998 mais c'est pour les classificateurs binaires et ne pouvait pas trouver une bonne ressource qui explique la sortie de decision_function pour les classificateurs multiclass avec forme ovo (one-vs-one).

Modifier:

L'exemple ci-dessus concerne la classe 'A'. Pour une autre entrée, le classifieur prédit 'C' et a donné le résultat suivant dans decision_function

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

Pour une autre entrée différente que le classificateur prédit comme "C" a donné le résultat suivant de decision_function,

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

Si cela avait été sur (one-vs-rest), cela deviendrait plus facile en sélectionnant le un avec une valeur plus élevée, mais in ovo (one-vs-one), il y a des valeurs (n * (n - 1)) / 2 dans la liste résultante.

Comment déduire quelle classe serait sélectionnée en fonction de la décision une fonction?

Réponse

Votre lien a suffisamment de ressources, alors passons en revue:

Lorsque vous appelez decision_function (), vous obtenez la sortie de chacun des classificateurs par paires (n * (n-1)/2 nombres au total). Voir pages 127 et 128 de "Machines à vecteurs de support pour la classification de modèles".

Cliquez sur le lien "page 127 et 128" (non montré ici, mais dans la réponse Stackoverflow). Tu devrais voir:

 enter image description here

  • L'implémentation SVM de Python utilise one-vs-one. C'est exactement ce dont parle le livre.
  • Pour chaque comparaison par paires, nous mesurons la fonction de décision
  • La fonction de décision est juste la limite de décision SVM binaire régulière

Qu'est-ce que cela a à voir avec votre question?

  • clf.decision_function () vous donnera le $ D $ pour chaque comparaison par paires
  • La classe avec le plus de votes gagne

Par exemple,

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

est en train de comparer:

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

Nous étiquetons chacun d'eux par le signe. On a:

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

Par exemple, 96.42193513 est positif et A est donc le libellé de AB.

Maintenant, nous avons trois C, C serait votre prédiction. Si vous répétez mon procédure pour les deux autres exemples, vous obtiendrez Python prédiction. Essayez le!

8
serv-inc

Ils ont probablement une relation mathématique un peu compliquée. Mais si vous utilisez le classificateur decision_function dans LinearSVC, la relation entre ces deux sera plus claire! Parce qu'alors, decision_function vous donnera des scores pour chaque étiquette de classe (différent de SVC) et prédire donnera la classe avec le meilleur score. 

0
Bilal Dadanlar