Test_train_split с stratify

#python #scikit-learn

#python #scikit-учиться

Вопрос:

Я пытаюсь разделить фрейм данных (~ 188 тыс. строк) на обучающий и тестовый образцы. Столбец (‘FLAG’) является моей целевой переменной, содержащей значение либо 0, либо 1.

Поскольку существует только около 1300 «ФЛАГОВ» со значением 1, я хочу выполнить стратифицированное разделение, чтобы убедиться, что в обоих образцах имеется репрезентативное число значений 1.

Я попытался разделить, используя функцию train_test_split от sklearn:

 train, test = train_test_split(df, test_size=0.2, stratify=df["FLAG"])
 

Моя проблема в том, что результирующий поезд и тестовый образец имеют 177942, соответственно 52 строки. Я бы ожидал чего-то вроде 150400 и 37600 строк.

Мое понимание из чтения документации (sklearn.model_selection.train_test_split) заключается в том, что я должен предоставить свой фрейм данных, test_size и столбец, содержащий целевые классы (т.Е. «ФЛАГ» в моем случае).

Даже общий пример:

 df = pd.DataFrame(data={'a': np.random.rand(100000), 'b': np.random.rand(100000), 'c': 0})
df.loc[np.random.randint(0, 100000, 1000), 'c'] = 1
tr, ts = train_test_split(df, test_size=.2, stratify=df['c'])
print(tr.shape, ts.shape)
 

ВОЗВРАТ: (93105, 3) (38, 3)

Мой список импорта:

 import cx_Oracle
import pandas as pd
from sklearn.model_selection import train_test_split
import numpy as np
 

Моя версия python: 3.7.0
Версия Sklearn: 0.20.3
Версия Pandas: 0.23.4

Комментарии:

1. Очень интересно. Я провел несколько тестов со случайно построенным образцом df, и, похоже, он работает нормально. Вы должны опубликовать некоторые образцы данных, чтобы мы могли воспроизвести вашу проблему. Мой пример df: df = pd.DataFrame(data={'a': np.random.rand(100000), 'b': np.random.rand(100000), 'c': 0}) . Установите около 1000 значений равными 1: df.loc[np.random.randint(0, 100000, 1000), 'c'] = 1 , разделите данные: tr, ts = train_test_split(df, test_size=.2, stratify=df['c']) . проверка фигур: tr.shape Out: (80000, 3) , и число 1s: tr.c.sum() Out: 796 и для ts: 199. Итак, похоже, проблема с вашими данными

2. @Scotty Я попробовал тот же тест. Как ни странно, мой train_test_split делает ту же странную вещь с вашим примером. Т.е. я получаю (93105, 3) и (38, 3) . Теперь я еще больше запутался.

3. @tk78: какие версии python и пакетов вы используете? Можете ли вы поместить весь импорт перед общим кодом и выполнить его повторно (например: возможно, ваш train_test_split переопределен каким-то другим пакетом, и это не тот, который вы думаете)

4. @vladmihaisima я добавил информацию, которую вы просили. Кстати: я просто тестирую эту самую вещь, используя виртуальную среду.

5. @tk78 Какова ваша версия sklean и pandas? Похоже на ошибку…

Ответ №1:

Мои исследования показали, что проблема вызвана переполнением целых чисел. Проблема возникает только на Python 3.7.x 32bit. 64-битная версия работает нормально.

В конце концов я переключился на 64-битный Python, чтобы решить проблему (ранее мне приходилось использовать 32-битную версию из-за несвязанной зависимости от пакета Oracle).