Sklearn StratifiedKFold: ValueError: Поддерживаемые целевые типы: ('binary', 'multiclass'). Вместо этого отобразился "многозначный индикатор"
Работа с Sklearn стратифицированным разделением kfold, и когда я пытаюсь разделить с помощью мультикласса, я получил ошибку (см. Ниже). Когда я попытался и разделил с помощью двоичного кода, это не проблема.
num_classes = len(np.unique(y_train))
y_train_categorical = keras.utils.to_categorical(y_train, num_classes)
kf=StratifiedKFold(n_splits=5, shuffle=True, random_state=999)
# splitting data into different folds
for i, (train_index, val_index) in enumerate(kf.split(x_train, y_train_categorical)):
x_train_kf, x_val_kf = x_train[train_index], x_train[val_index]
y_train_kf, y_val_kf = y_train[train_index], y_train[val_index]
ValueError: Supported target types are: ('binary', 'multiclass'). Got 'multilabel-indicator' instead.
Ответы
Ответ 1
keras.utils.to_categorical
создает один горячий кодированный вектор класса, то есть multilabel-indicator
упомянутый в сообщении об ошибке. StratifiedKFold
не предназначен для работы с такими входами; из split
метода docs:
split
(X, y, groups = None)
[...]
y: array-like, shape (n_samples,)
Целевая переменная для контролируемых проблем обучения. Стратификация выполняется на основе ярлыков y.
т.е. ваш y
должен быть 1-D массивом ваших ярлыков класса.
По сути, вам нужно просто инвертировать порядок операций: сначала y_train
(используя ваш y_train
), а затем конвертировать в to_categorical
.
Ответ 2
Я столкнулся с той же проблемой и выяснил, что вы можете проверить тип цели с помощью этой функции util
:
from sklearn.utils.multiclass import type_of_target
type_of_target(y)
'multilabel-indicator'
Из его документа:
- 'binary':
y
содержит <= 2 дискретных значения и 1d или вектор столбца. - "multiclass":
y
содержит более двух дискретных значений, не является последовательностью последовательностей и является 1d или вектором столбца. - "multiclass-multioutput":
y
- это 2d-массив, который содержит более двух дискретных значений, не является последовательностью последовательностей, и оба измерения имеют размер> 1. - "multilabel-indicator":
y
- индикаторная матрица ярлыков, массив из двух измерений с по меньшей мере двумя столбцами и не более 2 уникальных значений.
С LabelEncoder
вы можете преобразовать свои классы в 1d массив чисел (если ваши целевые метки находятся в 1d массиве категориальных/объектов):
from sklearn.preprocessing import LabelEncoder
label_encoder = LabelEncoder()
y = label_encoder.fit_transform(target_labels)
Ответ 3
В моем случае x
была двумерной матрицей, а y
также была 2d-матрицей, то есть действительно многопроцессорным многовыходным случаем. Я просто передал фиктивный np.zeros(shape=(n,1))
для y
и x
как обычно. Полный пример кода:
import numpy as np
from sklearn.model_selection import RepeatedStratifiedKFold
X = np.array([[1, 2], [3, 4], [1, 2], [3, 4], [3, 7], [9, 4]])
# y = np.array([0, 0, 1, 1, 0, 1]) # <<< works
y = X # does not work if passed into '.split'
rskf = RepeatedStratifiedKFold(n_splits=3, n_repeats=3, random_state=36851234)
for train_index, test_index in rskf.split(X, np.zeros(shape=(X.shape[0], 1))):
print("TRAIN:", train_index, "TEST:", test_index)
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
Ответ 4
Позвоните в split()
следующим образом:
for i, (train_index, val_index) in enumerate(kf.split(x_train, y_train_categorical.argmax(1))):
x_train_kf, x_val_kf = x_train[train_index], x_train[val_index]
y_train_kf, y_val_kf = y_train[train_index], y_train[val_index]