Что такое хороший способ разбиения массива NumPy случайным образом на набор данных для обучения и тестирования/валидации? Нечто похожее на функции cvpartition
или crossvalind
в Matlab.
Как разбить/разбить набор данных на учебные и тестовые наборы данных для, например, перекрестной проверки?
Ответ 1
Если вы хотите разделить набор данных один раз на две половины, вы можете использовать numpy.random.shuffle
или numpy.random.permutation
если вам нужно отслеживать индексы:
import numpy
# x is your dataset
x = numpy.random.rand(100, 5)
numpy.random.shuffle(x)
training, test = x[:80,:], x[80:,:]
или же
import numpy
# x is your dataset
x = numpy.random.rand(100, 5)
indices = numpy.random.permutation(x.shape[0])
training_idx, test_idx = indices[:80], indices[80:]
training, test = x[training_idx,:], x[test_idx,:]
Есть много способов многократно разделить один и тот же набор данных для перекрестной проверки. Одна из стратегий заключается в повторной выборке из набора данных с повторением:
import numpy
# x is your dataset
x = numpy.random.rand(100, 5)
training_idx = numpy.random.randint(x.shape[0], size=80)
test_idx = numpy.random.randint(x.shape[0], size=20)
training, test = x[training_idx,:], x[test_idx,:]
Наконец, sklearn содержит несколько методов перекрестной проверки (k-fold, left -n-out,...). Он также включает в себя более продвинутые методы "стратифицированной выборки", которые создают раздел данных, который сбалансирован по некоторым функциям, например, чтобы убедиться, что в наборе обучения и тестирования есть одинаковое количество положительных и отрицательных примеров.
Ответ 2
Есть еще один вариант, который влечет за собой использование scikit-learn. Как описывает Scikit Wiki, вы можете просто использовать следующие инструкции:
from sklearn.model_selection import train_test_split
data, labels = np.arange(10).reshape((5, 2)), range(5)
data_train, data_test, labels_train, labels_test = train_test_split(data, labels, test_size=0.20, random_state=42)
Таким образом, вы можете синхронизировать метки для данных, которые вы пытаетесь разделить на тренировку и тестирование.
Ответ 3
Просто заметьте. В случае, если вы хотите наборы для тренировки, тестирования и проверки, вы можете сделать это:
from sklearn.cross_validation import train_test_split
X = get_my_X()
y = get_my_y()
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
x_test, x_val, y_test, y_val = train_test_split(x_test, y_test, test_size=0.5)
Эти параметры будут давать 70% для обучения, а 15% - для тестирования и набора значений. Надеюсь это поможет.
Ответ 4
Поскольку модуль sklearn.cross_validation
устарел, вы можете использовать:
import numpy as np
from sklearn.model_selection import train_test_split
X, y = np.arange(10).reshape((5, 2)), range(5)
X_trn, X_tst, y_trn, y_tst = train_test_split(X, y, test_size=0.2, random_state=42)
Ответ 5
Вы также можете рассмотреть разбитое разделение на набор для обучения и тестирования. Начальное подразделение также генерирует тренировку и тестирование, установленное случайным образом, но таким образом, что сохраняются исходные пропорции классов. Это делает тренировочные и тестовые наборы лучше отражать свойства исходного набора данных.
import numpy as np
def get_train_test_inds(y,train_proportion=0.7):
'''Generates indices, making random stratified split into training set and testing sets
with proportions train_proportion and (1-train_proportion) of initial sample.
y is any iterable indicating classes of each observation in the sample.
Initial proportions of classes inside training and
testing sets are preserved (stratified sampling).
'''
y=np.array(y)
train_inds = np.zeros(len(y),dtype=bool)
test_inds = np.zeros(len(y),dtype=bool)
values = np.unique(y)
for value in values:
value_inds = np.nonzero(y==value)[0]
np.random.shuffle(value_inds)
n = int(train_proportion*len(value_inds))
train_inds[value_inds[:n]]=True
test_inds[value_inds[n:]]=True
return train_inds,test_inds
y = np.array([1,1,2,2,3,3])
train_inds,test_inds = get_train_test_inds(y,train_proportion=0.5)
print y[train_inds]
print y[test_inds]
Этот код выводит:
[1 2 3]
[1 2 3]
Ответ 6
Я написал функцию для моего собственного проекта, чтобы сделать это (однако он не использует numpy):
def partition(seq, chunks):
"""Splits the sequence into equal sized chunks and them as a list"""
result = []
for i in range(chunks):
chunk = []
for element in seq[i:len(seq):chunks]:
chunk.append(element)
result.append(chunk)
return result
Если вы хотите, чтобы фрагменты были рандомизированы, просто перетасуйте список, прежде чем передавать его.
Ответ 7
Вот код для разбиения данных на n = 5 раз в стратифицированном виде
% X = data array
% y = Class_label
from sklearn.cross_validation import StratifiedKFold
skf = StratifiedKFold(y, n_folds=5)
for train_index, test_index in skf:
print("TRAIN:", train_index, "TEST:", test_index)
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
Ответ 8
Спасибо, спасибо за ваш ответ. Я просто изменил его, чтобы избежать (1) замены во время выборки (2) дублированные экземпляры произошли как в обучении, так и в тестировании:
training_idx = np.random.choice(X.shape[0], int(np.round(X.shape[0] * 0.8)),replace=False)
training_idx = np.random.permutation(np.arange(X.shape[0]))[:np.round(X.shape[0] * 0.8)]
test_idx = np.setdiff1d( np.arange(0,X.shape[0]), training_idx)
Ответ 9
После некоторого прочтения и учета (многих...) различных способов разделения данных для обучения и тестирования, я решил провести время!
Я использовал 4 разных метода (ни один из них не использует библиотеку sklearn, которая, я уверен, даст наилучшие результаты, учитывая, что она хорошо разработана и протестирована):
- перемешать всю матрицу обр, а затем разделить данные для обучения и проверки
- перемешать индексы, а затем назначить его х и у, чтобы разделить данные
- так же, как метод 2, но более эффективным способом сделать это
- используя pandas dataframe для разделения
метод 3 выиграл, безусловно, с самым коротким временем, после этого метода 1, а метод 2 и 4 оказался действительно неэффективным.
Код для 4 различных методов, которые я рассчитал:
import numpy as np
arr = np.random.rand(100, 3)
X = arr[:,:2]
Y = arr[:,2]
spl = 0.7
N = len(arr)
sample = int(spl*N)
#%% Method 1: shuffle the whole matrix arr and then split
np.random.shuffle(arr)
x_train, x_test, y_train, y_test = X[:sample,:], X[sample:, :], Y[:sample, ], Y[sample:,]
#%% Method 2: shuffle the indecies and then shuffle and apply to X and Y
train_idx = np.random.choice(N, sample)
Xtrain = X[train_idx]
Ytrain = Y[train_idx]
test_idx = [idx for idx in range(N) if idx not in train_idx]
Xtest = X[test_idx]
Ytest = Y[test_idx]
#%% Method 3: shuffle indicies without a for loop
idx = np.random.permutation(arr.shape[0]) # can also use random.shuffle
train_idx, test_idx = idx[:sample], idx[sample:]
x_train, x_test, y_train, y_test = X[train_idx,:], X[test_idx,:], Y[train_idx,], Y[test_idx,]
#%% Method 4: using pandas dataframe to split
import pandas as pd
df = pd.read_csv(file_path, header=None) # Some csv file (I used some file with 3 columns)
train = df.sample(frac=0.7, random_state=200)
test = df.drop(train.index)
А для этого времени минимальное время выполнения из 3 повторений 1000 циклов:
- Метод 1: 0,35883826200006297 секунд
- Метод 2: 1,7157016959999964 секунд
- Метод 3: 1,7786616719995582 секунд
- Метод 4: 0,07562861499991413 секунд
Я надеюсь, что это полезно!