在sklearn上评估多个分数cross_val_score
问题描述:
我正在尝试使用sklearn来评估多个机器学习算法,包括几个指标(准确度,召回率,精度和可能更多)。在sklearn上评估多个分数cross_val_score
对于我从文档here和源代码中了解到的内容(我使用sklearn 0.17),cross_val_score函数仅为每次执行接收一个记分器。因此,对于计算多得分,我必须:
- 多次执行
-
实现我的(耗时且容易出错)射手
我这个代码执行多次:
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
而且我得到这样的输出:
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
这是好的,但对我自己的数据来说很慢。我如何测量所有分数?
答
因为写这篇文章scikit学习已经更新,使我的答案过时的时候,看到下面
的更清洁的解决方案,您可以编写自己的评分功能来捕获所有三块的信息,但交叉验证的评分函数只能返回
scikit-learn
中的单个数字(这可能是出于兼容性原因)。下面是一个例子,每个交叉验证片的每个分数都打印到控制台,返回的值就是三个度量的总和。如果要返回所有这些值,则必须对
cross_val_score
(cross_validation.py的第1351行)和
_score
(第1601行或同一文件)进行一些更改。
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'
其中给出:
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
由于scikit学习0.19.0溶液变成多容易
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'])
其中给出:
['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. ]
答
我跑过同样的问题,我创建了一个模块,可以在cross_val_score
中支持多个指标。
为了完成你想要使用此模块是什么,你可以写:
from multiscorer import MultiScorer
import numpy as np
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'
您可以检查和GitHub下载该模块。 希望它有帮助。
我会尝试实现什么'cross_val_score'正在做的手动 – Ryan
使用Python 3。6此示例不起作用,因为目标数据是多类的,但cross_val_score的平均值设置为“二进制”。 您会收到以下错误消息:“ValueError:Target is multiclass but average ='binary'。Please choose another average setting。” 我该如何解决这个问题?不能真正将它二进制化,我可以吗? –
我用Python 2.7。和sklearn 0.17。我认为这个错误发生在0.18。你使用什么sklearn版本? –