Введение

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

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

В конце концов, я обнаружил явление, которое вызывает такие колебания в таблице лидеров.

Предположить! Что может быть возможной причиной большого разброса в этих рангах? Другими словами, почему их модель теряет стабильность при оценке в частной таблице лидеров?

В этой статье мы рассмотрим возможные причины этого. Мы также рассмотрим концепцию перекрестной проверки и несколько распространенных методов ее выполнения.

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

Оглавление

  1. Почему модели теряют стабильность?
  2. Что такое перекрестная проверка?
  3. Несколько распространенных методов, используемых для перекрестной проверки
  • Подход с набором валидации
  • Пропустить одну перекрестную проверку (LOOCV)
  • k-кратная перекрестная проверка
  • Стратифицированная k-кратная перекрестная проверка
  • Состязательная проверка
  • Перекрестная проверка для временных рядов
  • Пользовательские методы перекрестной проверки

4. Как измерить дисперсию смещения модели?

Почему модели теряют стабильность?

Давайте поймем это, используя приведенный ниже снимок, иллюстрирующий соответствие различных моделей:

Здесь мы пытаемся найти взаимосвязь между размером и ценой. Для этого мы предприняли следующие шаги:

  1. Мы установили взаимосвязь, используя линейное уравнение, для которого были показаны графики. Первый график имеет высокую ошибку из точек обучающих данных. Следовательно, это не будет хорошо работать ни в публичной, ни в частной таблице лидеров. Это пример «недообучения». В этом случае наша модель не может уловить основной тренд данных.
  2. На втором графике мы только что нашли правильное соотношение между ценой и размером, т. Е. Низкая ошибка обучения и обобщение отношения.
  3. На третьем графике мы нашли отношение, которое имеет почти нулевую ошибку обучения. Это связано с тем, что взаимосвязь разрабатывается с учетом каждого отклонения в точке данных (включая шум), т. Е. Модель слишком чувствительна и фиксирует случайные закономерности, которые присутствуют только в текущем наборе данных. Это пример «переоснащения». В этих отношениях может быть большое расхождение между общедоступными и частными списками лидеров.

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

Что такое перекрестная проверка?

Перекрестная проверка — это метод, который включает в себя резервирование определенного образца набора данных, на котором вы не обучаете модель. Позже вы тестируете свою модель на этом образце, прежде чем завершить ее.

Вот шаги, связанные с перекрестной проверкой:

  1. Вы резервируете образец набора данных
  2. Обучите модель, используя оставшуюся часть набора данных
  3. Используйте резервную выборку тестового (проверочного) набора. Это поможет вам оценить эффективность работы вашей модели. Если ваша модель дает положительный результат на данных проверки, продолжайте использовать текущую модель. Это круто!

Несколько распространенных методов, используемых для перекрестной проверки

Существуют различные методы выполнения перекрестной проверки. Я обсудил некоторые из них в этом разделе.

Подход с набором валидации

При таком подходе мы резервируем 50 % набора данных для проверки, а оставшиеся 50 % — для обучения модели. Однако основным недостатком этого подхода является то, что, поскольку мы обучаем модель только на 50% набора данных, существует огромная вероятность того, что мы можем упустить некоторую интересную информацию о данных, что приведет к более высокому смещению.

Код Python:

train, validation = train_test_split(data, test_size=0.50, random_state = 5)

Оставьте одну перекрестную проверку (LOOCV)

В этом подходе мы резервируем только одну точку данных из доступного набора данных и обучаем модель на остальных данных. Этот процесс повторяется для каждой точки данных. Это также имеет свои преимущества и недостатки. Давайте посмотрим на них:

  • Мы используем все точки данных, поэтому систематическая ошибка будет низкой.
  • Мы повторяем процесс перекрестной проверки n раз (где n — количество точек данных), что приводит к увеличению времени выполнения.
  • Этот подход приводит к большему разбросу в эффективности модели тестирования, потому что мы тестируем по одной точке данных. Таким образом, на нашу оценку сильно влияет точка данных. Если точка данных окажется выбросом, это может привести к более высокой вариации.

validation[,setdiff(names(validation),label)])
score[[i]] = rmse(pred, validation[label]) # оценка/ошибка i-й складки
}
return(unlist(score)) # возвращает вектор
}

