Разбиение train/test в scikit-learn: stratify и редкий класс

train_test_split разделяет данные на обучающую и тестовую части. С stratify=y разбиение учитывает классы и старается сохранить их доли в обеих частях. X и y нужно передавать вместе, чтобы строки признаков и метки не разъехались.

Короткий пример

from sklearn.model_selection import train_test_split
x = list(range(20))
y = [0] * 16 + [1] * 4
x_train, x_test, y_train, y_test = train_test_split(
    x, y, test_size=0.2, random_state=7, stratify=y)
print(len(y_train), len(y_test))
print(sum(y_train), sum(y_test))

Результат:

16 4
3 1

Стратификация не создаёт новые наблюдения. Для слишком малого класса или слишком маленькой части разбиение может быть невозможно. После разбиения проверьте реальные количества классов; сохранение долей не заменяет временное или групповое разбиение, если его требует задача.

Попробуйте самостоятельно

Ниже — отдельное задание с другими данными. Напишите решение и запустите проверку кода без регистрации. Для последовательного обучения откройте курс.

Документация.

Сохранился ли редкий класс в test

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

Что уже дано

В видимом коде X содержит 100 идентификаторов строк, а y — 90 нулей и 10 единиц в том же порядке. Скрытая подготовка ничего не создаёт.

Что нужно сделать

Разделите X и y совместно двумя способами с test_size=0.2, random_state=31: обычным способом в X_train, X_test, y_train, y_test и с stratify=y в переменные с суффиксом _s. В shares сохраните доли класса 1 в исходном y и обеих частях каждого разбиения под ключами all, ordinary_train, ordinary_test, stratified_train, stratified_test.

Дополнительно реализуйте rare_recall_evaluable(labels): она должна возвращать bool, можно ли на этих истинных метках test вычислить содержательный recall для класса 1. Не полагайтесь на то, что вызов split завершился без ошибки: проверьте наличие класса 1 в полученной части. В recall_evaluable сохраните словарь с результатами функции для обычного и стратифицированного test под ключами ordinary_test и stratified_test. Функция будет проверена и на других наборах меток.

Ввод и вывод

stdin не используется. Печатать через print в stdout ничего не нужно. Проверяются оба разбиения с исходными индексами, доли, вывод о возможности оценить recall и функция на других метках. Исходные строки не меняйте и не добавляйте.

РешениеPython

Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.

Отправьте решение, чтобы увидеть результаты тестов.

Связанные задачи