Keras binary_crossentropy vs catégorical_crossentropy performances?

J’essaie de former un CNN pour classer le texte par sujet. Quand j’utilise binary_crossentropy j’obtiens ~ 80% d’acc, avec catégorical_crossentrop je reçois ~ 50% d’acc.

Je ne comprends pas pourquoi. C’est un problème de multiclass, cela signifie-t-il que je dois utiliser catégorique et que les résultats binarys n’ont pas de 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')) 

puis

 model.comstack(loss='categorical_crossentropy', optimizer='adam', mesortingcs=['accuracy']) 

ou

 model.comstack(loss='binary_crossentropy', optimizer='adam', mesortingcs=['accuracy']) 

    La raison de cette différence de performance apparente entre entropie catégorielle et binary est ce que @ xtof54 a déjà signalé dans sa réponse, à savoir:

    la précision calculée avec la méthode Keras “évaluer” est tout simplement fausse lorsque vous utilisez binary_crossentropy avec plus de 2 étiquettes

    J’aimerais approfondir ce point, démontrer le problème sous-jacent, 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é sur la manière dont Keras devine la précision à utiliser, en fonction de la fonction de perte que vous avez sélectionnée, lorsque vous incluez simplement mesortingcs=['accuracy'] dans votre compilation. En d’autres termes, votre première option de compilation

     model.comstack(loss='categorical_crossentropy', optimizer='adam', mesortingcs=['accuracy']) 

    est valide, votre deuxième:

     model.comstack(loss='binary_crossentropy', optimizer='adam', mesortingcs=['accuracy']) 

    ne produira pas ce que vous attendez, mais la raison n’est pas l’utilisation d’une entropie binary (qui, du moins en principe, est une fonction de perte absolument valide).

    Pourquoi donc? Si vous vérifiez le code source des mesures , Keras ne définit pas une seule mesure de précision, mais plusieurs différentes, parmi lesquelles binary_accuracy et categorical_accuracy . Ce qui se passe sous le capot est que, puisque vous avez sélectionné l’entropie binary comme fonction de perte et que vous n’avez pas spécifié de mésortingque de précision particulière, Keras (à tort …) en déduit que vous êtes intéressé par la binary_accuracy . – en fait, vous êtes intéressé par la categorical_accuracy la categorical_accuracy .

    Vérifions que c’est le cas, en utilisant l’ exemple MNIST CNN dans Keras, avec la modification suivante:

     model.comstack(loss='binary_crossentropy', optimizer='adam', mesortingcs=['accuracy']) # WRONG way model.fit(x_train, y_train, batch_size=batch_size, epochs=2, # only 2 epochs, for demonstration purposes verbose=1, validation_data=(x_test, y_test)) # Keras reported accuracy: score = model.evaluate(x_test, y_test, verbose=0) score[1] # 0.9975801164627075 # Actual accuracy calculated manually: import numpy as np y_pred = model.predict(x_test) acc = sum([np.argmax(y_test[i])==np.argmax(y_pred[i]) for i in range(10000)])/10000 acc # 0.98780000000000001 score[1]==acc # False 

    Pour remédier à cela, c’est-à-dire utiliser l’entropie binary croisée comme fonction de perte (comme je l’ai dit, rien à redire, tout en principe) tout en obtenant la précision catégorique requirejse par le problème, vous devez demander explicitement categorical_accuracy dans la compilation du modèle comme suit:

     from keras.mesortingcs import categorical_accuracy model.comstack(loss='binary_crossentropy', optimizer='adam', mesortingcs=[categorical_accuracy]) 

    Dans l’exemple MNIST, après l’entraînement, l’évaluation et la prédiction de l’ensemble de tests que j’ai montré ci-dessus, les deux mésortingques sont désormais les mêmes:

     # Keras reported accuracy: score = model.evaluate(x_test, y_test, verbose=0) score[1] # 0.98580000000000001 # Actual accuracy calculated manually: y_pred = model.predict(x_test) acc = sum([np.argmax(y_test[i])==np.argmax(y_pred[i]) for i in range(10000)])/10000 acc # 0.98580000000000001 score[1]==acc # True 

    Installation du système:

     Python version 3.5.3 Tensorflow version 1.2.1 Keras version 2.0.4 

    MISE À JOUR : Après mon post, j’ai découvert que ce problème avait déjà été identifié dans cette réponse .

    C’est un cas vraiment intéressant. En fait, dans votre configuration, la déclaration suivante est vraie:

     binary_crossentropy = len(class_id_index) * categorical_crossentropy 

    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 pourrait être un exemple de phénomène suivant:

    1. Au début, la classe la plus fréquente domine la perte – donc le réseau apprend à prédire principalement cette classe pour chaque exemple.
    2. Après avoir appris le schéma le plus fréquent, il commence à faire la distinction entre les classes moins fréquentes. Mais lorsque vous utilisez adam – le taux d’apprentissage a une valeur beaucoup plus faible qu’au début de l’entraînement (en raison de la nature de cet optimiseur). Cela ralentit la formation et empêche votre réseau, par exemple, de laisser un minimum local insuffisant.

    C’est pourquoi ce facteur constant pourrait aider dans le cas de binary_crossentropy . Après plusieurs époques, la valeur du taux d’apprentissage est plus grande que dans le cas de la categorical_crossentropy . Je recommence habituellement l’entraînement (et la phase d’apprentissage) plusieurs fois lorsque je remarque un tel comportement et / ou en ajustant les poids d’une classe en utilisant le schéma suivant:

     class_weight = 1 / class_frequency 

    Cela entraîne la perte de classes moins fréquentes, en équilibrant l’influence d’une perte de classe dominante au début d’une formation et dans une autre partie du processus d’optimisation.

    MODIFIER:

    En fait – j’ai vérifié cela même en cas de maths:

     binary_crossentropy = len(class_id_index) * categorical_crossentropy 

    devrait tenir – dans le cas de keras c’est pas vrai, parce que keras normalise automatiquement toutes les sorties pour totaliser 1 . C’est la raison de ce comportement étrange, car en cas de multiclassification, cette normalisation nuit à la formation.

    Je suis tombé sur un problème “inversé” – je obtenais de bons résultats avec categorical_crossentropy (avec 2 classes) et médiocre avec binary_crossentropy. Il semble que le problème était dû à une mauvaise fonction d’activation. Les parameters corrects étaient les suivants:

    • pour binary_crossentropy : activation sigmoïde, cible scalaire
    • pour categorical_crossentropy : activation softmax, cible codée à chaud

    Après avoir commenté la réponse de @Marcin, j’ai vérifié plus attentivement l’un de mes codes d’élèves où j’ai trouvé le même comportement étrange, même après seulement 2 époques! (L’explication de So @ Marcin n’était 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 de Keras “évaluer” est tout simplement fausse quand on utilise binary_crossentropy avec plus de 2 étiquettes. Vous pouvez vérifier cela en recalculant vous-même la précision (appelez d’abord la méthode de Keras “prédire” puis calculez le nombre de réponses correctes renvoyées par predire): vous obtenez la vraie précision, beaucoup plus faible que celle de Keras.

    Tout dépend du type de problème de classification auquel vous faites face. Il y a trois catégories principales;

    • classification binary (deux classes cibles)
    • classification multi-classes (plus de deux cibles exclusives )
    • classification multi-label (plus de deux cibles non exclusives ) dans laquelle plusieurs classes cibles peuvent être activées en même temps

    Dans le premier cas, une entropie binary devrait être utilisée et les cibles devraient être codées comme des vecteurs uniques.

    Dans le second cas, une entropie entrelacée catégorique devrait être utilisée et les cibles devraient être codées comme des vecteurs à un seul point.

    Dans le dernier cas, une entropie binary devrait être utilisée et les cibles devraient être codées comme des vecteurs uniques. Chaque neurone de sortie (ou unité) est considéré comme une variable binary aléatoire distincte, et la perte pour le vecteur entier des sorties est le produit de la perte de variables binarys uniques. C’est donc le produit de l’entropie binary croisée pour chaque unité de sortie.

    entropie binary est définie comme telle: entropie binary et entropie catégorique est défini comme tel: entropie catégorique

    Comme il s’agit d’un problème multi-classes, vous devez utiliser la propriété Concentration_Catégorical, l’entropie croisée binary produira des résultats erronés, le plus probable étant d’évaluer uniquement les deux premières classes.

    50% pour un problème multi-classe 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 produisant une classe aléatoire.

    Lorsque vous utilisez la perte categorical_crossentropy , vos cibles doivent être au format catégorique (par exemple, si vous avez 10 classes, la cible pour chaque échantillon doit être un vecteur à 10 dimensions, à l’exception de 1 à l’index correspondant à la classe de l’échantillon).