web-dev-qa-db-fra.com

Keras: Comment calcule-t-on l'exactitude pour la classification multi-étiquettes?

Je suis en train de relever le défi Kaggle du texte de commentaires sur les commentaires toxiques. Il y a 6 classes: ['threat', 'severe_toxic', 'obscene', 'insult', 'identity_hate', 'toxic']. Un commentaire peut être multiple de ces classes, donc c'est un problème de classification multi-étiquettes.

J'ai construit un réseau de neurones de base avec Keras comme suit:

model = Sequential()
model.add(Embedding(10000, 128, input_length=250))
model.add(Flatten())
model.add(Dense(100, activation='relu'))
model.add(Dense(len(classes), activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

Je lance cette ligne:

model.fit(X_train, train_y, validation_split=0.5, epochs=3)

et obtenez une précision de 99,11% après 3 époques.

Cependant, une précision de 99,11% est un peu plus élevée que la meilleure soumission Kaggle. Cela me fait penser que je suis (peut-être les deux) a) sur-ajustant ou b) d'utiliser abusivement la précision de Keras.

1) Cela semble un peu difficile à surpasser lorsque j'utilise 50% de mes données en tant que fractionnement de validation et que 3 époques.

2) La précision est-elle juste le pourcentage du temps que le modèle obtient chaque classe correcte?

Donc si je produisais [0, 0, 0, 0, 0, 1] et que la sortie correcte était [0, 0, 0, 0, 0, 0], mon exactitude serait 5/6?

Après un peu de réflexion, je pense que la métrique accuracy ne fait que regarder la classe prédite par mon modèle avec la plus grande confiance et en comparant la vérité au sol. 

Donc, si mon modèle génère [0, 0, 0.9, 0, 0, 0], il comparera la classe à l'index 2 ('obscene') avec la valeur vraie. Pensez-vous que c'est ce qui se passe?

Merci pour toute aide que vous pouvez offrir!

7
bclayman

Pour la classification multi-étiquettes, je pense qu'il est correct d'utiliser sigmoid comme activation et binary_crossentropy comme perte.

Si la sortie est multi-étiquettes clairsemées, ce qui signifie quelques étiquettes positives et une majorité d'étiquettes négatives, la métrique Keras accuracy sera surchargée par les étiquettes négatives correctement prédites. Si je me souviens bien, Keras ne choisit pas l'étiquette présentant la probabilité la plus élevée. Au lieu de cela, pour la classification binaire, le seuil est de 50%. Donc, la prédiction serait [0, 0, 0, 0, 0, 1]. Et si les étiquettes réelles étaient [0, 0, 0, 0, 0, 0], la précision serait 5/6. Vous pouvez tester cette hypothèse en créant un modèle qui prédit toujours une étiquette négative et examine la précision.

Si c'est effectivement le cas, vous pouvez essayer une métrique différente telle que top_k_categorical_accuracy .

Une autre possibilité à laquelle je peux penser est vos données d’entraînement. Les étiquettes y sont-elles en quelque sorte "filtrées" dans x? Juste une conjecture sauvage.

3
neurite

Vous pouvez vous référer à documentation Keras Metrics pour voir toutes les mesures disponibles (par exemple, binary_accuracy). Vous pouvez également créer votre propre métrique personnalisée (et vous assurer qu'elle correspond exactement à vos attentes). Je voulais être sûr que neurite avait raison sur la manière dont la précision est calculée. C’est ce que j’ai fait (remarque: activation="sigmoid"):

from keras.metrics import binary_accuracy
def custom_acc(y_true, y_pred):
    return binary_accuracy(y_true, y_pred)

# ...

model.compile(loss="binary_crossentropy", optimizer=optimizer, metrics=[
    "accuracy",
    "binary_accuracy",
    "categorical_accuracy",
    "sparse_categorical_accuracy",
    custom_acc
])

En exécutant la formation, vous verrez que le custom_acc est toujours égal au binary_accuracy (et donc au custom_acc). 

Maintenant, vous pouvez vous référer au code Keras sur Github pour voir comment il est calculé: 

K.mean(K.equal(y_true, K.round(y_pred)), axis=-1)

Ce qui confirme ce que neurite a dit (c.-à-d. Si la prédiction est [0, 0, 0, 0, 0, 1] et les étiquettes réelles étaient [0, 0, 0, 0, 0, 0], la précision serait de 5/6). 

2
smichaud