J'essaie de former un CNN à catégoriser le texte par sujet. Lorsque j'utilise l'entropie croisée binaire, j'obtiens une précision d'environ 80%, avec une entropie croisée catégorique, j'obtiens une précision d'environ 50%.
Je ne comprends pas pourquoi. C'est un problème multiclasse, cela ne signifie-t-il pas que je dois utiliser une entropie croisée catégorique et que les résultats avec une entropie croisée binaire n'ont aucun sens?
model.add(embedding_layer)
model.add(Dropout(0.25))
# convolution layers
model.add(Conv1D(nb_filter=32,
filter_length=4,
border_mode='valid',
activation='relu'))
model.add(MaxPooling1D(pool_length=2))
# dense layers
model.add(Flatten())
model.add(Dense(256))
model.add(Dropout(0.25))
model.add(Activation('relu'))
# output layer
model.add(Dense(len(class_id_index)))
model.add(Activation('softmax'))
Ensuite, je le compile soit comme ceci en utilisant categorical_crossentropy
comme fonction de perte:
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
ou
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
Intuitivement, il est logique que je veuille utiliser l'entropie croisée catégorielle, je ne comprends pas pourquoi j'obtiens de bons résultats avec des résultats binaires et des résultats médiocres avec des résultats catégoriques.
la source
categorical_crossentropy
. Les étiquettes doivent également être converties au format catégoriel. Voyezto_categorical
pour faire cela. Voir également les définitions des crossentropies catégoriques et binaires ici .categorical_crossentropy
. Si vous avez deux classes, elles seront représentées sous0, 1
forme d'étiquettes binaires et10, 01
au format d'étiquette catégorielle.Dense(1, activation='softmax')
car la classification binaire est tout simplement fausse. Rappelez-vous que la sortie softmax est une distribution de probabilité qui se résume à un. Si vous souhaitez n'avoir qu'un seul neurone de sortie avec une classification binaire, utilisez un sigmoïde avec une entropie croisée binaire.Réponses:
La raison de cette différence de performance apparente entre l'entropie croisée catégorielle et binaire est ce que l'utilisateur xtof54 a déjà signalé dans sa réponse ci - dessous , à savoir:
Je voudrais développer davantage à ce sujet, démontrer le problème sous-jacent réel, l'expliquer et proposer une solution.
Ce comportement n'est pas un bogue; la raison sous-jacente est un problème plutôt subtil et non documenté quant à la façon dont Keras devine réellement la précision à utiliser, en fonction de la fonction de perte que vous avez sélectionnée, lorsque vous incluez simplement
metrics=['accuracy']
dans votre compilation de modèle. En d'autres termes, alors que votre première option de compilationest valide, votre deuxième:
ne produira pas ce que vous attendez, mais la raison n'est pas l'utilisation de l'entropie croisée binaire (qui, du moins en principe, est une fonction de perte absolument valide).
Pourquoi donc? Si vous vérifiez le code source des métriques , Keras ne définit pas une seule métrique de précision, mais plusieurs différentes, parmi lesquelles
binary_accuracy
etcategorical_accuracy
. Ce qui se passe sous le capot, c'est que, puisque vous avez sélectionné l'entropie croisée binaire comme fonction de perte et que vous n'avez pas spécifié de métrique de précision particulière, Keras en déduit (à tort ...) que vous êtes intéressé par lebinary_accuracy
, et c'est ce qu'il renvoie - alors qu'en fait vous êtes intéressé par lecategorical_accuracy
.Vérifions que c'est bien le cas, en utilisant l' exemple MNIST CNN dans Keras, avec la modification suivante:
Pour remédier à cela, c'est-à-dire utiliser effectivement l'entropie croisée binaire comme fonction de perte (comme je l'ai dit, rien de mal à cela, du moins en principe) tout en obtenant la précision catégorique requise par le problème en question, vous devez demander explicitement
categorical_accuracy
dans le compilation de modèles comme suit:Dans l'exemple MNIST, après l'entraînement, la notation et la prédiction de l'ensemble de test comme je l'ai montré ci-dessus, les deux mesures sont maintenant les mêmes, comme elles devraient l'être:
Installation du système:
MISE À JOUR : Après mon message, j'ai découvert que ce problème avait déjà été identifié dans cette réponse .
la source
loss='categorical_crossentropy', metrics=['categorical_accuracy']
de la classification multiclasse? Ce serait mon intuitionTout dépend du type de problème de classification auquel vous faites face. Il existe trois catégories principales
Dans le premier cas, l'entropie croisée binaire doit être utilisée et les cibles doivent être codées en tant que vecteurs à un point.
Dans le second cas, une entropie croisée catégorielle doit être utilisée et les cibles doivent être codées en tant que vecteurs à un point.
Dans le dernier cas, l'entropie croisée binaire doit être utilisée et les cibles doivent être codées en tant que vecteurs one-hot. Chaque neurone de sortie (ou unité) est considéré comme une variable binaire aléatoire distincte, et la perte pour l'ensemble du vecteur de sorties est le produit de la perte de variables binaires uniques. C'est donc le produit de l'entropie croisée binaire pour chaque unité de sortie unique.
L'entropie croisée binaire est définie comme
et l'entropie croisée catégorique est définie comme
où
c
est l'index fonctionnant sur le nombre de classesla source
c
index est redondant dans la formule d'entropie croisée binaire, il n'a pas besoin d'être là (car il n'y a que 2 classes et la probabilité de chaque classe est intégréey(x)
. Sinon, ces formules devraient être correctes, mais remarquez que ce ne sont pas des pertes, ce sont des probabilités. Si vous voulez la perte, vous devez prendre lalog
de celles-ci.Je suis tombé sur un problème "inversé" - j'obtenais de bons résultats avec categorical_crossentropy (avec 2 classes) et médiocres avec binary_crossentropy. Il semble que le problème provienne d'une mauvaise fonction d'activation. Les paramètres corrects étaient:
binary_crossentropy
: activation sigmoïde, cible scalairecategorical_crossentropy
: activation softmax, cible encodée à chaudla source
C'est un cas vraiment intéressant. En fait, dans votre configuration, la déclaration suivante est vraie:
Cela signifie que jusqu'à un facteur de multiplication constant, vos pertes sont équivalentes. Le comportement étrange que vous observez pendant une phase d'entraînement peut être un exemple du phénomène suivant:
adam
- le taux d'apprentissage a une valeur beaucoup plus petite que ce qu'il avait au début de la formation (c'est à cause de la nature de cet optimiseur). Cela ralentit la formation et empêche votre réseau, par exemple, de laisser un faible minimum local moins possible.C'est pourquoi ce facteur constant pourrait aider en cas de
binary_crossentropy
. Après de nombreuses époques - la valeur du taux d'apprentissage est supérieure à celle ducategorical_crossentropy
cas. Je redémarre généralement la formation (et la phase d'apprentissage) plusieurs fois lorsque je remarque un tel comportement ou / et que j'ajuste les poids d'une classe en utilisant le modèle suivant:Cela rend la perte d'une classe moins fréquente équilibrant l'influence d'une perte de classe dominante au début d'une formation et dans une autre partie d'un processus d'optimisation.
ÉDITER:
En fait - j'ai vérifié cela même si en cas de maths:
devrait tenir - au cas où
keras
ce n'est pas vrai, car ilkeras
normalise automatiquement toutes les sorties à résumer1
. C'est la raison réelle de ce comportement étrange car en cas de multiclassification, une telle normalisation nuit à un entraînement.la source
Après avoir commenté la réponse @Marcin, j'ai vérifié plus attentivement le code d'un de mes élèves où j'ai trouvé le même comportement bizarre, même après seulement 2 époques! (L'explication de @ Marcin n'était donc pas très probable dans mon cas).
Et j'ai trouvé que la réponse est en fait très simple: la précision calculée avec la méthode Keras
evaluate
est tout simplement fausse lors de l'utilisation de binary_crossentropy avec plus de 2 étiquettes. Vous pouvez le vérifier en recalculant vous-même la précision (appelez d'abord la méthode Keras "prédire" puis calculez le nombre de réponses correctes renvoyées par prédire): vous obtenez la précision vraie, qui est bien inférieure à celle "évaluer" de Keras.la source
un exemple simple dans un cadre multi-classes pour illustrer
supposons que vous ayez 4 classes (encodées en un instant) et ci-dessous une seule prédiction
true_label = [0,1,0,0] predicted_label = [0,0,1,0]
lorsque vous utilisez categorical_crossentropy, la précision n'est que de 0, cela ne se soucie que de savoir si vous obtenez la classe concernée.
cependant, en utilisant binary_crossentropy, la précision est calculée pour toutes les classes, elle serait de 50% pour cette prédiction. et le résultat final sera la moyenne des précisions individuelles pour les deux cas.
il est recommandé d'utiliser categorical_crossentropy pour les problèmes multi-classes (les classes sont mutuellement exclusives) mais binary_crossentropy pour les problèmes multi-labels.
la source
Comme il s'agit d'un problème multi-classes, vous devez utiliser la fonction categorical_crossentropy, l'entropie croisée binaire produira de faux résultats et n'évaluera probablement que les deux premières classes uniquement.
50% pour un problème multi-classes peut être assez bon, selon le nombre de classes. Si vous avez n classes, alors 100 / n est la performance minimale que vous pouvez obtenir en sortant une classe aléatoire.
la source
lors de l'utilisation de la
categorical_crossentropy
perte, vos cibles doivent être au format catégorique (par exemple, si vous avez 10 classes, la cible de chaque échantillon doit être un vecteur à 10 dimensions qui est entièrement zéros sauf pour un 1 à l'index correspondant à la classe du échantillon).la source
Jetez un œil à l'équation, vous pouvez trouver que l' entropie croisée binaire punit non seulement ceux étiquette = 1, prédit = 0, mais aussi étiquette = 0, prédit = 1.
Cependant, l' entropie croisée catégorique ne punit que les étiquettes = 1 mais prédites = 1, c'est pourquoi nous supposons qu'il n'y a qu'une seule étiquette positive.
la source
Vous passez un tableau cible de forme (x-dim, y-dim) lors de l'utilisation comme perte
categorical_crossentropy
.categorical_crossentropy
s'attend à ce que les cibles soient des matrices binaires (1 et 0) de forme (échantillons, classes). Si vos cibles sont des classes entières, vous pouvez les convertir au format attendu via:Vous pouvez également utiliser la fonction de perte à la
sparse_categorical_crossentropy
place, qui attend des cibles entières.la source
Le binary_crossentropy (y_target, y_predict) n'a pas besoin de s'appliquer dans un problème de classification binaire. .
Dans le code source de binary_crossentropy () , la
nn.sigmoid_cross_entropy_with_logits(labels=target, logits=output)
fonction TensorFlow était en fait utilisée. Et, dans la documentation , il est dit que:la source