Почему использовать Scaler.fit только на x_train, а не на x_test для нормализации значений с помощью MinMaxScaler?

Вопрос или проблема

При нормализации данных все говорят, что необходимо использовать fit только на x_train и не на x_test? Почему мы не должны использовать fit на x_test?

Если мы не должны использовать fit на x_test, то почему нужно применять только трансформацию на x_test?

from sklearn.preprocessing import MinMaxScaler
Scaler=MinMaxScaler()
Scaler.fit(X_train)
x_train=Scaler.transform(x_train)
x_test=Scaler.transform(x_test)

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

В дополнение к комментарию Oxbowerce, можно рассуждать следующим образом: в реальном случае вы бы ожидали, что распределение данных X_train похоже на данные X_test, поэтому применение MinMaxScaler к данным X_test, обученным “только” на X_train, означает (или должно означать), что нет фактической разницы по сравнению с обучением вместе с X_test; в конце концов, этот скейлер находит минимальные и максимальные значения такого распределения и масштабирует их с помощью этих значений.

Тем не менее, вы могли бы переразобрать ваш трансформатор время от времени в производственной среде, если вы получите все больше данных с доступными новыми данными…

Работа sklearn MinMaxScaler осуществляется следующим образом:

  • операция fit: находит минимальные и максимальные значения вашего столбца признаков (обратите внимание, что это масштабирование применяется отдельно для каждого из ваших атрибутов/столбцов фрейма данных)
  • трансформация: применяет операцию масштабирования с минимальными и максимальными значениями, найдеными на этапе ‘fit’

Пример:

предположим, у нас есть один признак со следующими значениями:
[285, 543, 511, 359, 338, 678, 519, 760, 792, 395, 320, 952, 653, 129, 306, 91, 284, 359, 595, 167, 112, 802, 740, 977, 753, 74, 908, 353, 168, 622, 613, 602, 786, 396, 957, 600, 457, 74, 825, 547, 983, 825, 978, 823, 503, 782, 41, 574, 42, 851, 532, 225, 71, 827, 215, 25, 857, 682, 93, 218, 526, 776, 425, 688, 557, 61, 218, 984, 339, 92, 623, 762, 147, 634, 159, 24, 634, 365, 772, 283, 954, 805, 736, 678, 445, 677, 175, 484, 508, 341, 719, 599, 118, 401, 405, 349, 268, 133, 902, 804]

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

rescaled_X_value = (X_value – feature_values_min) / (feature_values_max – feature_values_min)

Вопрос в том, каковы наши минимальные и максимальные значения? Вот что операция ‘fit’ из scikit-learn MinMaxScaler делает с вашими обучающими данными; суть в том, что после использования этой операции ‘fit’ на обучающей выборке для нахождения минимальных и максимальных значений, вам не нужно повторять это на тестовых данных, вы просто применяете операцию ‘transform’, чтобы лишь пересчитать масштаб тестовый данных.
Давайте посмотрим, как это работает:

Если применить это вручную:

min_max_scaled_train_data = (train_feature_data - train_feature_data.min())/(train_feature_data.max()-train_feature_data.min())
min_max_scaled_train_data[:10]

Результат для первых 10 элементов:

array([0.27111575, 0.54014599, 0.50677789, 0.34827946, 0.32638165,
0.68091762, 0.51511992, 0.76642336, 0.79979145, 0.38581856])

И с использованием scikit-learn scaler:

from sklearn.preprocessing import MinMaxScaler

min_max_scaler = MinMaxScaler()
min_max_scaler.fit(train_feature_data.reshape(-1, 1))

min_max_scaler уже содержит информацию (т.е. минимальные и максимальные значения), которую можно применить к вашим новым данным (например, вашим тестовым данным), без повторного fit. Мы также можем видеть, что результат такой же, как и при выполнении вручную, как описано выше:

min_max_scaler.transform(train_feature_data.reshape(-1, 1))[:10]
array([[0.27111575],
[0.54014599],
[0.50677789],
[0.34827946],
[0.32638165],
[0.68091762],
[0.51511992],
[0.76642336],
[0.79979145],
[0.38581856]])

Для дополнительной проверки вы можете увидеть, что разница между train_data и всеми вашими данными (т.е. train + test) при нахождении минимальных и максимальных значений не так велика, потому что они обе происходят из одного распределения.
Вы можете найти полный код примера здесь

Утечка данных происходит, когда информация из тестового набора используется в процессе обучения модели, прямо или косвенно, что может привести к излишне оптимистичным оценкам производительности. Если вы вызываете scaler.fit(X_test), вы позволяете модели “заглядывать” в тестовые данные во время предобработки, поскольку статистика масштабирования (среднее, стандартное отклонение) будет получена из тестовых данных.

Ответ или решение

Использование MinMaxScaler для нормализации данных требует особого подхода, особенно в отношении данных для обучения и тестирования. Давайте рассмотрим, почему необходимо применять Scaler.fit только на x_train, а Scaler.transform на x_test, и не наоборот.

В начале процесса нормализации осуществляется обучение (fit) MinMaxScaler только на обучающем наборе данных (x_train). Это позволяет модели определить минимальные и максимальные значения векторов признаков в x_train. Использование только обучающих данных в процессе “fit” гарантирует, что параметры масштабирования обучены на выборке, аналогичной реальной.

Проведение “fit” на тестовом наборе (x_test) может привести к утечке данных. Это означает, что информация из тестового набора (которая в реальных условиях отсутствовала бы при развертывании модели) могла бы вмешаться в процесс обучения модели. Это бы исказило репрезентативность оценки модели и создало ложное впечатление о ее эффективности.

После обучения на x_train, следующий шаг — это применение трансформации (transform) как к обучающим, так и к тестовым данным. Используя Scaler.transform, мин и макс значения от обучающей выборки применяются для нормализации тестовых данных (x_test), что поддерживает консистентность и стабильность модели.

Дополнительно, важно осознавать, что в идеальной среде распределение признаков в x_train и x_test будет одинаковым, что делает подобный подход справедливым и оправданным. Переподгонка трансформера через некоторое время возможна, учитывая, что объём данных может изменяться и данные могут становиться доступными.

В условиях реального применения это означает, что данные должны быть структурированы и подготовлены таким образом, чтобы статистические параметры (min и max) обучались исключительно на обучающем наборе, а затем применялись ко всему набору данных. Это позволяет избежать утечки данных и обеспечивает более точную и надежную оценку качества работы модели.

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

Оцените материал
Добавить комментарий

Капча загружается...