Перекрестная проверка (CV)

  • Поддерживать перекрестную проверку
  • k-кратная перекрестная проверка

Тестовый набор по-прежнему должен храниться для окончательной оценки, но проверочный набор больше не нужен при выполнении CV.

В базовом подходе, называемом k-fold CV, обучающий набор разбивается на k меньших наборов. Для каждой из k «складок» выполняется следующая процедура:

  • Модель обучается с использованием k-1 складок в качестве обучающих данных;
  • полученная модель проверяется на оставшейся части данных (т. Е. Она используется в качестве тестового набора для вычисления показателя производительности, такого как точность).

Мера производительности, о которой сообщает k-кратная перекрестная проверка, представляет собой среднее значение значений, вычисленных в цикле.

Метод удержания

  • Разделить исходный набор данных на отдельный набор обучающих и тестовых данных
  • Набор обучающих данных — обучение модели
  • Тестовый набор данных - оцените его производительность обобщения

‹img src=’holdout method.png’ width=50%›

Вариант состоит в том, чтобы разделить тренировочный набор на два: тренировочный набор и проверочный набор.

Тренировочный комплект:- Для примерки разных моделей

Набор проверки: — для настройки и сравнения различных настроек параметров для дальнейшего повышения производительности при прогнозировании невидимых данных. И, наконец, выбор модели.

Этот процесс называется выбором модели. Мы хотим выбрать оптимальные значения параметров настройки (также называемых гиперпараметрами).

‹img src=’holdout method w validation.png’ width=50%›

K-кратная перекрестная проверка

  • Случайным образом разделите набор обучающих данных на k раз без замены.
  • k — 1 кратность используется для обучения модели.
  • Одна складка используется для оценки производительности.

Эта процедура повторяется k раз.

Окончательные результаты: - k моделей и оценки производительности.

  • рассчитать среднюю производительность моделей на основе различных независимых сверток, чтобы получить оценку производительности, которая менее чувствительна к подразделению обучающих данных по сравнению с методом удержания.
  • k-кратная перекрестная проверка используется для настройки модели. Поиск оптимальных значений гиперпараметров, обеспечивающих удовлетворительную производительность обобщения.
  • Как только мы нашли удовлетворительные значения гиперпараметров, мы можем переобучить модель на полном обучающем наборе и получить окончательную оценку производительности с использованием независимого тестового набора. Обоснование подгонки модели ко всему набору обучающих данных после k-кратной перекрестной проверки заключается в том, что добавление большего количества обучающих выборок к алгоритму обучения обычно приводит к более точной и надежной модели.
  • Общее k равно 10
  • Для относительно небольших тренировочных сетов увеличьте количество сгибов.

Стратифицированная k-кратная перекрестная проверка

  • вариация k-кратного
  • Может дать более точные оценки смещения и дисперсии, особенно в случаях неравных пропорций классов

Иллюстрация

Перекрестная проверка: оценка производительности оценщика

Адаптировано из scikit учиться

Изучение параметров прогностической функции и проверка ее на одних и тех же данных является методологической ошибкой: модель, которая будет просто повторять метки выборок, которые она только что видела, будет иметь высшую оценку, но не сможет предсказать ничего полезного на еще... невидимые данные. Эта ситуация называется переоснащением.

Чтобы этого избежать, при выполнении (контролируемого) эксперимента по машинному обучению принято удерживать часть доступных данных в виде тестового набора X_test, y_test. Обратите внимание, что слово «эксперимент» предназначено не только для академического использования, потому что даже в коммерческих условиях машинное обучение обычно начинается экспериментально.

В scikit-learn случайное разделение на обучающие и тестовые наборы можно быстро вычислить с помощью вспомогательной функции train_test_split. Давайте загрузим набор данных радужной оболочки, чтобы он соответствовал линейной машине опорных векторов:

In [1]:

import numpy as np
from sklearn.model_selection import train_test_split
from sklearn import datasets
from sklearn import svm
boston = datasets.load_boston()
boston.data.shape, boston.target.shape

Выход[1]:

((506, 13), (506,))

Теперь мы можем быстро выбрать обучающий набор, сохраняя 40% данных для тестирования (оценки) нашего регрессора:

In [2]:

X_train, X_test, y_train, y_test = train_test_split(
    boston.data, boston.target, test_size=0.4, random_state=0)
X_train.shape, y_train.shape
X_test.shape, y_test.shape

regression = svm.SVR(kernel='linear', C=1).fit(X_train, y_train)
regression.score(X_test, y_test)

Выход[2]:

0.6672554157940424

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

Таким образом, знания о тестовом наборе могут «просочиться» в модель, и метрики оценки больше не сообщают о производительности обобщения.

Чтобы решить эту проблему, еще одна часть набора данных может быть представлена ​​в виде так называемого «проверочного набора»: обучение продолжается на обучающем наборе, после чего выполняется оценка на проверочном наборе, и когда эксперимент кажется успешным , окончательную оценку можно выполнить на тестовом наборе.

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

