2010-09-09 16 views

Répondre

71

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.

+7

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

0

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

24

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.

4

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] 
+0

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

18

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.

+4

devrait probablement ajouter ceci à votre code: 'from sklearn.cross_validation import train_test_split' pour indiquer clairement quel module vous utilisez – Radix

+0

Est-ce que cela doit être aléatoire? – liang

+0

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

0

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] 
0

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) 
6

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)