it-swarm.com.de

Sklearn StratifiedKFold: ValueError: Unterstützte Zieltypen sind: ('binary', 'multiclass'). Stattdessen 'Multilabel-Indikator'

Bei der Arbeit mit Sklearn stratified kfold split, und wenn ich versuche, mithilfe von Multi-Class zu teilen, erhielt ich einen Fehler (siehe unten). Wenn ich es mit binär versucht und aufgeteilt habe, funktioniert es kein Problem.

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

keras.utils.to_categorical erzeugt einen One-Hot-codierten Klassenvektor, d. h. den in der Fehlermeldung genannten multilabel-indicator. StratifiedKFold ist nicht dafür ausgelegt, mit solchen Eingaben zu arbeiten. aus der split-Methode docs :

split (X, y, groups = Keine)

[...]

y: Array-ähnliche Form (n_samples,)

Die Zielvariable für überwachte Lernprobleme. Die Schichtung wird anhand der y-Labels vorgenommen.

ihre y muss ein 1-D-Array Ihrer Klassenbezeichnungen sein.

Im Wesentlichen müssen Sie lediglich die Reihenfolge der Operationen umkehren: Zuerst aufteilen (mit Ihrem ersten y_train) und anschließend to_categorical konvertieren.

12
desertnaut

Ich bin auf das gleiche Problem gestoßen und habe herausgefunden, dass Sie den Typ des Ziels mit dieser util-Funktion überprüfen können:

from sklearn.utils.multiclass import type_of_target
type_of_target(y)

'multilabel-indicator'

Aus seinem Dokument:

  • 'binary': y enthält <= 2 diskrete Werte und ist 1d oder eine Spalte Vektor.
  • 'multiclass': y enthält mehr als zwei diskrete Werte und ist kein Sequenz von Sequenzen und ist 1d oder ein Spaltenvektor.
  • 'multiclass-multioutput': y ist ein 2d-Array, das mehr .__ enthält. als zwei diskrete Werte ist keine Sequenz von Sequenzen und beide Abmessungen haben eine Größe von> 1.
  • 'Multilabel-Indikator': y ist eine Labelindikatormatrix, ein Array von zwei Dimensionen mit mindestens zwei Spalten und höchstens 2 eindeutig Werte.

Mit LabelEncoder können Sie Ihre Klassen in ein 1d-Array von Zahlen umwandeln (vorausgesetzt, Ihre Ziel-Labels befinden sich in einem 1d-Array von Kategorien/Objekten)

from sklearn.preprocessing import LabelEncoder

label_encoder = LabelEncoder()
y = label_encoder.fit_transform(target_labels)
2
nocibambi

Aufruf an split() wie folgt:

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]
1
wilmeragsgh

In meinem Fall war x eine 2D-Matrix und y auch eine 2d-Matrix, d. H. Ein Fall mit mehreren Klassen und mehreren Ausgängen. Ich habe wie üblich einen Dummy np.zeros(shape=(n,1)) für die y und die x übergeben. Vollständiger Codebeispiel:

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