126 votes

Comment diviser/partitionner un ensemble de données en ensembles de données de formation et de test pour, par exemple, la validation croisée ?

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.

154voto

pberkes Points 1889

Si vous voulez diviser l'ensemble de données une fois en deux parties, vous pouvez utiliser numpy.random.shuffle ou numpy.random.permutation si vous avez besoin de garder la trace des indices (n'oubliez pas de fixer la graine aléatoire pour que tout soit reproductible) :

import numpy
# x is your dataset
x = numpy.random.rand(100, 5)
numpy.random.shuffle(x)
training, test = x[:80,:], x[80:,:]

o

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 y a beaucoup d'autres façons de faire de partitionner de manière répétée le même ensemble de données pour la validation croisée. Beaucoup d'entre eux sont disponible dans le sklearn bibliothèque (k-fold, leave-n-out, ...). sklearn comprend également des fonctions plus avancées "échantillonnage stratifié" méthodes qui créent une partition des données équilibrée en ce qui concerne 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.

64voto

Paulo Malvar Points 649

Il existe une autre option qui consiste simplement à utiliser scikit-learn. Comme Le wiki de Scikit décrit 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 séparer en formation et en test.

1 votes

Il s'agit d'une réponse très pratique, en raison de la manipulation réaliste de la rame et des étiquettes.

0 votes

Il retourne une liste, pas un tableau.

41voto

offwhitelotus Points 737

Juste une remarque. Si vous voulez des ensembles de formation, de test et 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 donneront 70 % à la formation, et 15 % chacun aux ensembles de test et de val. J'espère que cela vous aidera.

6 votes

Devrait probablement ajouter ceci à votre code : from sklearn.cross_validation import train_test_split pour indiquer clairement le module que vous utilisez

0 votes

Est-ce que ça doit être aléatoire ?

0 votes

Autrement dit, est-il possible de diviser selon l'ordre donné par X et y ?

15voto

M. Mashaye Points 844

Comme sklearn.cross_validation a été déprécié, vous pouvez l'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)

6voto

Apogentus Points 170

Vous pouvez également envisager une division stratifiée en ensembles de formation et de test. La division stratifiée génère également des ensembles de formation et de test de manière aléatoire, mais de telle sorte que les proportions des classes d'origine soient préservées. Ainsi, les ensembles d'entraînement et de test reflètent mieux 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 sort :

[1 2 3]
[1 2 3]

0 votes

Merci. La dénomination est quelque peu trompeuse, value_inds sont vraiment des indices, mais les sorties ne sont pas des indices, seulement des masques.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X