Практически всегда от моделей машинного обучения требуется указать их точность. Для расчета точности необходимо
1) обучить модель на тренировочном датасете
2) предсказать результаты на тестовом датасете
3) сравнить правильные данные с предсказанными
Данная процедура проста, но в зависимости от разбиения на обучающий датасет и тестовый датасет мы получим немного разные значения. И какой же результат более правильный?
Правильного нет, ведь точность классификатора само по себе понятие относительное. Но интуитивно понятно, что для лучшей оценки необходимо провести процедуру 1-2-3 как можно большее количество раз.
И вот как раз для оценки точности классификатора и придумали кросс-валидацию. Или K-fold cross-validation.
Идея проста, весь датасет делится на N частей. На каждой итерации N-1 часть идёт на train, и одна на test.
В sklearn для этого есть специальный метод cross_val_score:
import numpy as np from sklearn.model_selection import cross_val_score from sklearn.datasets import load_iris from sklearn.ensemble import RandomForestClassifier # воспользуемся известным датасетом для примера iris = load_iris() clf = RandomForestClassifier(n_estimators=30, random_state=42) # передаем классификатор, X, y и кол-во фолдов=5 res = cross_val_score(clf, iris['data'], iris['target'], cv=5) print(res) # [0.96666667 0.96666667 0.93333333 0.96666667 1. ] print(np.mean(res)) # 0.966
Как видим всё очень просто, по сравнению с train_test_split мы получим более точную оценку качества классификатора, т.к. провели эксперимент N раз (в нашем случае 5 раз).
Да, пришлось потратить в 5 раз больше времени по сравнению с train_test_split, но когда данных не очень много — это оправдано.
Однако не всегда удаётся воспользоваться методом cross_val_score, например если хотим что-то ещё подсчитать в это время.
Для этого есть более гибкий метод KFold.
Kfold часто используют не только для оценки точности классификатора, но и например для контроля переобучения для классификатора.
Для многих моделей очень важно знать, в какой момент начинается переобучение. Таким образом можно обучить 10 классификаторов с контролем переобучения и потом усреднить их предсказания. Это может дать дать лучий результат, чем если обучить одну модель сразу на всех данных, без контроля переобучения.
Для примера возьмем библиотеку catboost и будем валидироваться оставшемся фолде
from sklearn.model_selection import KFold from sklearn.datasets import load_iris from catboost import CatBoostClassifier iris = load_iris() # инициализация KFold с 5тью фолдами cv = KFold(n_splits=5, random_state=42, shuffle=True) classifiers = [] # метод split возвращает индексы для объектов train и test for train_index, test_index in cv.split(iris['target']): clf = CatBoostClassifier(random_state=42, iterations=200, verbose=50, learning_rate=0.1) X_train, X_test = iris['data'][train_index], iris['data'][test_index] y_train, y_test = iris['target'][train_index], iris['target'][test_index] clf.fit(X_train, y_train, eval_set=(X_test, y_test), use_best_model=True) # получим 5 оптимальных классификаторов classifiers.append(clf)