Quel est un bon moyen de diviser un tableau NumPy de manière aléatoire en un ensemble de données d'entraînement et de test / validation? Quelque chose de similaire aux fonctions cvpartition
ou crossvalind
dans Matlab.
Réponses:
Si vous souhaitez diviser l'ensemble de données une fois en deux moitiés, vous pouvez utiliser numpy.random.shuffle
, ou numpy.random.permutation
si vous avez besoin de garder une trace des indices:
import numpy
# x is your dataset
x = numpy.random.rand(100, 5)
numpy.random.shuffle(x)
training, test = x[:80,:], x[80:,:]
ou
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,:]
Il existe de nombreuses façons de partitionner à plusieurs reprises le même ensemble de données pour la validation croisée . Une stratégie consiste à rééchantillonner à partir de l'ensemble de données, avec répétition:
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,:]
Enfin, sklearn contient plusieurs méthodes de validation croisée (k-fold , Leave -n-out, ...). Il comprend également des méthodes plus avancées «d'échantillonnage stratifié» qui créent une partition des données équilibrée par rapport à certaines caractéristiques, par exemple pour s'assurer qu'il y a la même proportion d'exemples positifs et négatifs dans l'ensemble d'apprentissage et de test.
Il existe une autre option qui implique simplement d'utiliser scikit-learn. Comme le décrit le wiki de scikit , vous pouvez simplement utiliser les instructions suivantes:
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)
De cette façon, vous pouvez synchroniser les étiquettes des données que vous essayez de diviser en entraînement et en test.
Juste une note. Si vous souhaitez entraîner, tester et valider des ensembles, vous pouvez le faire:
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)
Ces paramètres donneront 70% à la formation et 15% chacun pour tester et valider les ensembles. J'espère que cela t'aides.
from sklearn.cross_validation import train_test_split
pour préciser le module que vous utilisez
a=0.7
, b=0.15
, c=0.15
et d = dataset
, N=len(dataset)
puis x_train = dataset[0:int(a*N)]
, x_test = dataset[int(a*N):int((a+b)*N)]
et x_val = dataset[int((a+b)*N):]
.
from sklearn.model_selection import train_test_split
Le sklearn.cross_validation
module étant obsolète, vous pouvez utiliser:
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)
Vous pouvez également envisager une division stratifiée en ensemble de formation et de test. La division Startified génère également un ensemble de formation et de tests de manière aléatoire, mais de manière à conserver les proportions de classe d'origine. Cela permet aux ensembles de formation et de test de mieux refléter les propriétés de l'ensemble de données d'origine.
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]
Ce code génère:
[1 2 3]
[1 2 3]
value_inds
sont vraiment des indices, mais la sortie ne sont pas des indices, seulement des masques.
J'ai écrit une fonction pour mon propre projet pour faire cela (il n'utilise pas numpy, cependant):
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
Si vous voulez que les morceaux soient randomisés, mélangez simplement la liste avant de la transmettre.
Voici un code pour diviser les données en n = 5 fois de manière stratifiée
% 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]
Merci pberkes pour votre réponse. Je viens de le modifier pour éviter (1) le remplacement lors de l'échantillonnage (2) des instances dupliquées se sont produites à la fois lors de la formation et des tests:
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)
Après avoir fait quelques lectures et pris en compte les (nombreuses ..) différentes façons de fractionner les données à entraîner et à tester, j'ai décidé de timeit!
J'ai utilisé 4 méthodes différentes (aucune d'entre elles n'utilise la bibliothèque sklearn, qui, j'en suis sûr, donnera les meilleurs résultats, étant donné que c'est un code bien conçu et testé):
la méthode 3 a gagné de loin avec le temps le plus court, après cette méthode 1, et les méthodes 2 et 4 se sont révélées vraiment inefficaces.
Le code pour les 4 méthodes différentes que j'ai chronométrées:
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)
Et pour les temps, le temps minimum pour exécuter sur 3 répétitions de 1000 boucles est:
J'espère que c'est utile!
Vous devrez probablement non seulement vous diviser en train et tester, mais également effectuer une validation croisée pour vous assurer que votre modèle se généralise. Ici, je suppose que 70% de données d'entraînement, 20% de validation et 10% de données de maintien / test.
Découvrez le np.split :
Si indices_or_sections est un tableau 1-D d'entiers triés, les entrées indiquent où le long de l'axe le tableau est divisé. Par exemple, [2, 3] donnerait, pour axis = 0,
ary [: 2] ary [2: 3] ary [3:]
t, v, h = np.split(df.sample(frac=1, random_state=1), [int(0.7*len(df)), int(0.9*len(df))])
Split en train test et valide
x =np.expand_dims(np.arange(100), -1)
print(x)
indices = np.random.permutation(x.shape[0])
training_idx, test_idx, val_idx = indices[:int(x.shape[0]*.9)], indices[int(x.shape[0]*.9):int(x.shape[0]*.95)], indices[int(x.shape[0]*.9):int(x.shape[0]*.95)]
training, test, val = x[training_idx,:], x[test_idx,:], x[val_idx,:]
print(training, test, val)