Должен ли быть сделан выбор характеристик перед разделением обучающего теста или после? - PullRequest
0 голосов
/ 25 мая 2019

На самом деле, существует противоречие 2 фактов, которые являются возможными ответами на вопрос:

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

  2. Противоречивый ответ заключается в том, что, если для выбора функции используется только обучающий набор, выбранный из всего набора данных, то порядок выбора характеристик или оценки важности функций, вероятно, будет динамически изменяться при изменении значения random_state в Train_Test_Split. , И если выбор функции для какой-либо конкретной работы изменяется, то невозможно сделать обобщение важности функции, что нежелательно. Во-вторых, если для выбора функции используется только обучающий набор, тогда тестовый набор может содержать определенный набор экземпляров, который не соответствует или противоречит выбору характеристик, выполненному только в обучающем наборе, поскольку общие исторические данные не анализируются. Кроме того, оценки важности признаков могут быть оценены только в том случае, если дан набор экземпляров, а не один тест / неизвестный экземпляр.

Ответы [ 2 ]

3 голосов
/ 26 мая 2019

Обычный ответ № 1 здесь правильный;аргументы в противоречивом ответе № 2 на самом деле не верны.

Когда возникают такие сомнения, полезно представить, что вы просто не не имеете доступа ни к одному набору тестов во время модели.процесс подгонки (который включает в себя важность функции);Вы должны рассматривать набор тестов как буквально невидимые данные (и, поскольку они не были видны, их нельзя было использовать для оценки важности функций).

Hastie & Tibshirani уже давно спорили оправильный и неправильный способ выполнения таких процессов;Я кратко изложил проблему в сообщении в блоге: Как НЕ выполнять выбор функции! - и хотя обсуждение касается перекрестной проверки, легко увидеть, что аргументы верны для случая поезда / тестаsplit тоже.

Единственный аргумент, который на самом деле справедлив в вашем противоречивом ответе # 2, заключается в том, что

общие исторические данные не анализируются

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


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

ОБНОВЛЕНИЕ (после комментариев):

тенденции в наборе тестов могут быть различными

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

Кроме того, при этом может быть высокая вероятность переоснащения

Единственный определенный способ переоснащения состоит в использовании тестового набора.любым способом во время конвейера (в том числе для выбора функции, как вы предлагаете).Возможно, у связанного поста в блоге достаточно аргументов (включая цитаты и ссылки), чтобы быть убедительными.Классический пример: показания в Опасности переоснащения или Как отбросить 50 мест за 1 минуту :

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

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

какая польза от теста, установленного для Обученной модели M1

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

Тем не менее, сам вопрос не без достоинств;как именно вы собираетесь оценить процесс выбора функции M1, если не с независимым набором тестов?

выбор функции должен быть сделан таким образом, чтобы улучшить производительность модели

Ну, никто не может спорить с этим, конечно! Подвох - о какой именно производительности мы говорим? Поскольку приведенный выше Kaggler действительно улучшал «производительность», пока он шел (применяя ошибочную процедуру), пока его модель не столкнулась с реальной невидимые данные (момент истины!), И неудивительно, что провалился .

По общему признанию, это не тривиальные вещи, и может потребоваться некоторое время, пока вы их не усвоите (не случайно, что, как демонстрируют Hastie & Tibshirani, есть даже исследовательских работ , где процедура выполняется неправильно ). До тех пор, мой совет, чтобы держать вас в безопасности, заключается в следующем: на всех этапах построения модели (включая выбор характеристик), притворяются , что у вас нет доступа к тесту установите вообще, и он станет доступен только тогда, когда вам нужно оценить производительность вашей окончательной модели.

2 голосов
/ 11 июня 2019

На самом деле продемонстрировать не сложно, почему использование всего набора данных (т. Е. Перед разделением на обучение / тестирование) для выбора объектов может сбить вас с толку.Вот одна из таких демонстраций с использованием случайных фиктивных данных с Python и scikit-learn:

import numpy as np
from sklearn.feature_selection import SelectKBest
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

# random data:
X = np.random.randn(500, 10000)
y = np.random.choice(2, size=500)

Поскольку наши данные X являются случайными (500 выборок, 10 000 объектов), а наши метки y являются двоичными,мы ожидаем, что мы никогда не сможем превысить базовую точность для такой настройки, то есть ~ 0,5, или около 50%.Давайте посмотрим, что происходит, когда мы применяем неправильную процедуру использования всего набора данных для выбора объектов, прежде чем разделить:

selector = SelectKBest(k=25)
# first select features
X_selected = selector.fit_transform(X,y)
# then split
X_selected_train, X_selected_test, y_train, y_test = train_test_split(X_selected, y, test_size=0.25, random_state=42)

# fit a simple logistic regression
lr = LogisticRegression()
lr.fit(X_selected_train,y_train)

# predict on the test set and get the test accuracy:
y_pred = lr.predict(X_selected_test)
accuracy_score(y_test, y_pred)
# 0.76000000000000001

Вау!Мы получаем 76% тест точность по бинарной проблеме, где, согласно самым основным законам статистики, мы должны получить что-то очень близкое к 50%!

Правда в том, чтонам удалось получить такую ​​точность теста просто потому, что мы совершили очень простую ошибку: мы по ошибке думаем , что наши тестовые данные не видны, но на самом деле тестовые данные уже были обнаружены в процессе построения моделиво время выбора функции, в частности, здесь:

X_selected = selector.fit_transform(X,y)

Насколько плохо выключен мы можем быть в реальности?Что ж, опять же нетрудно увидеть: предположим, что после того, как мы закончили с нашей моделью и у нас развернуто ее (ожидая что-то похожее на 76% точности на практике с новыми невидимыми данными), мы получим некоторые действительно новые данные:

X_new = np.random.randn(500, 10000)

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

y_new = np.random.choice(2, size=500)

Как наша модель будет работать здесь, когда столкнется с этими действительно невидимыми данными?Нетрудно проверить:

# select the same features in the new data
X_new_selected = selector.transform(X_new)
# predict and get the accuracy:
y_new_pred = lr.predict(X_new_selected)
accuracy_score(y_new, y_new_pred)
# 0.45200000000000001

Ну, это правда: мы отправили нашу модель в бой, думая, что она способна с точностью ~ 76%, но на самом деле она работает как случайное предположение...


Итак, давайте теперь посмотрим правильную процедуру (т. Е. Сначала разделим, и выберем функции, основываясь только на наборе training ):

# split first
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)
# then select features using the training set only
selector = SelectKBest(k=25)
X_train_selected = selector.fit_transform(X_train,y_train)

# fit again a simple logistic regression
lr.fit(X_train_selected,y_train)
# select the same features on the test set, predict, and get the test accuracy:
X_test_selected = selector.transform(X_test)
y_pred = lr.predict(X_test_selected)
accuracy_score(y_test, y_pred)
# 0.52800000000000002

Там, где точность теста 0f 0,528 достаточно близка к теоретически предсказанному одному из 0,5 в таком случае (т. Е. Фактически случайному угадыванию).

Престижность Якобу Шрайберу за предоставление простой идеи(отметьте все темы , они содержат другие полезные примеры), хотя и в несколько ином контексте, чем тот, о котором вы спрашиваете здесь (перекрестная проверка):

enter image description here

...