Quel est un bon moyen de diviser un tableau NumPy de manière aléatoire en jeu de données d'apprentissage et de test/validation? Quelque chose de similaire aux fonctions cvpartition
ou crossvalind
dans Matlab.Comment diviser/partitionner un ensemble de données en ensembles de données d'apprentissage et de test pour, par exemple, la validation croisée?
Répondre
Si vous voulez 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 sont de nombreuses façons de repeatedly partition the same data set for cross validation. Une stratégie consiste à rééchantillonner de l'ensemble de données, avec la 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 several cross validation methods (k fois, laissez-n-out, ...). Il comprend également des méthodes "stratified sampling" plus avancées qui créent une partition des données équilibrée par rapport à certaines fonctionnalités, par exemple pour s'assurer qu'il existe la même proportion d'exemples positifs et négatifs dans l'ensemble d'apprentissage et de test.
j'ai écrit une fonction pour mon propre projet de le faire (il n'utilise 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 répartis de façon aléatoire, juste mélanger la liste avant de le transmettre dans
Il existe une autre option qui nécessite l'utilisation de scikit-learn. Comme scikit's wiki describes, 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 rester en synchronisation les étiquettes pour les données que vous essayez de diviser en formation et test.
Vous pouvez également considérer la division stratifiée dans l'ensemble d'entraînement et de test. La division Startifiée génère également un jeu d'entraînement et de test au hasard, mais de manière à préserver les proportions de classe originales. Cela rend les ensembles de formation et de test mieux refléter les propriétés de l'ensemble de données original.
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]
Cette sortie Code:
[1 2 3]
[1 2 3]
Merci! La dénomination est quelque peu trompeuse, 'value_inds' sont vraiment des indices, mais les résultats ne sont pas des indices, seulement des masques. – greenoldman
Juste une note. Si vous voulez former, tester et ensembles de validation, 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 donnent 70% à la formation, et 15% chacun pour tester et ensembles de val. J'espère que cela t'aides.
Voici un code pour diviser les données en n = 5 plis de façon 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 modifia pour éviter (1) remplacement tout d'échantillonnage (2) cas dupliqués se sont produits dans la formation et les 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)
Comme le module sklearn.cross_validation
a été dépréciée, 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)
merci pour ces solutions. Mais, la dernière méthode, en utilisant randint, n'a-t-elle pas une bonne chance de donner les mêmes indices pour les ensembles de test et d'entraînement? – ggauravr