Ответ
Стратификация — это техника разделения набора данных на обучающую и тестовую (или валидационную) выборки, при которой сохраняется исходное распределение значений целевой переменной (или другого важного категориального признака) в каждой из подвыборок.
Зачем это нужно? Без стратификации при случайном разбиении в тестовой выборке может оказаться непропорционально мало примеров редкого класса, что приведет к некорректной оценке модели, особенно для задач с несбалансированными классами.
Пример на Python с scikit-learn:
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as np
# Создадим синтетический несбалансированный датасет
# 1000 примеров, целевая переменная 'target' имеет классы 0 и 1 (90% и 10%)
data = pd.DataFrame({'feature': np.random.randn(1000)})
data['target'] = np.random.choice([0, 1], size=1000, p=[0.9, 0.1])
print('Исходное распределение классов:')
print(data['target'].value_counts(normalize=True))
# 0: 0.90, 1: 0.10
# Разбиение БЕЗ стратификации
X_train_naive, X_test_naive, y_train_naive, y_test_naive = train_test_split(
data[['feature']], data['target'], test_size=0.2, random_state=42
)
print('nБез стратификации в тесте:')
print(y_test_naive.value_counts(normalize=True))
# Может получиться, например, 0: 0.92, 1: 0.08 — класс 1 представлен хуже.
# Разбиение СО стратификацией
X_train, X_test, y_train, y_test = train_test_split(
data[['feature']], data['target'],
test_size=0.2,
stratify=data['target'], # Ключевой параметр
random_state=42
)
print('nСо стратификацией в тесте:')
print(y_test.value_counts(normalize=True))
# Гарантированно будет ~0: 0.90, 1: 0.10 — распределение сохранено.
Где еще применяется?
StratifiedKFold/StratifiedShuffleSplit: Для кросс-валидации, чтобы в каждом фолде было то же распределение классов, что и в исходных данных.- Стратификация по нескольким признакам: Можно создать составной стратифицирующий признак.
Ограничение: Применима только к категориальным (дискретным) целевым переменным.
Ответ 18+ 🔞
Да ты посмотри, какая хитрая жопа эти ваши данные! Ну вот представь: у тебя есть куча записей, и тебе надо их поделить — часть на обучение модели, часть на проверку. Так вот, если ты просто рандомно их тыкать начнёшь, как мартышка, то может выйти полный пиздец.
В чём прикол? А прикол в том, что если у тебя там, допустим, 90% одних случаев и 10% других (редкий класс), то при обычном делении в тестовую выборку может попасть нихуя этих редких случаев. А потом ты будешь орать, что модель говно, потому что она редкое дерьмо вообще не ловит. А это просто ты её так криво проверил, доверия к такой оценке — ноль ебать.
Смотри, как это на Питоне делается, чтоб не облажаться:
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as np
# Наколбасим данных для примера. 1000 строк, целевая 'target' — нули и единицы. 90% нулей, 10% единиц.
data = pd.DataFrame({'feature': np.random.randn(1000)})
data['target'] = np.random.choice([0, 1], size=1000, p=[0.9, 0.1])
print('Как изначально всё лежит:')
print(data['target'].value_counts(normalize=True))
# Примерно: 0: 0.90, 1: 0.10
# ДЕЛИМ КАК ОБЫЧНЫЙ РАСПИЗДЯЙ (без стратификации)
X_train_naive, X_test_naive, y_train_naive, y_test_naive = train_test_split(
data[['feature']], data['target'], test_size=0.2, random_state=42
)
print('nБез стратификации в тестовой выборке:')
print(y_test_naive.value_counts(normalize=True))
# Может вылезти хуй с горы: 0: 0.92, 1: 0.08. Единиц стало ещё меньше, ёпта!
# А ТЕПЕРЬ ДЕЛИМ С МОЗГАМИ (со стратификацией)
X_train, X_test, y_train, y_test = train_test_split(
data[['feature']], data['target'],
test_size=0.2,
stratify=data['target'], # Вот этот волшебный пендель!
random_state=42
)
print('nСо стратификацией в тестовой выборке:')
print(y_test.value_counts(normalize=True))
# Всё чётко: ~0: 0.90, 1: 0.10. Распределение как в оригинале, красота.
Где ещё эту штуку впендюрить можно?
StratifiedKFold/StratifiedShuffleSplit: Когда делаешь кросс-валидацию, чтобы в каждом куске (фолде) пропорции классов были как в исходнике, а не как бог на душу положит.- По нескольким признакам сразу: Можно склеить важные категориальные фичи в один стратифицирующий признак, если тебе надо сохранить баланс не только по целевой, но и по другим штукам.
Но есть и подвох: Эта фигня работает только с категориальными (дискретными) целевыми переменными. Если у тебя там цена квартиры — это уже сплошной поток, и стратифицировать по нему — это ёперный театр, нужно уже что-то другое придумывать.