Как разбить данные на 3 набора (поезд, валидация и тест)?
У меня есть pandas dataframe, и я хочу разделить его на 3 отдельных набора. Я знаю, что используя train_test_split от sklearn.cross_validation
, можно разделить данные на два набора (поезд и тест). Однако я не мог найти решения о разделении данных на три набора. Желательно, чтобы я хотел иметь индексы исходных данных.
Я знаю, что обходным решением было бы использовать train_test_split
два раза и как-то настроить индексы. Но существует ли более стандартный/встроенный способ разделения данных на 3 набора вместо 2?
Ответы
Ответ 1
Numpy решение. Мы разделим наш набор данных на следующие части:
- 60% - поездный набор,
- 20% - проверочный набор,
- 20% - тестовый набор
In [305]: train, validate, test = np.split(df.sample(frac=1), [int(.6*len(df)), int(.8*len(df))])
In [306]: train
Out[306]:
A B C D E
0 0.046919 0.792216 0.206294 0.440346 0.038960
2 0.301010 0.625697 0.604724 0.936968 0.870064
1 0.642237 0.690403 0.813658 0.525379 0.396053
9 0.488484 0.389640 0.599637 0.122919 0.106505
8 0.842717 0.793315 0.554084 0.100361 0.367465
7 0.185214 0.603661 0.217677 0.281780 0.938540
In [307]: validate
Out[307]:
A B C D E
5 0.806176 0.008896 0.362878 0.058903 0.026328
6 0.145777 0.485765 0.589272 0.806329 0.703479
In [308]: test
Out[308]:
A B C D E
4 0.521640 0.332210 0.370177 0.859169 0.401087
3 0.333348 0.964011 0.083498 0.670386 0.169619
[int(.6*len(df)), int(.8*len(df))]
- это indices_or_sections
массив для numpy.split().
Вот небольшая демонстрация для использования np.split()
- позвольте разбить массив из 20 элементов на следующие части: 80%, 10%, 10%:
In [45]: a = np.arange(1, 21)
In [46]: a
Out[46]: array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
In [47]: np.split(a, [int(.8 * len(a)), int(.9 * len(a))])
Out[47]:
[array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
array([17, 18]),
array([19, 20])]
Ответ 2
Примечание:
Была написана функция для обработки заполнения создания рандомизированного набора. Не следует полагаться на расщепление множеств, которое не рандомизирует множества.
import numpy as np
import pandas as pd
def train_validate_test_split(df, train_percent=.6, validate_percent=.2, seed=None):
np.random.seed(seed)
perm = np.random.permutation(df.index)
m = len(df.index)
train_end = int(train_percent * m)
validate_end = int(validate_percent * m) + train_end
train = df.iloc[perm[:train_end]]
validate = df.iloc[perm[train_end:validate_end]]
test = df.iloc[perm[validate_end:]]
return train, validate, test
Демонстрация
np.random.seed([3,1415])
df = pd.DataFrame(np.random.rand(10, 5), columns=list('ABCDE'))
df
![enter image description here]()
train, validate, test = train_validate_test_split(df)
train
![enter image description here]()
validate
![enter image description here]()
test
![enter image description here]()
Ответ 3
Однако один из подходов к разделению набора данных на train
, test
, cv
с 0.6
, 0.2
, 0.2
состоит в том, train_test_split
дважды использовать метод train_test_split
.
from sklearn.model_selection import train_test_split
x, x_test, y, y_test = train_test_split(xtrain,labels,test_size=0.2,train_size=0.8)
x_train, x_cv, y_train, y_cv = train_test_split(x,y,test_size = 0.25,train_size =0.75)
Ответ 4
Один из подходов - использовать функцию train_test_split дважды.
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test
= train_test_split(X, y, test_size=0.2, random_state=1)
X_train, X_val, y_train, y_val
= train_test_split(X_train, y_train, test_size=0.25, random_state=1)
Ответ 5
Очень удобно использовать train_test_split
без выполнения переиндексации после разделения на несколько наборов и без написания дополнительного кода. В приведенном выше наилучшем ответе не упоминается, что разделение двух раз с использованием train_test_split
без изменения размеров разделов не даст изначально предполагаемый раздел:
x_train, x_remain = train_test_split(x, test_size=(val_size + test_size))
Тогда часть проверочных и тестовых наборов в x_remain изменится и может быть посчитана как
new_test_size = np.around(test_size / (val_size + test_size), 2)
# To preserve (new_test_size + new_val_size) = 1.0
new_val_size = 1.0 - new_test_size
x_val, x_test = train_test_split(x_remain, test_size=new_test_size)
В этом случае все начальные разделы сохраняются.