web-dev-qa-db-fra.com

Lutte contre le déséquilibre de classe: contribution croissante à la perte et à la DMS

(Une mise à jour de cette question a été ajoutée.)

Je suis un étudiant diplômé de l'université de Gand, en Belgique; mes recherches portent sur la reconnaissance des émotions avec des réseaux de neurones convolutionnels profonds. J'utilise le framework Caffe pour implémenter les CNN.

Récemment, j'ai rencontré un problème concernant le déséquilibre des classes. J'utilise 9216 échantillons d'entraînement, environ 5% sont marqués positivement (1), les échantillons restants sont marqués négativement (0).

J'utilise la couche SigmoidCrossEntropyLoss pour calculer la perte. Lors de l'entraînement, la perte diminue et la précision est extrêmement élevée même après quelques époques. Cela est dû au déséquilibre: le réseau prédit toujours simplement négatif (0). (La précision et le rappel sont égaux à zéro, ce qui confirme cette affirmation)}

Pour résoudre ce problème, je voudrais dimensionner la contribution à la perte en fonction de la combinaison prédiction-vérité (punir sévèrement les faux négatifs). Mon mentor/entraîneur m’a également conseillé de utiliser un facteur d’échelle lors de la rétro-propagation par le biais d’une descente de gradient stochastique (sgd): le facteur serait corrélé au déséquilibre du lot. Un lot contenant uniquement des échantillons négatifs ne mettrait pas à jour les poids.

J'ai ajouté un seul calque personnalisé à Caffe: pour signaler d'autres métriques telles que la précision et le rappel. Mon expérience avec le code Caffe est limitée, mais j'ai beaucoup de connaissances en écriture de code C++.


Quelqu'un pourrait-il m'aider ou me diriger dans la bonne direction pour ajuster les couches SigmoidCrossEntropyLoss et Sigmoid afin de prendre en compte les modifications suivantes:

  1. ajuster la contribution d'un échantillon à la perte totale en fonction de la combinaison prédiction-vérité (vrai positif, faux positif, vrai négatif, faux négatif).
  2. échelonne la mise à jour du poids effectuée par descente de gradient stochastique en fonction du déséquilibre dans le lot (négatifs par rapport aux positifs).

Merci d'avance!


Mettre à jour

J'ai incorporé le InfogainLossLayer comme suggéré par Shai. J'ai également ajouté une autre couche personnalisée qui construit la matrice infogain H en fonction du déséquilibre du lot en cours.

Actuellement, la matrice est configurée comme suit:

H(i, j) = 0          if i != j
H(i, j) = 1 - f(i)   if i == j (with f(i) = the frequency of class i in the batch)

Je prévois d'expérimenter différentes configurations pour la matrice à l'avenir.

J'ai testé cela sur un déséquilibre 10: 1. Les résultats ont montré que le réseau apprenait des choses utiles à présent: (résultats après 30 époques)} _

  • La précision est d'env. ~ 70% (en baisse de ~ 97%);
  • La précision est d'env. ~ 20% (au lieu de 0%);
  • Rappel est d'env. ~ 60% (au lieu de 0%).

Ces chiffres ont été atteints à environ 20 époques et n'ont pas changé de manière significative par la suite.

!! Les résultats indiqués ci-dessus ne sont qu'une preuve de concept, ils ont été obtenus en formant un simple réseau sur un jeu de données déséquilibré 10: 1. !!

29
Maarten Bamelis

Pourquoi n'utilisez-vous pas la couche InfogainLoss pour compenser le déséquilibre de votre équipement d'entraînement?

La perte d’Infogain est définie à l’aide d’une matrice de pondération H (dans votre cas 2 par 2). La signification de ses entrées est

[cost of predicting 1 when gt is 0,    cost of predicting 0 when gt is 0
 cost of predicting 1 when gt is 1,    cost of predicting 0 when gt is 1]

Ainsi, vous pouvez définir les entrées de H pour refléter la différence entre les erreurs de prédiction 0 ou 1.

Vous pouvez trouver comment définir la matrice H pour caffe dans ce fil .

En ce qui concerne les poids d'échantillon, vous pouvez trouver cet article intéressant: il montre comment modifier la couche SoftmaxWithLoss pour prendre en compte les poids d'échantillon.


Récemment, une modification de la perte d'entropie croisée a été proposée par Tsung-Yi Lin, Priya Goyal, Ross Girshick, Kaiming He, Piotr DollárPerte focale pour la détection d'objets denses, (ICCV 2017 ) .
L'idée sous-jacente à la perte focale est d'attribuer une pondération différente pour chaque exemple en fonction de la difficulté relative à prévoir cet exemple (plutôt en fonction de la taille de la classe, etc.). Depuis le peu de temps que j’ai pu expérimenter avec cette perte, c’est une sensation supérieure à "InfogainLoss" avec des poids pondérés. 

20
Shai

J'ai également rencontré ce problème de déséquilibre de classe dans ma tâche de classification. En ce moment, j'utilise CrossEntropyLoss avec un poids (documentation ici ) et cela fonctionne bien. L'idée est de donner plus de pertes aux échantillons dans les classes avec un plus petit nombre d'images.

Calcul du poids

poids pour chaque classe inversement proportionnelle au nombre d'images de cette classe. Voici un extrait permettant de calculer le poids pour toutes les classes à l’aide de numpy,

cls_num = []
# train_labels is a list of class labels for all training samples
# the labels are in range [0, n-1] (n classes in total)
train_labels = np.asarray(train_labels)
num_cls = np.unique(train_labels).size

for i in range(num_cls):
    cls_num.append(len(np.where(train_labels==i)[0]))

cls_num = np.array(cls_num)

cls_num = cls_num.max()/cls_num
x = 1.0/np.sum(cls_num)

# the weight is an array which contains weight to use in CrossEntropyLoss
# for each class.
weight = x*cls_num
0
jdhao