Respuestas:
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 formas de particionar repetidamente el mismo conjunto de datos para la validación cruzada . Una estrategia es volver a muestrear a partir del 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 está equilibrada 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.
Hay otra opción que solo implica usar scikit-learn. Como describe la wiki de scikit , puede 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 manera, puede mantener sincronizadas las etiquetas de los datos que está intentando dividir en entrenamiento y prueba.
Solo una nota. En caso de que desee entrenar, probar y conjuntos de validación, 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% al entrenamiento y un 15% a cada uno de los conjuntos de prueba y val. Espero que esto ayude.
from sklearn.cross_validation import train_test_split
para dejar en claro qué módulo está utilizando
a=0.7
, b=0.15
, c=0.15
, y d = dataset
, N=len(dataset)
y, a continuación x_train = dataset[0:int(a*N)]
, x_test = dataset[int(a*N):int((a+b)*N)]
y x_val = dataset[int((a+b)*N):]
.
from sklearn.model_selection import train_test_split
Como el sklearn.cross_validation
módulo quedó obsoleto, 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)
También puede considerar la división estratificada en conjunto de entrenamiento y prueba. La división iniciada también genera conjuntos de entrenamiento y prueba aleatoriamente, pero de tal manera que se conservan las proporciones originales de la clase. 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]
value_inds
son verdaderamente índices, pero la salida no son índices, solo máscaras.
Escribí una función para mi propio proyecto para hacer esto (aunque 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 sean aleatorios, simplemente mezcle la lista antes de pasarla.
Aquí hay un código para dividir los datos en n = 5 pliegues de manera 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]
Gracias pberkes por tu respuesta. Lo modifiqué para evitar (1) el reemplazo mientras se tomaban muestras (2) ocurrieron instancias duplicadas tanto en el entrenamiento como en las 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)
Después de leer un poco y tener en cuenta las (muchas ...) formas diferentes de dividir los datos para entrenar y probar, ¡decidí cronometrarlo!
Utilicé 4 métodos diferentes (ninguno de ellos está usando la biblioteca sklearn, que estoy seguro dará los mejores resultados, dado que está bien diseñado y probado código):
el método 3 ganó con mucho con el tiempo más corto, después del método 1, y se descubrió que el método 2 y 4 eran realmente ineficientes.
El código para los 4 métodos diferentes que cronometré:
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)
Y para los tiempos, el tiempo mínimo para ejecutar de 3 repeticiones de 1000 bucles es:
¡Espero que sea de ayuda!
Es probable que no solo deba dividirse en entrenamiento y prueba, sino también una validación cruzada para asegurarse de que su modelo se generalice. Aquí estoy asumiendo 70% de datos de entrenamiento, 20% de validación y 10% de datos de prueba / retención.
Consulte el np.split :
Si índices_o_secciones es una matriz 1-D de enteros ordenados, las entradas indican en qué parte del eje se divide la matriz. Por ejemplo, [2, 3], para el eje = 0, resultaría en
ario [: 2] ario [2: 3] ario [3:]
t, v, h = np.split(df.sample(frac=1, random_state=1), [int(0.7*len(df)), int(0.9*len(df))])
Dividido en prueba de tren y válido
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)