web-dev-qa-db-fra.com

Scikit-learn train_test_split avec des index

Comment puis-je obtenir les index d'origine des données lorsque j'utilise train_test_split ()?

Ce que j'ai est la suivante

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)

Mais cela ne donne pas les indices des données d'origine. Une solution consiste à ajouter les index aux données (par exemple, data = [(i, d) for i, d in enumerate(data)]), à les transférer ensuite à l'intérieur de train_test_split, puis à les développer à nouveau. Y a-t-il des solutions plus propres?

31
CentAu

Scikit apprend très bien jouer avec les pandas, je vous suggère donc de l’utiliser. Voici un exemple:

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

Vous pouvez appeler directement n'importe quelle fonction scikit sur DataFrame/Series et cela fonctionnera.

Supposons que vous souhaitiez effectuer une régression logistique, voici comment récupérer les coefficients de manière agréable:

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
26
Julien Marrec

Vous pouvez utiliser des images ou des séries de pandas comme l'a dit Julien, mais si vous voulez vous limiter à numpy, vous pouvez passer un tableau supplémentaire d'indices:

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)
58
ogrisel

Le docs mention train_test_split n'est qu'une fonction pratique au-dessus de la division aléatoire.

Je viens de réorganiser une partie de leur code pour créer mon propre exemple. Notez que la solution actuelle est le bloc de code central. Le reste est importé et configuré pour un exemple exécutable.

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)

Maintenant, j'ai les index actuels: train_is, test_is

1
Jibwa

Voici la solution la plus simple (vous ne savez pas pourquoi Jibwa a semblé compliquée dans une autre réponse), sans avoir à générer des index vous-même - utilisez simplement l'objet ShuffleSplit pour générer 1 division.

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