Scikit-learn train_test_split с индексами

Как получить исходные индексы данных при использовании train_test_split()?

Что у меня есть следующее

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)

Но это не дает показателей исходных данных. Один из обходных путей - добавить индексы к данным (например, data = [(i, d) for i, d in enumerate(data)]), а затем передать их в train_test_split и затем снова развернуть. Есть ли более чистые решения?

Ответы

Ответ 1

Scikit learn играет с Pandas очень хорошо, поэтому я предлагаю вам использовать его. Вот пример:

In [1]: 
import pandas as pd
import numpy as np
from sklearn.model_selection 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

Вы можете напрямую вызывать любые функции scikit на DataFrame/Series, и это будет работать.

Допустим, вы хотели сделать LogisticRegression, вот как вы можете получить коэффициенты хорошим способом:

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

Ответ 2

Вы можете использовать pandas dataframes или series, как сказал Julien, но если вы хотите ограничить себя numpy, вы можете передать дополнительный массив индексов:

from sklearn.model_selection 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)

Ответ 3

В документах упоминается, что train_test_split - это просто вспомогательная функция поверх разбиения в случайном порядке.

Я просто перестроил часть их кода, чтобы сделать свой собственный пример. Обратите внимание, что реальным решением является средний блок кода. Остальное - это импорт и настройка для работающего примера.

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)

Теперь у меня есть актуальные индексы: train_is, test_is

Ответ 4

Здесь самое простое решение (Jibwa сделал его сложным в другом ответе), без необходимости самим генерировать индексы - просто используя объект ShuffleSplit для генерации 1 разбиения.

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]