LOOCV пропускает одну точку данных. Точно так же вы можете оставить p обучающих примеров, чтобы иметь проверочный набор размера p для каждой итерации. Это называется LPOCV (Leave P Out Cross Validation).

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

Из приведенных выше двух методов проверки мы узнали:

  1. Мы должны обучить модель на большой части набора данных. В противном случае мы не сможем прочитать и распознать основную тенденцию в данных. В конечном итоге это приведет к более высокому смещению
  2. Нам также нужно хорошее соотношение точек данных тестирования. Как мы видели выше, меньшее количество точек данных может привести к ошибке дисперсии при проверке эффективности модели.
  3. Мы должны повторять процесс обучения и тестирования несколько раз. Мы должны изменить распределение набора данных поезда и тестирования. Это помогает правильно проверить эффективность модели.

Есть ли у нас метод, отвечающий всем этим трем требованиям?

Да! Этот метод известен как «k-кратная перекрестная проверка». Это легко следовать и реализовать. Ниже приведены шаги для этого:

  1. Случайным образом разделите весь набор данных на k раз
  2. Для каждой k-кратности в вашем наборе данных постройте свою модель на k — 1-кратности набора данных. Затем протестируйте модель, чтобы проверить эффективность для k-го сгиба.
  3. Запишите ошибку, которую вы видите в каждом из прогнозов.
  4. Повторяйте это до тех пор, пока каждая из k-кратностей не послужит тестовым набором.
  5. Среднее значение ваших k зарегистрированных ошибок называется ошибкой перекрестной проверки и будет служить вашей метрикой производительности для модели.

Ниже представлена ​​визуализация k-кратной проверки при k=10.

Теперь один из наиболее часто задаваемых вопросов: «Как выбрать правильное значение k?».

Всегда помните, что более низкое значение k является более предвзятым и, следовательно, нежелательным. С другой стороны, более высокое значение К менее смещено, но может страдать от большой изменчивости. Важно знать, что меньшее значение k всегда приводит нас к подходу с проверочным набором, тогда как более высокое значение k приводит к подходу LOOCV.

Именно, LOOCV эквивалентен n-кратной перекрестной проверке, где n — количество обучающих примеров.

Код Python:

from sklearn.model_selection import KFold 
kf = RepeatedKFold(n_splits=5, n_repeats=10, random_state=None) 
for train_index, test_index in kf.split(X):
      print("Train:", train_index, "Validation:",test_index)
      X_train, X_test = X[train_index], X[test_index] 
      y_train, y_test = y[train_index], y[test_index]

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

Стратификация — это процесс реорганизации данных таким образом, чтобы каждая складка была хорошим представителем целого. Например, в задаче бинарной классификации, где каждый класс содержит 50 % данных, лучше всего упорядочить данные таким образом, чтобы в каждом сгибе каждый класс содержал примерно половину экземпляров.

Как правило, это лучший подход при работе как со смещением, так и с дисперсией. Случайно выбранный фолд может неадекватно представлять второстепенный класс, особенно в случаях, когда существует огромный дисбаланс классов.

Фрагмент кода Python для стратифицированной k-кратной перекрестной проверки:

from sklearn.model_selection import StratifiedKFold
skf = StratifiedKFold(n_splits=5, random_state=None)
# X is the feature set and y is the target
for train_index, test_index in skf.split(X,y): 
    print("Train:", train_index, "Validation:", val_index) 
    X_train, X_test = X[train_index], X[val_index] 
    y_train, y_test = y[train_index], y[val_index]

Сказав это, если набор поездов не представляет адекватно все население, то использование стратифицированного k-кратного может быть не лучшей идеей. В таких случаях следует использовать простую k-кратную перекрестную проверку с повторением.

При повторной перекрестной проверке процедура перекрестной проверки повторяется n раз, что дает n случайных разделов исходной выборки. Результаты n снова усредняются (или комбинируются иным образом) для получения единой оценки.

Код Python для повторной перекрестной проверки k-fold:

from sklearn.model_selection import RepeatedKFold
rkf = RepeatedKFold(n_splits=5, n_repeats=10, random_state=None)
# X is the feature set and y is the target
for train_index, test_index in rkf.split(X):
     print("Train:", train_index, "Validation:", val_index)
     X_train, X_test = X[train_index], X[val_index]
     y_train, y_test = y[train_index], y[val_index]

5. Состязательная проверка

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

