2016-03-08 360 views
12

我正在尝试使用sklearn来评估多个机器学习算法,包括几个指标(准确度,召回率,精度和可能更多)。在sklearn上评估多个分数cross_val_score

对于我从文档here和源代码中了解到的内容(我使用sklearn 0.17),cross_val_score函数仅为每次执行接收一个记分器。因此,对于计算多得分,我必须:

  1. 多次执行
  2. 实现我的(耗时且容易出错)射手

    我这个代码执行多次:

    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 

这是好的,但对我自己的数据来说很慢。我如何测量所有分数?

+0

我会尝试实现什么'cross_val_score'正在做的手动 – Ryan

+0

使用Python 3。6此示例不起作用,因为目标数据是多类的,但cross_val_score的平均值设置为“二进制”。 您会收到以下错误消息:“ValueError:Target is multiclass but average ='binary'。Please choose another average setting。” 我该如何解决这个问题?不能真正将它二进制化,我可以吗? –

+0

我用Python 2.7。和sklearn 0.17。我认为这个错误发生在0.18。你使用什么sklearn版本? –

回答

14

因为写这篇文章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.  ] 
10

我跑过同样的问题,我创建了一个模块,可以在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下载该模块。 希望它有帮助。