python - stratify - train test
Scikit-learn train_test_split con índices (4)
¿Cómo obtengo los índices originales de los datos cuando uso train_test_split ()?
Lo que tengo es el siguiente
from sklearn.cross_validation import train_test_split
import numpy as np
data = np.reshape(np.randn(20),(10,2)) # 10 training examples
labels = np.random.randint(2, size=10) # 10 labels
x1, x2, y1, y2 = train_test_split(data, labels, size=0.2)
Pero esto no da los índices de los datos originales. Una solución alternativa es agregar índices a los datos (por ejemplo, data = [(i, d) for i, d in enumerate(data)]
) y luego pasarlos dentro de train_test_split
y luego expandir nuevamente. ¿Hay alguna solución más limpia?
Aquí está la solución más simple (no estoy seguro de por qué Jibwa lo hizo parecer complicado en otra respuesta), sin tener que generar índices usted mismo, simplemente usando el objeto ShuffleSplit para generar 1 división.
import numpy as np
from sklearn.model_selection import ShuffleSplit # or StratifiedShuffleSplit
sss = ShuffleSplit(n_splits=1, test_size=0.1)
data_size = 100
X = np.reshape(np.random.rand(data_size*2),(data_size,2))
y = np.random.randint(2, size=data_size)
sss.get_n_splits(X, y)
train_index, test_index = next(sss.split(X, y))
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
La docs mencionada train_test_split es solo una función de conveniencia en la parte superior de shuffle split.
Acabo de reorganizar parte de su código para hacer mi propio ejemplo. Tenga en cuenta que la solución real es el bloque medio de código. El resto es importaciones y configuración para un ejemplo ejecutable.
from sklearn.model_selection import ShuffleSplit
from sklearn.utils import safe_indexing, indexable
from itertools import chain
import numpy as np
X = np.reshape(np.random.randn(20),(10,2)) # 10 training examples
y = np.random.randint(2, size=10) # 10 labels
seed = 1
cv = ShuffleSplit(random_state=seed, test_size=0.25)
arrays = indexable(X, y)
train, test = next(cv.split(X=X))
iterator = list(chain.from_iterable((
safe_indexing(a, train),
safe_indexing(a, test),
train,
test
) for a in arrays)
)
X_train, X_test, train_is, test_is, y_train, y_test, _, _ = iterator
print(X)
print(train_is)
print(X_train)
Ahora tengo los índices reales: train_is, test_is
Puede usar marcos de datos de pandas o series, como dijo Julien, pero si desea restringirse a sí mismo para que no pueda hacerlo, puede pasar una serie adicional de índices:
from sklearn.cross_validation import train_test_split
import numpy as np
n_samples, n_features, n_classes = 10, 2, 2
data = np.random.randn(n_samples, n_features) # 10 training examples
labels = np.random.randint(n_classes, size=n_samples) # 10 labels
indices = np.arange(n_samples)
x1, x2, y1, y2, idx1, idx2 = train_test_split(
data, labels, indices, test_size=0.2)
Scikit Learn juega realmente bien con Pandas, por lo que te sugiero que lo uses. Aquí hay un ejemplo:
In [1]:
import pandas as pd
import numpy as np
from sklearn.cross_validation import train_test_split
data = np.reshape(np.random.randn(20),(10,2)) # 10 training examples
labels = np.random.randint(2, size=10) # 10 labels
In [2]:
X = pd.DataFrame(data)
y = pd.Series(labels)
In [3]:
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=test_size,
random_state=0)
In [4]: X_test
Out[4]:
0 1
2 -1.39 -1.86
8 0.48 -0.81
4 -0.10 -1.83
In [5]: y_test
Out[5]:
2 1
8 1
4 1
dtype: int32
Puede llamar directamente a cualquier función de scikit en DataFrame / Series y funcionará.
Digamos que querías hacer una Regresión logística, aquí es cómo puedes recuperar los coeficientes de una manera agradable:
In [6]:
from sklearn.linear_model import LogisticRegression
model = linear_model.LogisticRegression()
model = model.fit(X_train, y_train)
# Retrieve coefficients: index is the feature name ([0,1] here)
df_coefs = pd.DataFrame(model.coef_[0], index=X.columns, columns = [''Coefficient''])
df_coefs
Out[6]:
Coefficient
0 0.076987
1 -0.352463