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.
keras.utils.to_categorical
は、ワンホットでエンコードされたクラスベクトル、つまりmultilabel-indicator
はエラーメッセージに記載されています。 StratifiedKFold
は、そのような入力で動作するようには設計されていません。 split
メソッドから docs :
split
(X、y、groups = None)[...]
y:配列のような形状(n_samples、)
教師あり学習問題のターゲット変数。層別化はyラベルに基づいて行われます。
つまり、y
はクラスラベルの1次元配列でなければなりません。
基本的に、あなたがしなければならないことは、単に操作の順序を逆にすることです:最初に分割します(最初のy_train
)、およびto_categorical
その後。
私は同じ問題にぶつかり、このutil
関数を使用してターゲットのタイプを確認できることがわかりました。
from sklearn.utils.multiclass import type_of_target
type_of_target(y)
'multilabel-indicator'
そのdocstringから:
- 'binary':
y
には2個以下の離散値が含まれ、1dまたは列ベクトルです。- 'multiclass':
y
は3つ以上の離散値を含み、シーケンスのシーケンスではなく、1dまたは列ベクトルです。- 'multiclass-multioutput':
y
は3つ以上の離散値を含む2D配列であり、シーケンスのシーケンスではなく、両方の次元のサイズが1より大きい。- 'multilabel-indicator':
y
は、ラベルインジケーターマトリックス、少なくとも2列の2次元の配列、最大2つの一意の値です。
LabelEncoder
を使用すると、クラスを1Dの数値配列に変換できます(ターゲットラベルが1Dのカテゴリ/オブジェクトの配列にある場合)。
from sklearn.preprocessing import LabelEncoder
label_encoder = LabelEncoder()
y = label_encoder.fit_transform(target_labels)
このような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]
私の場合、x
は2Dマトリックスであり、y
も2Dマトリックスでした。つまり、実際にはマルチクラスマルチ出力の場合です。通常どおり、y
とx
にダミーのnp.zeros(shape=(n,1))
を渡しました。完全なコード例:
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]