web-dev-qa-db-fra.com

Comment le score de précision scikit-learn cross_val_predict est-il calculé?

Est-ce que la méthode cross_val_predict (voir doc , v0.18) avec k comme indiqué dans le code ci-dessous calcule la précision de chaque pli et la moyenne finale ou non? 

cv = KFold(len(labels), n_folds=20)
clf = SVC()
ypred = cross_val_predict(clf, td, labels, cv=cv)
accuracy = accuracy_score(labels, ypred)
print accuracy
11
hiker

Non!

Selon cross validation doc page, cross_val_predict ne renvoie aucun résultat, mais uniquement les étiquettes basées sur une certaine stratégie décrite ici:

La fonction cross_val_predict a une interface similaire à celle de cross_val_score, mais renvoie, pour chaque élément de l'entrée, le prédiction obtenue pour cet élément lorsqu’il était dans le test ensemble. Seules les stratégies de validation croisée qui attribuent tous les éléments à un Vous pouvez utiliser le jeu de tests exactement une fois (sinon, une exception est déclenchée).

Et par conséquent, en appelant accuracy_score(labels, ypred), vous calculez simplement les scores de précision des étiquettes prédites par la stratégie particulière susmentionnée par rapport aux étiquettes réelles. Ceci est à nouveau spécifié dans la même page de documentation:

Ces prédictions peuvent ensuite être utilisées pour évaluer le classificateur:

predicted = cross_val_predict(clf, iris.data, iris.target, cv=10) 
metrics.accuracy_score(iris.target, predicted)

Notez que le résultat de ce calcul peut être légèrement différent parmi ceux obtenus en utilisant cross_val_score car les éléments sont groupés en différentes manières.

Si vous avez besoin de scores de précision de plis différents, vous devriez essayer:

>>> scores = cross_val_score(clf, X, y, cv=cv)
>>> scores                                              
array([ 0.96...,  1.  ...,  0.96...,  0.96...,  1.        ])

et ensuite pour la précision moyenne de tous les plis, utilisez scores.mean():

>>> print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
Accuracy: 0.98 (+/- 0.03)

Modifier:

Pour calculer Cohen Kappa coefficient et la matrice de confusion, j'ai supposé que vous entendiez le coefficient kappa et la matrice de confusion entre les étiquettes vraies et les étiquettes prédites de chaque pli:

from sklearn.model_selection import KFold
from sklearn.svm.classes import SVC
from sklearn.metrics.classification import cohen_kappa_score
from sklearn.metrics import confusion_matrix

cv = KFold(len(labels), n_folds=20)
clf = SVC()
for train_index, test_index in cv.split(X):
    clf.fit(X[train_index], labels[train_index])
    ypred = clf.predict(X[test_index])
    kappa_score = cohen_kappa_score(labels[test_index], ypred)
    confusion_matrix = confusion_matrix(labels[test_index], ypred)

Edit 2:

Que renvoie cross_val_predict?

KFold divise les données en k parties, puis pour i = 1..k itérations, procède de la manière suivante: prend toutes les parties sauf une partie en tant que données d'apprentissage, y adapte le modèle, puis prédit les étiquettes pour une partie (données de test ). A chaque itération, l’étiquette d’une partie des données est prédite. À la fin, cross_val_predict fusionne toutes les étiquettes partiellement prédites et les renvoie dans leur ensemble.

Ce code montre ce processus étape par étape:

X = np.array([[0], [1], [2], [3], [4], [5]])
labels = np.array(['a', 'a', 'a', 'b', 'b', 'b'])

cv = KFold(len(labels), n_folds=3)
clf = SVC()
ypred_all = np.chararray((labels.shape))
i = 1
for train_index, test_index in cv.split(X):
    print("iteration", i, ":")
    print("train indices:", train_index)
    print("train data:", X[train_index])
    print("test indices:", test_index)
    print("test data:", X[test_index])
    clf.fit(X[train_index], labels[train_index])
    ypred = clf.predict(X[test_index])
    print("predicted labels for data of indices", test_index, "are:", ypred)
    ypred_all[test_index] = ypred
    print("merged predicted labels:", ypred_all)
    i = i+1
    print("=====================================")
y_cross_val_predict = cross_val_predict(clf, X, labels, cv=cv)
print("predicted labels by cross_val_predict:", y_cross_val_predict)

Le résultat est:

iteration 1 :
train indices: [2 3 4 5]
train data: [[2] [3] [4] [5]]
test indices: [0 1]
test data: [[0] [1]]
predicted labels for data of indices [0 1] are: ['b' 'b']
merged predicted labels: ['b' 'b' '' '' '' '']
=====================================
iteration 2 :
train indices: [0 1 4 5]
train data: [[0] [1] [4] [5]]
test indices: [2 3]
test data: [[2] [3]]
predicted labels for data of indices [2 3] are: ['a' 'b']
merged predicted labels: ['b' 'b' 'a' 'b' '' '']
=====================================
iteration 3 :
train indices: [0 1 2 3]
train data: [[0] [1] [2] [3]]
test indices: [4 5]
test data: [[4] [5]]
predicted labels for data of indices [4 5] are: ['a' 'a']
merged predicted labels: ['b' 'b' 'a' 'b' 'a' 'a']
=====================================
predicted labels by cross_val_predict: ['b' 'b' 'a' 'b' 'a' 'a']
36
Omid

Comme vous pouvez le constater d'après le code cross_val_predict sur github , la fonction calcule pour chaque pli les prédictions et les concatène. Les prédictions sont faites sur la base d'un modèle appris d'autres plis.

Voici une combinaison de votre code et de l'exemple fourni dans le code

from sklearn import datasets, linear_model
from sklearn.model_selection import cross_val_predict, KFold
from sklearn.metrics import accuracy_score

diabetes = datasets.load_diabetes()
X = diabetes.data[:400]
y = diabetes.target[:400]
cv = KFold(n_splits=20)
lasso = linear_model.Lasso()
y_pred = cross_val_predict(lasso, X, y, cv=cv)
accuracy = accuracy_score(y_pred.astype(int), y.astype(int))

print(accuracy)
# >>> 0.0075

Enfin, pour répondre à votre question: "Non, l’exactitude n’est pas calculée en moyenne pour chaque pli"

5
BloodyD

Je voudrais ajouter une option pour une réponse rapide et facile, supérieure à celle des développeurs précédents. 

Si vous prenez la moyenne micro de F1, vous obtiendrez essentiellement le taux de précision. Ainsi, par exemple, ce serait:

from sklearn.model_selection import cross_val_score, cross_val_predict
from sklearn.metrics import precision_recall_fscore_support as score    

y_pred = cross_val_predict(lm,df,y,cv=5)
precision, recall, fscore, support = score(y, y_pred, average='micro') 
print(fscore)

Cela fonctionne mathématiquement, puisque la moyenne micro donne la moyenne pondérée de la matrice de confusion.

Bonne chance. 

0
Shlomo Koppel

Comme il est écrit dans la documentation sklearn.model_selection.cross_val_predict :

Il n'est pas approprié de passer ces prévisions dans une évaluation métrique. Utilisation cross_validate pour mesurer l'erreur de généralisation.

0
Enrico Damini