Стратифицированный KFold не дает 9 отчетливых складок - Python 3,7 - PullRequest
0 голосов
/ 09 июля 2020

Я изо всех сил пытаюсь правильно использовать код sklearn StratifiedKFold.

У меня очень большой набор данных (X) и последующий список классов (y), то есть несбалансированное. Я хочу разбить это на 9 стратифицированных складок.

Однако результаты не такие, как я ожидал. По сути, я каждый раз добавляю весь набор данных и создаю 9 складок всего набора данных. Что необычно, так это то, что я не хочу получить разделение на поезд и тест для каждой свертки, я просто хочу стратифицированное разделение моих данных. (т.е. возьмите мои данные / 9, поддерживая дисбаланс классов).

# https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.StratifiedKFold.html
skf = StratifiedKFold(n_splits = 9, random_state=8, shuffle=False)

# Lists to hold the fold data and the fold classes
fold_data = []
fold_classes = []

print(X.shape)
print(y.shape)

unique, counts = np.unique(y, return_counts=True)
print(dict(zip(unique, counts)))

# Split into 9 splits
for train_index, test_index in skf.split(X, y):    
    # Get the first fold
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    print(X_train.shape, X_test.shape) # Why this shape so big? 
    
    # Use numpy to concatenate the training and testing data
    temp_data = np.concatenate((X_train, X_test), axis=0)
    temp_classes = np.concatenate((y_train, y_test), axis=0)
    
    # Append the current fold to the overall folds
    fold_data.append(temp_data)
    fold_classes.append(temp_classes)

print("overall size: {}".format(X.shape))
for x in fold_data:
    print("Example fold size: {}".format(x.shape))

Урожайность:

(240970, 3291)
(240970,)
{0: 196365, 1: 44605}
(214195, 3291) (26775, 3291)
(214195, 3291) (26775, 3291)
(214195, 3291) (26775, 3291)
(214195, 3291) (26775, 3291)
(214195, 3291) (26775, 3291)
(214195, 3291) (26775, 3291)
(214195, 3291) (26775, 3291)
(214195, 3291) (26775, 3291)
(214195, 3291) (26775, 3291)

Я просмотрел различные ресурсы и не могу понять, как правильно выполнить sh что я делаю. Я ищу что-то, что эффективно создает эффект 9 различных складок, без перекрывающихся данных, с размерами примерно 26,774 строк, при этом каждый класс сохраняет свое разделение (около 21,818 класса 0 и 4956 класса 1)

ОБНОВЛЕНИЕ Я пробовал использовать StratifiedShuffleSplit, но получил ту же проблему. Каждая складка - это все данные, а не 1/9 данных.

1 Ответ

2 голосов
/ 09 июля 2020

Вы можете создать 9 разбиений, сохраняя тестовые индексы в каждом разбиении, а затем использовать их для создания своих 9 разбиений данных.

from sklearn.model_selection import StratifiedKFold
import numpy as np

X = np.zeros(240970 * 10).reshape(240970, -1) # shape: (240970, 10)
y = np.random.randint(5, size=240970) # shape: (240970, )

skf = StratifiedKFold(n_splits=9, shuffle=False)

splits = []
for train_index, test_index in skf.split(X, y): 
    splits.append(test_index)

# Flatten the test indices
flat_idxs = np.concatenate(splits).ravel()

# Check the number of unique indices equals the shape of X
np.unique(flat_idxs).shape[0] == X.shape[0] # True

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

...