python - optimize - ¿Cómo dividir/particionar un conjunto de datos en conjuntos de datos de entrenamiento y prueba para, por ejemplo, validación cruzada?
python optimization solver (8)
¿Cuál es una buena manera de dividir aleatoriamente una matriz NumPy en el conjunto de datos de entrenamiento y prueba / validación? Algo similar a las funciones de cvpartition
o crossvalind
en Matlab.
Aquí hay un código para dividir los datos en n = 5 pliegues de forma estratificada
% 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]
Como el módulo sklearn.cross_validation
está en desuso, puede usar:
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)
Escribí una función para mi propio proyecto para hacer esto (sin embargo, no usa numpy):
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 desea que los fragmentos se aleatoricen, simplemente mezcle la lista antes de pasarla.
Gracias pbykes por tu respuesta. Lo modifiqué para evitar (1) reemplazo mientras tomaba muestras (2) ocurrieron instancias duplicadas tanto en entrenamiento como en pruebas:
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)
Hay otra opción que solo implica usar scikit-learn. Como describe el wiki de scikit , puedes usar las siguientes instrucciones:
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 esta forma, puede mantener sincronizadas las etiquetas de los datos que intenta dividir en entrenamiento y prueba.
Si desea dividir el conjunto de datos una vez en dos mitades, puede usar numpy.random.shuffle
, o numpy.random.permutation
si necesita realizar un seguimiento de los índices:
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,:]
Hay muchas maneras de particionar repetidamente el mismo conjunto de datos para la validación cruzada . Una estrategia es volver a muestrear desde el conjunto de datos, con repetición:
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,:]
Finalmente, sklearn contiene varios métodos de validación cruzada (k-fold, leave-n-out, ...). También incluye métodos más avanzados de "muestreo estratificado" que crean una partición de los datos que se equilibra con respecto a algunas características, por ejemplo, para asegurarse de que haya la misma proporción de ejemplos positivos y negativos en el conjunto de entrenamiento y prueba.
Solo una nota. En caso de que desee conjuntos de validación, prueba y AND, puede hacer esto:
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)
Estos parámetros darán un 70% de entrenamiento y un 15% cada uno para probar y val set. Espero que esto ayude.
También puede considerar la división estratificada en el conjunto de entrenamiento y prueba. La división iniciada también genera un conjunto de entrenamiento y prueba al azar, pero de tal manera que se conservan las proporciones de clase originales. Esto hace que los conjuntos de entrenamiento y prueba reflejen mejor las propiedades del conjunto de datos 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]
Este código genera:
[1 2 3]
[1 2 3]