J'essaie d'évaluer plusieurs algorithmes d'apprentissage automatique avec sklearn pour quelques mesures (précision, rappel, précision et peut-être plus).
Pour ce que j'ai compris de la documentation ici et du code source (j'utilise sklearn 0.17), la fonction cross_val_score ne reçoit qu'un marqueur pour chaque exécution. Donc, pour calculer plusieurs scores, je dois:
Mettre en œuvre mon scoreur (long et sujet aux erreurs)
J'ai exécuté plusieurs fois avec ce code:
from sklearn.svm import SVC
from sklearn.naive_bayes import GaussianNB
from sklearn.tree import DecisionTreeClassifier
from sklearn.cross_validation import cross_val_score
import time
from sklearn.datasets import load_iris
iris = load_iris()
models = [GaussianNB(), DecisionTreeClassifier(), SVC()]
names = ["Naive Bayes", "Decision Tree", "SVM"]
for model, name in Zip(models, names):
print name
start = time.time()
for score in ["accuracy", "precision", "recall"]:
print score,
print " : ",
print cross_val_score(model, iris.data, iris.target,scoring=score, cv=10).mean()
print time.time() - start
Et j'obtiens cette sortie:
Naive Bayes
accuracy : 0.953333333333
precision : 0.962698412698
recall : 0.953333333333
0.0383198261261
Decision Tree
accuracy : 0.953333333333
precision : 0.958888888889
recall : 0.953333333333
0.0494720935822
SVM
accuracy : 0.98
precision : 0.983333333333
recall : 0.98
0.063080072403
Ce qui est correct, mais c'est lent pour mes propres données. Comment puis-je mesurer tous les scores?
Depuis la rédaction de cet article, scikit-learn a été mis à jour et a rendu ma réponse obsolète, voir la solution beaucoup plus propre ci-dessous
Vous pouvez écrire votre propre fonction de notation pour capturer les trois informations, mais une fonction de notation pour la validation croisée ne doit renvoyer qu'un seul nombre dans scikit-learn
(c'est probablement pour des raisons de compatibilité). Voici un exemple où chacun des scores de chaque tranche de validation croisée s'imprime sur la console, et la valeur renvoyée n'est que la somme des trois mesures. Si vous souhaitez renvoyer toutes ces valeurs, vous devrez apporter des modifications à cross_val_score
(ligne 1351 de cross_validation.py) et _score
(ligne 1601 ou même fichier).
from sklearn.svm import SVC
from sklearn.naive_bayes import GaussianNB
from sklearn.tree import DecisionTreeClassifier
from sklearn.cross_validation import cross_val_score
import time
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score, precision_score, recall_score
iris = load_iris()
models = [GaussianNB(), DecisionTreeClassifier(), SVC()]
names = ["Naive Bayes", "Decision Tree", "SVM"]
def getScores(estimator, x, y):
yPred = estimator.predict(x)
return (accuracy_score(y, yPred),
precision_score(y, yPred, pos_label=3, average='macro'),
recall_score(y, yPred, pos_label=3, average='macro'))
def my_scorer(estimator, x, y):
a, p, r = getScores(estimator, x, y)
print a, p, r
return a+p+r
for model, name in Zip(models, names):
print name
start = time.time()
m = cross_val_score(model, iris.data, iris.target,scoring=my_scorer, cv=10).mean()
print '\nSum:',m, '\n\n'
print 'time', time.time() - start, '\n\n'
Qui donne:
Naive Bayes
0.933333333333 0.944444444444 0.933333333333
0.933333333333 0.944444444444 0.933333333333
1.0 1.0 1.0
0.933333333333 0.944444444444 0.933333333333
0.933333333333 0.944444444444 0.933333333333
0.933333333333 0.944444444444 0.933333333333
0.866666666667 0.904761904762 0.866666666667
1.0 1.0 1.0
1.0 1.0 1.0
1.0 1.0 1.0
Sum: 2.86936507937
time 0.0249638557434
Decision Tree
1.0 1.0 1.0
0.933333333333 0.944444444444 0.933333333333
1.0 1.0 1.0
0.933333333333 0.944444444444 0.933333333333
0.933333333333 0.944444444444 0.933333333333
0.866666666667 0.866666666667 0.866666666667
0.933333333333 0.944444444444 0.933333333333
0.933333333333 0.944444444444 0.933333333333
1.0 1.0 1.0
1.0 1.0 1.0
Sum: 2.86555555556
time 0.0237860679626
SVM
1.0 1.0 1.0
0.933333333333 0.944444444444 0.933333333333
1.0 1.0 1.0
1.0 1.0 1.0
1.0 1.0 1.0
0.933333333333 0.944444444444 0.933333333333
0.933333333333 0.944444444444 0.933333333333
1.0 1.0 1.0
1.0 1.0 1.0
1.0 1.0 1.0
Sum: 2.94333333333
time 0.043044090271
Depuis scikit-learn 0.19.0, la solution devient beaucoup plus facile
from sklearn.model_selection import cross_validate
from sklearn.datasets import load_iris
from sklearn.svm import SVC
iris = load_iris()
clf = SVC()
scoring = {'acc': 'accuracy',
'prec_macro': 'precision_macro',
'rec_micro': 'recall_macro'}
scores = cross_validate(clf, iris.data, iris.target, scoring=scoring,
cv=5, return_train_score=True)
print(scores.keys())
print(scores['test_acc'])
Qui donne:
['test_acc', 'score_time', 'train_acc', 'fit_time', 'test_rec_micro', 'train_rec_micro', 'train_prec_macro', 'test_prec_macro']
[ 0.96666667 1. 0.96666667 0.96666667 1. ]
J'ai rencontré le même problème et j'ai créé un module qui peut prendre en charge plusieurs mesures dans cross_val_score
.
Afin d'accomplir ce que vous voulez avec ce module, vous pouvez écrire:
from multiscorer import MultiScorer
import numpy as np
from sklearn.metrics import accuracy_score, precision_score, recall_score
from sklearn.model_selection import cross_val_score
from numpy import average
scorer = MultiScorer({
'Accuracy' : (accuracy_score, {}),
'Precision' : (precision_score, {'pos_label': 3, 'average':'macro'}),
'Recall' : (recall_score, {'pos_label': 3, 'average':'macro'})
})
for model, name in Zip(models, names):
print name
start = time.time()
cross_val_score(model, iris.data, iris.target,scoring=scorer, cv=10)
results = scorer.get_results()
for metric_name in results.keys():
average_score = np.average(results[metric_name])
print('%s : %f' % (metric_name, average_score))
print 'time', time.time() - start, '\n\n'
Vous pouvez vérifier et télécharger ce module depuis GitHub . J'espère que ça aide.