Решением этой проблемы, как обсуждалось ранее, является процедура, называемая перекрестной проверкой (сокращенно CV). Тестовый набор по-прежнему должен храниться для окончательной оценки, но проверочный набор больше не нужен при выполнении CV. В базовом подходе, называемом k-fold CV, обучающая выборка разбивается на k меньших наборов (другие подходы описаны ниже, но в целом следуют тем же принципам). Для каждой из k «складок» выполняется следующая процедура:

  • Модель обучается с использованием k-1 складок в качестве обучающих данных;
  • полученная модель проверяется на оставшейся части данных (т. Е. Она используется в качестве тестового набора для вычисления показателя производительности, такого как точность).

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

Вычисление метрик с перекрестной проверкой

In [3]:

from sklearn.model_selection import cross_val_score
regression = svm.SVR(kernel='linear', C=1)
scores = cross_val_score(regression, boston.data, boston.target, cv=5)
scores

Выход[3]:

array([0.77328953, 0.72833447, 0.53795481, 0.15209389, 0.07729196])

Таким образом, средний балл и 95% доверительный интервал оценки балла определяются как:

In [4]:

print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
Accuracy: 0.45 (+/- 0.58)

По умолчанию оценка, вычисляемая на каждой итерации CV, является методом оценки оценщика. Это можно изменить, используя параметр подсчета очков:

In [5]:

from sklearn import metrics
scores = cross_val_score(
    regression, boston.data, boston.target, cv=5, scoring='neg_mean_squared_error')
scores

Выход[5]:

array([ -7.82949025, -24.73154773, -37.00390719, -74.37141515,
       -24.53325372])

Подробнее см. в разделе Параметр оценки: определение правил оценки модели. В случае набора данных Iris выборки сбалансированы по целевым классам, поэтому точность и оценка F1 почти равны.

Когда аргумент cv является целым числом, cross_val_score по умолчанию использует стратегии KFold или StratifiedKFold, причем последняя используется, если оценщик получен из ClassifierMixin.

К-кратный

KFold делит все выборки на k групп выборок, называемых складками (если k = n, это эквивалентно стратегии «Пропустить один») одинакового размера (если возможно). Функция прогнозирования изучается с использованием k - 1 кратности, а оставшаяся кратность используется для проверки.

Пример 2-кратной перекрестной проверки набора данных с 4 образцами:

In [6]:

import numpy as np
from sklearn.model_selection import KFold
X = ["a", "b", "c", "d"]
kf = KFold(n_splits=2)
for train, test in kf.split(X):
    print("%s %s" % (train, test))
[2 3] [0 1]
[0 1] [2 3]

Стратифицированный k-кратный

StratifiedKFold — это вариант k-fold, который возвращает стратифицированные складки: каждый набор содержит примерно такой же процент выборок каждого целевого класса, как и полный набор.

Пример стратифицированной 3-кратной перекрестной проверки набора данных с 10 образцами из двух слегка несбалансированных классов:

In [7]:

from sklearn.model_selection import StratifiedKFold
X = np.ones(10)
y = [0, 0, 0, 0, 1, 1, 1, 1, 1, 1]
skf = StratifiedKFold(n_splits=3)
for train, test in skf.split(X, y):
    print("%s %s" % (train, test))
[2 3 6 7 8 9] [0 1 4 5]
[0 1 3 4 5 8 9] [2 6 7]
[0 1 2 4 5 6 7] [3 8 9]

In [8]:

from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
#from sklearn.linear_model import LogisticRegression
from sklearn import svm
from sklearn.pipeline import make_pipeline
#pipe_lr = make_pipeline(StandardScaler(),
#                        PCA(n_components=2),
#                        LogisticRegression(random_state=1))
pipe_svm = make_pipeline(StandardScaler(),
                        PCA(n_components=2),
                        svm.SVR(kernel='linear', C=1))
pipe_svm.fit(X_train, y_train)
y_pred = pipe_svm.predict(X_test)
print('Test Accuracy: %.3f' % pipe_svm.score(X_test, y_test))
Test Accuracy: 0.391

In [9]:

from sklearn.model_selection import cross_val_score
scores = cross_val_score(estimator=pipe_svm,
                         X=X_train,
                         y=y_train,
                         cv=10,
                         n_jobs=1)
print('CV accuracy scores: %s' % scores)
CV accuracy scores: [0.63971176 0.43579197 0.46977821 0.25027246 0.5124364  0.26221374
 0.30877195 0.54528563 0.37810066 0.47313549]

In [10]:

print('CV accuracy: %.3f +/- %.3f' % (np.mean(scores),
                                      np.std(scores)))
CV accuracy: 0.428 +/- 0.121

In [ ]: