Quel est le bon moyen de diviser un tableau NumPy de manière aléatoire en un ensemble de données d'apprentissage et de test/validation? Quelque chose de semblable aux fonctions cvpartition
ou crossvalind
dans Matlab.
Si vous souhaitez fractionner le jeu de données une fois en deux moitiés, vous pouvez utiliser numpy.random.shuffle
ou numpy.random.permutation
si vous devez suivre les index:
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 manières de partitionner plusieurs fois le même jeu de données pour une validation croisée . Une stratégie consiste à rééchantillonner à partir du jeu 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 inclut également des méthodes "d'échantillonnage stratifié" plus avancées qui créent une partition des données équilibrée par rapport à certaines caractéristiques, par exemple pour s'assurer que la formation contient la même quantité d'exemples positifs et négatifs. ensemble d'essai.
Une autre option consiste simplement à utiliser scikit-learn. Comme décrit dans 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 scinder en formations et tests.
Juste une note. Si vous souhaitez former, 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 des ensembles. J'espère que cela t'aides.
Le module sklearn.cross_validation
é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 un ensemble d’entraînement et d’essai. La division Startified génère également des ensembles d’entraînement et de test de manière aléatoire, mais de manière à préserver les proportions de classe originales. Cela permet aux ensembles de formation et de test de mieux refléter les propriétés du jeu 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 affiche:
[1 2 3]
[1 2 3]
Merci pberkes pour ta 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)
J'ai écrit une fonction pour mon propre projet pour le faire (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, il suffit de mélanger la liste avant de la transmettre.
Voici un code pour fractionner les données en n = 5 plis 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]
Après avoir lu un peu et pris en compte les nombreuses (nombreuses ..) façons de diviser les données pour former et tester, j'ai décidé de le faire!
J'ai utilisé 4 méthodes différentes (aucune d'entre elles n'utilise la bibliothèque Sklearn, ce qui, j'en suis sûr, donnera les meilleurs résultats, car il s'agit d'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!