Какие способы нормализации распределения данных существуют
Что проверяют
Различаете ли вы масштабирование признака и изменение формы его распределения. Это разные операции, и следом обычно спрашивают, что вы сделаете с признаком с тяжёлым правым хвостом и каким моделям это вообще нужно.
Как отвечать
Сначала линейные преобразования, они меняют масштаб, но не форму:
- стандартизация (
StandardScaler): вычитает среднее и делит на стандартное отклонение. Скошенное распределение остаётся скошенным; - Min-Max (
MinMaxScaler): сжатие в диапазон от 0 до 1, один выброс сплющивает все остальные значения; RobustScaler: медиана и межквартильный размах, выбросы на масштаб почти не влияют.
Затем нелинейные, которые приближают распределение к нормальному:
- логарифм:
np.log1pдля неотрицательных данных с длинным хвостом: цены, доходы, счётчики; - Box-Cox: подбирает степень по данным, работает только на строго положительных значениях;
- Yeo-Johnson: то же для нуля и отрицательных. В scikit-learn оба живут в
PowerTransformer, по умолчаниюmethod="yeo-johnson"и стандартизация после; QuantileTransformerсoutput_distribution="normal": переводит в ранги и отображает на нормальное распределение. Даёт нужную форму, но теряет расстояния между значениями.
Преобразователь обучают только на train и внутри Pipeline, иначе статистики теста утекают в модель:
pipe = make_pipeline(PowerTransformer(), LogisticRegression())
pipe.fit(X_train, y_train)Кому это нужно: линейным моделям, KNN, SVM, нейросетям, всему с регуляризацией или расстояниями. Деревьям и бустингу монотонное преобразование признака почти ничего не даёт.
Где спотыкаются
Говорят, что StandardScaler делает распределение нормальным. Он только сдвигает и масштабирует.
Делают fit_transform на всём датасете до разбиения. Метрика на валидации выходит завышенной, это классическая утечка данных.
Логарифмируют целевую переменную и забывают, что предсказание после np.expm1 ближе к медиане, чем к среднему. Сюда же путаница с Normalizer: он приводит к единичной длине строки, а не столбцы.