Je voudrais utiliser l'argument class_weight dans keras model.fit pour gérer les données d'entraînement déséquilibrées. En regardant certains documents, j'ai compris que nous pouvons passer un dictionnaire comme celui-ci:
class_weight = {0 : 1,
1: 1,
2: 5}
(Dans cet exemple, la classe 2 recevra une pénalité plus élevée dans la fonction de perte.)
Le problème est que la sortie de mon réseau a un codage à chaud, c'est-à-dire classe-0 = (1, 0, 0), classe-1 = (0, 1, 0) et classe-3 = (0, 0, 1).
Comment pouvons-nous utiliser le poids_classe pour une sortie codée à chaud?
En regardant certains codes dans Keras , cela ressemble à _feed_output_names
contient une liste des classes de sortie, mais dans mon cas, model.output_names
/model._feed_output_names
résultats ['dense_1']
Connexes: Comment définir les poids de classe pour les classes déséquilibrées dans Keras?
Je suppose que nous pouvons utiliser sample_weights
au lieu. À l'intérieur de Keras, en fait, class_weights
sont convertis en sample_weights
.
sample_weight: tableau facultatif de la même longueur que x, contenant des poids à appliquer à la perte du modèle pour chaque échantillon. Dans le cas des données temporelles, vous pouvez passer un tableau 2D avec une forme (échantillons, longueur_séquence), pour appliquer un poids différent à chaque pas de temps de chaque échantillon. Dans ce cas, vous devez vous assurer de spécifier sample_weight_mode = "temporal" dans compile ().
Voici une solution un peu plus courte et plus rapide. Si votre y codé à chaud est un tableau np:
import numpy as np
from sklearn.utils.class_weight import compute_class_weight
y_integers = np.argmax(y, axis=1)
class_weights = compute_class_weight('balanced', np.unique(y_integers), y_integers)
d_class_weights = dict(enumerate(class_weights))
d_class_weights
peut ensuite être transmis à class_weight
dans .fit
.
Une réponse un peu compliquée, mais la meilleure que j'ai trouvée jusqu'à présent. Cela suppose que vos données sont codées à chaud, multi-classes et fonctionnent uniquement sur les étiquettes DataFrame df_y
:
import pandas as pd
import numpy as np
# Create a pd.series that represents the categorical class of each one-hot encoded row
y_classes = df_y.idxmax(1, skipna=False)
from sklearn.preprocessing import LabelEncoder
# Instantiate the label encoder
le = LabelEncoder()
# Fit the label encoder to our label series
le.fit(list(y_classes))
# Create integer based labels Series
y_integers = le.transform(list(y_classes))
# Create dict of labels : integer representation
labels_and_integers = dict(Zip(y_classes, y_integers))
from sklearn.utils.class_weight import compute_class_weight, compute_sample_weight
class_weights = compute_class_weight('balanced', np.unique(y_integers), y_integers)
sample_weights = compute_sample_weight('balanced', y_integers)
class_weights_dict = dict(Zip(le.transform(list(le.classes_)), class_weights))
Il en résulte un sample_weights
vecteur calculé pour équilibrer un ensemble de données déséquilibré qui peut être transmis au Keras sample_weight
, et un class_weights_dict
pouvant être alimenté au Keras class_weight
propriété dans le .fit
méthode. Vous ne voulez pas vraiment utiliser les deux, choisissez-en un. J'utilise class_weight
maintenant parce que c'est compliqué d'obtenir sample_weight
travailler avec fit_generator
.
dans _standardize_weights
, keras fait:
if y.shape[1] > 1:
y_classes = y.argmax(axis=1)
donc, fondamentalement, si vous choisissez d'utiliser un codage à chaud, les classes sont l'index des colonnes.
Vous pouvez également vous demander comment mapper l'index de colonne aux classes d'origine de vos données. Eh bien, si vous utilisez la classe LabelEncoder de scikit apprenez à effectuer un codage à chaud, l'index de colonne mappe l'ordre du unique labels
calculé par le .fit
une fonction. Le doc dit
Extraire un tableau ordonné d'étiquettes uniques
Exemple:
from sklearn.preprocessing import LabelBinarizer
y=[4,1,2,8]
l=LabelBinarizer()
y_transformed=l.fit_transorm(y)
y_transormed
> array([[0, 0, 1, 0],
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 1]])
l.classes_
> array([1, 2, 4, 8])
En conclusion, les clés du class_weights
le dictionnaire doit refléter l'ordre dans le classes_
attribut de l'encodeur.