Привет! Ты загрузил данные, изучил их, построил графики… Но вот проблема: один признак измеряется в тысячах, а другой — в единицах. Алгоритмы машинного обучения могут принять большие числа за более важные признаки. Как это исправить? С помощью масштабирования!
В этой статье мы разберём:
- Зачем нужно масштабирование
StandardScaler— стандартизация (среднее = 0, дисперсия = 1)MinMaxScaler— нормализация в диапазон [0, 1]- Как применять, чтобы не было утечки данных
- Какой метод когда выбрать
- Что нужно знать перед началом
- Основная часть
- Зачем масштабировать данные?
- StandardScaler — стандартизация
- MinMaxScaler — нормализация
- Сравнение методов
- Как правильно применять: fit() и transform()
- Работа с Pipeline
- Пример с Iris: сравнение методов
- Задачи для закрепления
- Нюансы и подводные камни
- StandardScaler чувствителен к выбросам
- MinMaxScaler чувствителен к выбросам
- fit на train, transform на test
- Частые ошибки и как их избежать
- Ошибка 1: fit_transform на всём наборе
- Ошибка 2: Забыл масштабировать категориальные признаки
- Ошибка 3: Не сохранил scaler после обучения
- Шпаргалка
- Заключение
- КВИЗ
- Что дальше?
Что нужно знать перед началом
Для этого урока тебе понадобится:
- Установленный scikit-learn (
pip install scikit-learn) - Базовое понимание машинного обучения
- Знание, что такое признаки (X) и целевая переменная (y)
Совет: Масштабирование — обязательный шаг для многих алгоритмов. Не пропускай его!
Основная часть
Зачем масштабировать данные?
Представь, что у тебя два признака: возраст (от 0 до 100) и зарплата (от 0 до 1 000 000). Алгоритмы, основанные на расстоянии (KNN, SVM), будут считать, что зарплата в 10 000 раз важнее возраста, просто потому что числа больше. Это неправильно!
Какие алгоритмы требуют масштабирования:
- K-ближайших соседей (KNN)
- Метод опорных векторов (SVM)
- Линейная и логистическая регрессия с регуляризацией
- Нейронные сети
- PCA и другие методы снижения размерности
Какие алгоритмы НЕ требуют масштабирования:
- Деревья решений
- Случайный лес
- Градиентный бустинг
Совет: Для алгоритмов на основе расстояний масштабирование критически важно. Для деревьев — необязательно, но иногда помогает ускорить обучение.
StandardScaler — стандартизация
StandardScaler преобразует данные так, чтобы среднее значение стало 0, а стандартное отклонение — 1.
Формула:
z = (x — mean) / std
Что происходит:
- Каждое значение центрируется (вычитается среднее)
- Масштабируется (делится на стандартное отклонение)
- Результат: среднее = 0, дисперсия = 1
from sklearn.preprocessing import StandardScaler
import numpy as np
# Пример данных
X = np.array([[1, 2], [3, 4], [5, 6]])
# Создаём scaler
scaler = StandardScaler()
# Обучаем и преобразуем
X_scaled = scaler.fit_transform(X)
print("До масштабирования:")
print(X)
print("\nПосле StandardScaler:")
print(X_scaled)
print(f"\nСреднее: {X_scaled.mean(axis=0)}")
print(f"Стандартное отклонение: {X_scaled.std(axis=0)}")Результат:
До масштабирования:
[[1 2]
[3 4]
[5 6]]
После StandardScaler:
[[-1.22474487 -1.22474487]
[ 0. 0. ]
[ 1.22474487 1.22474487]]
Среднее: [0. 0.]
Стандартное отклонение: [1. 1.]Совет: StandardScaler подходит для алгоритмов, которые предполагают нормальное распределение данных (линейная регрессия, логистическая регрессия, SVM, PCA).
MinMaxScaler — нормализация
MinMaxScaler сжимает данные в заданный диапазон (по умолчанию от 0 до 1).
Формула:
x_scaled = (x — min) / (max — min)
Что происходит:
- Находится минимум и максимум
- Все значения линейно преобразуются в диапазон [0, 1]
- Сохраняется относительный порядок значений
from sklearn.preprocessing import MinMaxScaler
import numpy as np
# Пример данных
X = np.array([[1, 2], [3, 4], [5, 6]])
# Создаём scaler
scaler = MinMaxScaler()
# Обучаем и преобразуем
X_scaled = scaler.fit_transform(X)
print("До масштабирования:")
print(X)
print("\nПосле MinMaxScaler:")
print(X_scaled)
print(f"\nМинимум: {X_scaled.min(axis=0)}")
print(f"Максимум: {X_scaled.max(axis=0)}")Результат:
До масштабирования:
[[1 2]
[3 4]
[5 6]]
После MinMaxScaler:
[[0. 0. ]
[0.5 0.5]
[1. 1. ]]
Минимум: [0. 0.]
Максимум: [1. 1.]Совет: MinMaxScaler хорошо работает, когда нужно сохранить нулевые значения или когда данные имеют известные границы. Идеален для нейросетей и KNN.
Сравнение методов
Совет: Если в данных есть выбросы, рассмотри
RobustScaler— он использует медиану и квартили.
Как правильно применять: fit() и transform()
Золотое правило масштабирования:
Учимся на тренировочной выборке, применяем и к тренировочной, и к тестовой .
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
# Загружаем данные
iris = load_iris()
X, y = iris.data, iris.target
# Разделяем на train/test
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42
)
# 1. Создаём scaler
scaler = StandardScaler()
# 2. Обучаем на ТРЕНИРОВОЧНЫХ данных (fit)
scaler.fit(X_train)
# 3. Применяем к тренировочным (transform)
X_train_scaled = scaler.transform(X_train)
# 4. Применяем к тестовым (transform) — используем те же параметры!
X_test_scaled = scaler.transform(X_test)
print("Среднее на train:", X_train_scaled.mean(axis=0))
print("Среднее на test:", X_test_scaled.mean(axis=0))Совет: Никогда не используй
fit_transform()на всём наборе данных сразу! Это называется утечка данных (data leakage) и даст завышенные результаты .
Работа с Pipeline
Для удобства можно объединить масштабирование и обучение в один конвейер:
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# Данные
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
iris.data, iris.target, test_size=0.3, random_state=42
)
# Создаём Pipeline
pipeline = Pipeline([
('scaler', StandardScaler()),
('classifier', LogisticRegression(max_iter=1000))
])
# Обучаем (scale и модель автоматически)
pipeline.fit(X_train, y_train)
# Предсказываем (scale применяется автоматически)
accuracy = pipeline.score(X_test, y_test)
print(f"Точность: {accuracy:.2%}")Совет: Pipeline гарантирует, что масштабирование будет применяться корректно при кросс-валидации.
Пример с Iris: сравнение методов
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
# Загружаем данные
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
def evaluate_scaler(scaler, name):
# Масштабируем
scaler.fit(X_train)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)
# Обучаем KNN
model = KNeighborsClassifier(n_neighbors=5)
model.fit(X_train_scaled, y_train)
# Оцениваем
y_pred = model.predict(X_test_scaled)
acc = accuracy_score(y_test, y_pred)
print(f"{name}: {acc:.2%}")
# Без масштабирования
model = KNeighborsClassifier(n_neighbors=5)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
print(f"Без масштабирования: {accuracy_score(y_test, y_pred):.2%}")
# С масштабированием
evaluate_scaler(StandardScaler(), "StandardScaler")
evaluate_scaler(MinMaxScaler(), "MinMaxScaler")Результат (примерный):
Без масштабирования: 93.33%
StandardScaler: 96.67%
MinMaxScaler: 96.67%Совет: В датасете Iris масштабирование даёт небольшое улучшение. На данных с разными масштабами разница может быть огромной!
Задачи для закрепления
Задача 1. Объясни, зачем нужно масштабирование признаков.
Задача 2. В чём разница между StandardScaler и MinMaxScaler?
Задача 3. Почему нельзя использовать fit_transform() на всём наборе данных сразу?
Задача 4. Какой метод масштабирования лучше выбрать для KNN?
Задача 5. Создай Pipeline с StandardScaler и логистической регрессией.
Ответы:
Задача 1.
Масштабирование нужно, чтобы признаки с большими числовыми значениями не доминировали над признаками с маленькими значениями. Алгоритмы, основанные на расстоянии (KNN, SVM), чувствительны к этому.
Задача 2.
- StandardScaler: делает среднее = 0, дисперсию = 1. Не ограничивает диапазон.
- MinMaxScaler: сжимает данные в диапазон [0, 1].
Задача 3.
fit_transform() на всём наборе приводит к утечке данных — параметры масштабирования (mean, std, min, max) вычисляются с учётом тестовых данных, что даёт завышенную оценку качества.
Задача 4.
Для KNN подходят оба метода. MinMaxScaler часто работает лучше, потому что KNN чувствителен к относительным расстояниям, и диапазон [0, 1] даёт более понятные расстояния.
Задача 5.
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
pipeline = Pipeline([
('scaler', StandardScaler()),
('classifier', LogisticRegression())
])
pipeline.fit(X_train, y_train)Нюансы и подводные камни
StandardScaler чувствителен к выбросам
Выбросы сильно влияют на среднее и стандартное отклонение . Если в данных есть выбросы, рассмотри RobustScaler.
MinMaxScaler чувствителен к выбросам
Выбросы сдвигают min и max, и основная часть данных может оказаться сжатой в узкий диапазон.
fit на train, transform на test
Это не просто рекомендация, а правило. Нарушение приведёт к неправильной оценке модели.
Частые ошибки и как их избежать
Ошибка 1: fit_transform на всём наборе
# Утечка данных
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# Правильно
scaler.fit(X_train)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)Ошибка 2: Забыл масштабировать категориальные признаки
Масштабируй только числовые признаки. Категориальные кодируй отдельно (OneHotEncoder).
Ошибка 3: Не сохранил scaler после обучения
Если ты сохраняешь модель, сохраняй и scaler, чтобы применять его к новым данным:
import joblib
joblib.dump(scaler, 'scaler.pkl')
joblib.dump(model, 'model.pkl')Шпаргалка
| Что нужно | Как пишется |
|---|---|
| Импорт StandardScaler | from sklearn.preprocessing import StandardScaler |
| Импорт MinMaxScaler | from sklearn.preprocessing import MinMaxScaler |
| Создать scaler | scaler = StandardScaler() |
| Обучить | scaler.fit(X_train) |
| Преобразовать | X_scaled = scaler.transform(X) |
| Обучить и преобразовать | X_scaled = scaler.fit_transform(X) |
| Pipeline | Pipeline([('scaler', StandardScaler()), ('model', LogisticRegression())]) |
Заключение
Сегодня мы узнали:
- Зачем масштабировать данные перед обучением
- StandardScaler — стандартизация (среднее 0, дисперсия 1)
- MinMaxScaler — нормализация в [0, 1]
- Правило: fit на train, transform на test
- Pipeline для автоматизации
Какое масштабирование выбрать?
| Сценарий | Рекомендация |
|---|---|
| Линейная регрессия, SVM, PCA | StandardScaler |
| Нейросети, KNN | MinMaxScaler |
| Есть выбросы | RobustScaler |
| Нужно сохранить ноль | MinMaxScaler |




