web-dev-qa-db-ja.com

Sklearn StratifiedKFold:ValueError:サポートされるターゲットタイプは、( 'binary'、 'multiclass')です。代わりに「multilabel-indicator」を取得しました

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.
17
jKraut

keras.utils.to_categoricalは、ワンホットでエンコードされたクラスベクトル、つまりmultilabel-indicatorはエラーメッセージに記載されています。 StratifiedKFoldは、そのような入力で動作するようには設計されていません。 splitメソッドから docs

split(X、y、groups = None)

[...]

y:配列のような形状(n_samples、)

教師あり学習問題のターゲット変数。層別化はyラベルに基づいて行われます。

つまり、yはクラスラベルの1次元配列でなければなりません。

基本的に、あなたがしなければならないことは、単に操作の順序を逆にすることです:最初に分割します(最初のy_train)、およびto_categoricalその後。

15
desertnaut

私は同じ問題にぶつかり、この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)
4
nocibambi

このような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]
2
wilmeragsgh

私の場合、xは2Dマトリックスであり、yも2Dマトリックスでした。つまり、実際にはマルチクラスマルチ出力の場合です。通常どおり、yxにダミーの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]
1
shadi