Подтвердить что ты не робот

Оцените несколько баллов по sklearn cross_val_score

Я пытаюсь оценить несколько алгоритмов машинного обучения с помощью sklearn для нескольких показателей (точность, отзыв, точность и, возможно, больше).

Для чего я понял из документации здесь и из исходного кода (я использую 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

Это нормально, но он медленный для моих собственных данных. Как измерить все баллы?

4b9b3361

Ответ 1

С момента написания этого сообщения scikit-learn обновил и сделал мой ответ устаревшим, см. гораздо более чистое решение ниже


Вы можете написать свою собственную функцию подсчета очков, чтобы захватить все три части информации, однако функция подсчета очков для перекрестной проверки должна возвращать только один номер в scikit-learn (это, скорее всего, связано с соображениями совместимости). Ниже приведен пример, где каждый из оценок для каждого фрагмента перекрестной проверки печатается на консоли, а возвращаемое значение представляет собой сумму трех показателей. Если вы хотите вернуть все эти значения, вам придется внести некоторые изменения в cross_val_score (строка 1351 из cross_validation.py) и _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-learn 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.        ]

Ответ 2

Я столкнулся с одной и той же проблемой, и я создал модуль, который поддерживает несколько показателей в 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. Надеюсь, что это поможет.