Quelle est la bonne façon de diviser un tableau NumPy de façon aléatoire en deux ensembles de données : formation et test/validation ? Quelque chose de similaire à la méthode cvpartition
o crossvalind
dans Matlab.
Réponses
Trop de publicités?Après avoir lu quelques articles et pris en compte les (nombreuses ) différentes façons de diviser les données pour former et tester, j'ai décidé d'utiliser le 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 le code est bien conçu et testé) :
- mélanger la matrice entière et ensuite diviser les données pour former et tester.
- mélanger les indices et ensuite leur attribuer x et y pour diviser les données
- même méthode que la méthode 2, mais d'une manière plus efficace de le faire
- utiliser le dataframe de pandas pour diviser
La méthode 3 l'a emporté de loin avec le temps le plus court, suivie de la méthode 1, et les méthodes 2 et 4 se sont révélées vraiment inefficaces.
Le code pour les 4 différentes méthodes 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 à exécuter sur 3 répétitions de 1000 boucles est :
- Méthode 1 : 0,35883826200006297 secondes
- Méthode 2 : 1,7157016959999964 secondes
- Méthode 3 : 1,7876616719995582 secondes
- Méthode 4 : 0,07562861499991413 secondes
J'espère que c'est utile !
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 aléatoires, il suffit de mélanger la liste avant de la transmettre.
Divisé en test de train 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)
Voici un code pour diviser 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]
Merci pberkes pour votre réponse. Je l'ai juste modifié pour éviter (1) le remplacement pendant l'échantillonnage (2) les instances dupliquées qui se sont produites à la fois dans la formation et le test :
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)