Общая идея состоит в том, чтобы проверить степень сходства между обучением и тестами с точки зрения распределения признаков. Если это не так, мы можем подозревать, что они совершенно разные. Эту интуицию можно количественно оценить, объединив обучающие и тестовые наборы, назначив метки 0/1 (0 — поезд, 1-тест) и оценив задачу бинарной классификации.

Давайте разберемся, как это можно сделать, выполнив следующие шаги:

  1. Удалить целевую переменную из набора поездов
train.drop(['target'], axis = 1, inplace = True)
  1. Создайте новую целевую переменную, которая равна 1 для каждой строки в наборе поездов и 0 для каждой строки в тестовом наборе.
train['is_train'] = 1
test['is_train'] = 0
  1. Объедините обучающие и тестовые наборы данных
df = pd.concat([train, test], axis = 0)
  1. Используя приведенную выше вновь созданную целевую переменную, подберите модель классификации и предскажите вероятности для каждой строки быть в тестовом наборе.
y = df['is_train']; df.drop('is_train', axis = 1, inplace = True) 
# Xgboost parameters
xgb_params = {'learning_rate': 0.05, 
              'max_depth': 4,
              'subsample': 0.9,        
              'colsample_bytree': 0.9,
              'objective': 'binary:logistic',
              'silent': 1, 
              'n_estimators':100, 
              'gamma':1,         
              'min_child_weight':4}   
clf = xgb.XGBClassifier(**xgb_params, seed = 10)
  1. Отсортируйте набор поездов, используя вычисленные вероятности на шаге 4, и возьмите верхние n% выборок/строк в качестве набора проверки (n% — это часть набора поездов, которую вы хотите сохранить в наборе проверки)
probs = clf.predict_proba(x1)[:,1]
new_df = pd.DataFrame({'id':train.id, 'probs':probs})
new_df = new_df.sort_values(by = 'probs', ascending=False) # 30% validation set
val_set_ids = new_df.iloc[1:np.int(new_df.shape[0]*0.3),1]

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

Тем не менее, вы должны быть осторожны при использовании этого типа метода проверки. Как только распределение тестового набора изменится, проверочный набор может перестать быть хорошим подмножеством для оценки вашей модели.

6. Перекрестная проверка временных рядов

Случайное разделение набора данных временных рядов не работает, потому что временной раздел ваших данных будет перепутан. Для задачи прогнозирования временных рядов мы выполняем перекрестную проверку следующим образом.

  1. Складки для перекрестной проверки временных рядов создаются в виде прямой цепочки.
  2. Предположим, у нас есть временной ряд годового потребительского спроса на продукт за период n лет. Складки будут созданы следующим образом:
fold 1: training [1], test [2]
fold 2: training [1 2], test [3]
fold 3: training [1 2 3], test [4]
fold 4: training [1 2 3 4], test [5]
fold 5: training [1 2 3 4 5], test [6]
.
.
.
fold n: training [1 2 3 ….. n-1], test [n]

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

Код Python:

from sklearn.model_selection import TimeSeriesSplit
X = np.array([[1, 2], [3, 4], [1, 2], [3, 4]])
y = np.array([1, 2, 3, 4])
tscv = TimeSeriesSplit(n_splits=3)
for train_index, test_index in tscv.split(X):
     print("Train:", train_index, "Validation:", val_index)
     X_train, X_test = X[train_index], X[val_index]
     y_train, y_test = y[train_index], y[val_index]
TRAIN: [0] TEST: [1]
TRAIN: [0 1] TEST: [2]
TRAIN: [0 1 2] TEST: [3]

h = 1 означает, что мы допускаем ошибку только для прогнозов на 1 шаг вперед.

(h = 4) Ошибка на 4 шага вперед показана на диаграмме ниже. Это можно использовать, если вы хотите оценить свою модель для многошагового прогноза.

7. Пользовательские методы перекрестной проверки

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

Например, в недавно завершившемся конкурсе Повелитель машин от Analytics Vidhya самым стабильным методом проверки, используемым лучшими финишерами, было использование переменной кампании id.

Как измерить дисперсию смещения модели?

После k-кратной перекрестной проверки мы получим k различных ошибок оценки модели (e1, e2…..ek). В идеальном сценарии сумма этих значений ошибок должна равняться нулю. Чтобы вернуть смещение модели, мы берем среднее значение всех ошибок. Чем ниже среднее значение, тем лучше модель.

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

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