Как создать тестовые и обучающие выборки из одного DataFrame с помощью pandas?
У меня есть довольно большой набор данных в виде датафрейма, и я хотел бы узнать, как можно разбить этот датафрейм на две случайные выборки (80% для тренировки и 20% для тестирования).
Спасибо!
5 ответ(ов)
Вы можете использовать randn
из библиотеки NumPy для генерации случайных данных, как показано в следующем примере:
import pandas as pd
import numpy as np
# Генерируем DataFrame с 100 строками и 2 столбцами случайных значений
df = pd.DataFrame(np.random.randn(100, 2))
# Создаем маску для разделения данных на обучающую и тестовую выборки
msk = np.random.rand(len(df)) < 0.8
# Формируем обучающую выборку
train = df[msk]
# Формируем тестовую выборку
test = df[~msk]
Чтобы убедиться, что разбиение произошло корректно, можно вывести длину обеих выборок:
# Выводим длину тестовой выборки
print(len(test)) # должно быть около 21
# Выводим длину обучающей выборки
print(len(train)) # должно быть около 79
Таким образом, вы сможете легко разделить ваш набор данных на обучающую и тестовую выборки с помощью NumPy и pandas.
Использование метода sample
в Pandas позволяет случайным образом выбирать данные для обучения и тестирования следующим образом:
train = df.sample(frac=0.8, random_state=200)
test = df.drop(train.index)
Здесь параметр frac=0.8
указывает, что мы выбираем 80% данных для обучающей выборки, а оставшиеся 20% автоматически составляют тестовую выборку. При использовании одного и того же значения random_state
вы всегда будете получать один и тот же набор данных в обучающей и тестовой выборках. Это добавляет уровень повторяемости, сохраняя при этом случайное разделение данных. Такой подход особенно полезен для обеспечения устойчивости к изменениям в обучении вашей модели.
Если вы хотите разделить данные на обучающую и тестовую выборки, то я бы использовал функцию train_test_split
из библиотеки scikit-learn. Вы можете сгенерировать индексы для выборок следующим образом:
from sklearn.model_selection import train_test_split
y = df.pop('output') # Извлекаем целевую переменную
X = df # Оставляем только признаки
# Разделяем данные на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(X.index, y, test_size=0.2)
# Получаем DataFrame для обучающей выборки
X_train_df = X.iloc[X_train] # Вернёт DataFrame для обучающей выборки
Здесь X_train
будет содержать индексы обучающей выборки, а X.iloc[X_train]
вернет соответствующие строки из оригинального DataFrame X
. Убедитесь, что вы корректно извлекаете целевую переменную y
из вашего DataFrame с помощью pop()
.
Нет необходимости конвертировать в NumPy. Просто используйте DataFrame из pandas для выполнения разделения, и он вернёт DataFrame.
from sklearn.model_selection import train_test_split
train, test = train_test_split(df, test_size=0.2)
Если вы хотите разделить X
и y
, то используйте следующий код:
X_train, X_test, y_train, y_test = train_test_split(df[list_of_x_cols], df[y_col], test_size=0.2)
А если вы хотите разделить весь DataFrame:
X, y = df[list_of_x_cols], df[y_col]
Вопрос: Как правильно создать обучающую, тестовую и валидационную выборки для различных случаев в sklearn?
Ответ:
Существует множество способов создания обучающих/тестовых и даже валидационных выборок в зависимости от ваших потребностей и структуры данных. Вот несколько типичных случаев:
Случай 1: Классический способ train_test_split
без дополнительных опций.
from sklearn.model_selection import train_test_split
train, test = train_test_split(df, test_size=0.3)
В этом примере данные делятся на обучающую (70%) и тестовую (30%) выборки без каких-либо дополнительных параметров.
Случай 2: Для очень небольших наборов данных (<500 строк) лучше использовать кросс-валидацию. В результате вы получите предсказания для каждой строки обучающего набора.
from sklearn.model_selection import KFold
kf = KFold(n_splits=10, random_state=0)
y_hat_all = []
for train_index, test_index in kf.split(X, y):
reg = RandomForestRegressor(n_estimators=50, random_state=0)
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
clf = reg.fit(X_train, y_train)
y_hat = clf.predict(X_test)
y_hat_all.append(y_hat)
Здесь используется KFold для разделения данных на 10 частей, что позволяет каждому примеру участвовать в обучении и тестировании.
Случай 3а: Небалансированные наборы данных для задач классификации. Аналогично случаю 1, вы можете использовать параметр stratify
:
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, test_size=0.3)
Это гарантирует, что выборка будет сбалансирована по классам.
Случай 3б: Небалансированные наборы данных для задач классификации с использованием кросс-валидации. Используйте StratifiedKFold
для сбалансированного разделения:
from sklearn.model_selection import StratifiedKFold
kf = StratifiedKFold(n_splits=10, random_state=0)
y_hat_all = []
for train_index, test_index in kf.split(X, y):
reg = RandomForestRegressor(n_estimators=50, random_state=0)
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
clf = reg.fit(X_train, y_train)
y_hat = clf.predict(X_test)
y_hat_all.append(y_hat)
Этот подход позволяет эффективно работать с небалансированными данными, обеспечивая равноценное представительство классов.
Случай 4: Вы хотите создать обучающие, тестовые и валидационные наборы на больших данных для настройки гиперпараметров (60% — обучение, 20% — тестирование, 20% — валидация).
from sklearn.model_selection import train_test_split
X_train, X_test_val, y_train, y_test_val = train_test_split(X, y, test_size=0.6)
X_test, X_val, y_test, y_val = train_test_split(X_test_val, y_test_val, stratify=y, test_size=0.5)
Сначала мы делим данные на тренировочный набор и временный набор (тест и валидация), а затем временный набор разбивается на тестовый и валидационный.
Каждый из этих подходов может быть адаптирован в зависимости от конкретной задачи и структуры ваших данных.
Преобразование списка словарей в DataFrame pandas
Объединение двух столбцов текста в DataFrame pandas
Импорт нескольких CSV-файлов в pandas и объединение в один DataFrame
Получить список из колонки или строки DataFrame в pandas?
Выбор строки из pandas Series/DataFrame по целочисленному индексу