May 25, 2022

Разделение данных на выборки

Рассмотрим способы разделения данных на выборки для обучения, валидации и теста модели. Сначала создадим демонстрационный набор:

import pandas as pd
import numpy as np
np.random.seed(0)
df = pd.DataFrame({'y':[1,0,1,0,0,0,1,1,1,0],
                   'val1':[np.nan, 6, 3, np.nan, np.nan, 8, -5 , 2, 3, 4],
                   'val2':[1, np.nan, 3, 2, -9, 3, np.nan, 3, 4, 5]
                   }, index=['one', 'two', 'three', 'four', 'five',
                              'six', 'seven', 'eight', 'nine', 'ten'])

df

Наиболее популярно для разделения на выборки использовать возможности библиотеки Scikit-learn. Например, ее функция train_test_split позволяет сформировать готовые датасеты, указав размер тестовой выборки:

from sklearn.model_selection import train_test_split
X_tr, X_ts, y_tr, y_ts = train_test_split(df.drop(columns='y'), df['y'], test_size=0.2)

display(X_tr), display(X_ts)

Одного зачастую удобнее использовать порядковые номера строк, так как с такими индикаторами разбиения удобнее работать (например, для воспроизведения разбиения в библиотеке машинного обучения H2O). Это можно сделать с train_test_split:

tr_idx, ts_idx = train_test_split(range(df.shape[0]), test_size=0.2)
display(tr_idx), display(ts_idx)

display(df.iloc[tr_idx]), display(df.iloc[ts_idx])

Другой способ - использование функции split библиотеки NumPy. Так как зачастую приходится создавать не только обучающую и тестовую выборки, но еще и валидационную, с ее помощью это сделать проще (для train_test_split потребовался бы вызов два раза):

idx = np.arange(df.shape[0])
np.random.shuffle(idx)

tr_idx, val_idx, ts_idx = np.split(idx, [round(0.8*len(idx)), round(0.9*len(idx))])
tr_idx, val_idx, ts_idx 

Чтобы функция сработала, ей помимо индексов потребуется указать номера строк - "разделителей" (также индексы перемешиваем перед этим). А вот так собираем результирующие датасеты:

display(df.iloc[tr_idx]), display(df.iloc[val_idx]), display(df.iloc[ts_idx])

Для разбиения можно использовать и другие способы из sklearn (но они предполагают деление на две выборки, поэтому и придется вызывать пару раз). Вот пример с ShuffleSplit:

from sklearn.model_selection import ShuffleSplit
sp = ShuffleSplit(test_size=0.2)
tr_idx, ts_idx = next(sp.split(df))
tr_idx, ts_idx

Не пропустите ничего интересного и подписывайтесь на страницы канала в других социальных сетях:

Яндекс Дзен

Telegram