Как правильно выполнить перекрестную проверку в scikit-learn? - PullRequest
3 голосов
/ 21 марта 2019

Я пытаюсь выполнить перекрестную проверку для классификатора k-nn, и я не понимаю, какой из следующих двух методов правильно выполняет перекрестную проверку.

training_scores = defaultdict(list)
validation_f1_scores = defaultdict(list)
validation_precision_scores = defaultdict(list)
validation_recall_scores = defaultdict(list)
validation_scores = defaultdict(list)

def model_1(seed, X, Y):
    np.random.seed(seed)
    scoring = ['accuracy', 'f1_macro', 'precision_macro', 'recall_macro']
    model = KNeighborsClassifier(n_neighbors=13)

    kfold = StratifiedKFold(n_splits=2, shuffle=True, random_state=seed)
    scores = model_selection.cross_validate(model, X, Y, cv=kfold, scoring=scoring, return_train_score=True)
    print(scores['train_accuracy'])
    training_scores['KNeighbour'].append(scores['train_accuracy'])
    print(scores['test_f1_macro'])
    validation_f1_scores['KNeighbour'].append(scores['test_f1_macro'])
    print(scores['test_precision_macro'])
    validation_precision_scores['KNeighbour'].append(scores['test_precision_macro'])
    print(scores['test_recall_macro'])
    validation_recall_scores['KNeighbour'].append(scores['test_recall_macro'])
    print(scores['test_accuracy'])
    validation_scores['KNeighbour'].append(scores['test_accuracy'])

    print(np.mean(training_scores['KNeighbour']))
    print(np.std(training_scores['KNeighbour']))
    #rest of print statments

Похоже, что цикл во второй модели избыточен.

def model_2(seed, X, Y):
    np.random.seed(seed)
    scoring = ['accuracy', 'f1_macro', 'precision_macro', 'recall_macro']
    model = KNeighborsClassifier(n_neighbors=13)

    kfold = StratifiedKFold(n_splits=2, shuffle=True, random_state=seed)
    for train, test in kfold.split(X, Y):
        scores = model_selection.cross_validate(model, X[train], Y[train], cv=kfold, scoring=scoring, return_train_score=True)
        print(scores['train_accuracy'])
        training_scores['KNeighbour'].append(scores['train_accuracy'])
        print(scores['test_f1_macro'])
        validation_f1_scores['KNeighbour'].append(scores['test_f1_macro'])
        print(scores['test_precision_macro'])
        validation_precision_scores['KNeighbour'].append(scores['test_precision_macro'])
        print(scores['test_recall_macro'])
        validation_recall_scores['KNeighbour'].append(scores['test_recall_macro'])
        print(scores['test_accuracy'])
        validation_scores['KNeighbour'].append(scores['test_accuracy'])

    print(np.mean(training_scores['KNeighbour']))
    print(np.std(training_scores['KNeighbour']))
    # rest of print statments

Я использую StratifiedKFold, и я не уверен, нужен ли мне цикл, как в функции model_2, или функция cross_validate уже использует разбиение, поскольку мы передаем cv=kfold в качестве аргумента.

Я не вызываю fit метод, это нормально? cross_validate звонит автоматически или мне нужно позвонить fit перед тем, как позвонить cross_validate?

Наконец, как мне создать матрицу путаницы? Нужно ли создавать его для каждого сгиба, если да, как рассчитать итоговую / среднюю матрицу путаницы?

Ответы [ 2 ]

4 голосов
/ 21 марта 2019

Документация , возможно, является вашим лучшим другом в таких вопросах;из простого примера должно быть очевидно, что вы не должны использовать ни цикл for, ни вызов fit.Адаптируя пример для использования KFold, как вы:

from sklearn.model_selection import KFold, cross_validate
from sklearn.datasets import load_boston
from sklearn.tree import DecisionTreeRegressor

X, y = load_boston(return_X_y=True)
n_splits = 5
kf = KFold(n_splits=n_splits, shuffle=True)

model = DecisionTreeRegressor()
scoring=('r2', 'neg_mean_squared_error')

cv_results = cross_validate(model, X, y, cv=kf, scoring=scoring, return_train_score=False)
cv_results

Результат:

{'fit_time': array([0.00901461, 0.00563478, 0.00539804, 0.00529385, 0.00638533]),
 'score_time': array([0.00132656, 0.00214362, 0.00134897, 0.00134444, 0.00176597]),
 'test_neg_mean_squared_error': array([-11.15872549, -30.1549505 , -25.51841584, -16.39346535,
        -15.63425743]),
 'test_r2': array([0.7765484 , 0.68106786, 0.73327311, 0.83008371, 0.79572363])}

как я могу создать матрицу путаницы?Нужно ли создавать его для каждого сгиба

Никто не может сказать вам, если вам нужно для создания матрицы путаницы для каждого сгиба - это ваш выбор.Если вы решите сделать это, может быть, лучше пропустить cross_validate и выполнить процедуру «вручную» - см. Мой ответ в Как отобразить матрицу путаницы и отчет (отзыв, точность, измерить) для каждого раза перекрестной проверки.

Если да, как рассчитать итоговую / среднюю матрицу путаницы?

Нет «окончательной / средней» матрицы путаницы;если вы хотите вычислить что-то большее, чем k единиц (по одному для каждого k-кратного), как описано в связанном ответе, вам необходимо иметь отдельный набор проверки ...

3 голосов
/ 21 марта 2019

model_1 правильно.

https://scikit -learn.org / стабильный / модули / полученные / sklearn.model_selection.cross_validate.html

cross_validate(estimator, X, y=None, groups=None, scoring=None, cv=’warn’, n_jobs=None, verbose=0, fit_params=None, pre_dispatch=‘2*n_jobs’, return_train_score=’warn’, return_estimator=False, error_score=’raise-deprecating’)

, где

estimator - это объект, реализующий 'fit'. Это будет называться, чтобы соответствовать модели на сгибах поезда.

cv: это генератор перекрестной проверки, который используется для создания обучающих и тестовых расщеплений.

Если вы последуете примеру в документации по sklearn

cv_results = cross_validate(lasso, X, y, cv=3, return_train_score=False) cv_results['test_score'] array([0.33150734, 0.08022311, 0.03531764])

Вы можете видеть, что модель lasso устанавливается 3 раза по одному разу для каждого сгиба на отрезках поездов, а также проверяется 3 раза на тестовых отрезках. Вы можете видеть, что результаты теста на данных проверки сообщаются.

Перекрестная проверка моделей Keras

Keras предоставляет оболочку, которая делает модели keras совместимыми с методом sklearn cross_validatation. Вы должны обернуть модель keras, используя KerasClassifier

from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import KFold, cross_validate
from keras.models import Sequential
from keras.layers import Dense
import numpy as np

def get_model():
    model = Sequential()
    model.add(Dense(2, input_dim=2, activation='relu')) 
    model.add(Dense(1, activation='sigmoid'))
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

model = KerasClassifier(build_fn=get_model, epochs=10, batch_size=8, verbose=0)
kf = KFold(n_splits=3, shuffle=True)

X = np.random.rand(10,2)
y = np.random.rand(10,1)

cv_results = cross_validate(model, X, y, cv=kf, return_train_score=False)

print (cv_results)
...