Как убедиться, что определенная точка данных не входит в набор тестов при разделении на стратифицированную перекрестную проверку?

#python #pandas #scikit-learn #cross-validation

Вопрос:

У меня есть фрейм данных, который выглядит так.

 d = {'col1': [1, 2,3,4,5,6,7,8], 'col2': ['a', 'a','b', 'b', 'c', 'c', 'd', 'd']}
df = pd.DataFrame(data=d)
df

  col1  col2
0   1     a
1   2     a
2   3     b
3   4     b
4   5     c
5   6     c
6   7     d
7   8     d
 

Когда я использую перекрестную проверку k-кратности, я хочу убедиться, что значения в col2 присутствуют либо только в наборе поездов, либо в наборе тестов. То есть во время разделения, если df['col2'][0] = a , и df['col2'][1] = a , то строки с индексами 0 и 1 должны быть как в наборе поездов , так и в тестовом наборе. Не должно быть так, чтобы строка 0 находилась в наборе поездов, а строка 1-в наборе тестов.

Есть ли простой способ сделать это?

Изменить: Есть ли способ просто разделить фрейм данных на два, чтобы каждая часть содержала все точки данных, имеющие значение a col2 в первом фрейме данных или во втором, но не в обоих? Я пытался использовать groupby , но он возвращает объект, и когда я преобразую его в словарь, я могу получить к нему доступ только с помощью ключей, т. Е. a, b, c, d

Ответ №1:

Вы можете убедиться, что значение переменной присутствует только в наборе, выполнив GroupShuffleSplit следующее:

 from sklearn.model_selection import GroupShuffleSplit

import pandas as pd

d = {'col1': [1, 2,3,4,5,6,7,8],
    'col2': ['a', 'a','b', 'b', 'c', 'c', 'd', 'd'],
    'label': [1,1,1,1,0,0,0,0]}
df = pd.DataFrame(data=d)

X = df[['col1', 'col2']]
y = df['label']
groups= df['col2']
gss = GroupShuffleSplit(n_splits=2, train_size=.8, random_state=42)
for train_idx, test_idx in gss.split(X, y, groups):
    X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]
    y_train, y_test = y.iloc[train_idx], y.iloc[test_idx]
 

Комментарии:

1. Это здорово, большое вам спасибо. Приведет ли это также к стратифицированному разделению между данными поезда и тестовыми данными? Мой ярлык на самом деле является третьей колонкой.

2. Проблема в том, что sklearn предлагает только возможность получить stratified или group разделить. Нет никакого стратифицированного группового разделения. но ты можешь написать свой собственный.

3. Спасибо, это действительно приятно знать. Если я напишу свой собственный раздел группы стратификации, будет ли правильным подходом разделить ее на группы, а затем проверить метки в каждом разделении и обменять только эти строки? Или есть другой способ продолжить?

4. Я бы выполнил стратификационное разделение на уникальные значения col2 , а затем нашел бы образцы X, которые имеют эти значения col2. Но вы не можете быть уверены, что получившаяся группа будет иметь правильный размер. В зависимости от представления одного значения col2 результирующий набор может отличаться.

5. похоже, что у sklearn он уже находится на стадии разработки , однако при попытке его использования я получаю ошибку импорта.


Ответ №2:


С помощью @Antoine Dubuis я нашел реализацию sklearn того, что я хотел сделать, — под названием StratifiedGroupKFold.

Он все еще находится в разработке по состоянию на июль 2021 года, но может быть использован в версии для разработки/ночной версии. Я советую создать отдельную виртуальную среду для ее использования.

Я использовал его, и в настоящее время он, похоже, работает, поэтому надеюсь, что скоро он будет выпущен в стабильном выпуске.