Classificateur de texte avec plusieurs sorties et plusieurs pertes dans Keras

Table des matières

Classificateur de texte avec plusieurs sorties et plusieurs pertes dans Keras

Dans cet article, nous allons passer en revue la définition d’un classificateur multi-étiquettes, les pertes multiples, le prétraitement de texte et une explication étape par étape sur la façon de construire un RNN-LSTM multi-sortie dans Keras.

L’ensemble de données sur lequel nous travaillerons consiste en des messages de catastrophe naturelle classés en 36 classes différentes. L’ensemble de données a été fourni par Figure huit. Exemple de messages d’entrée:

['Weather update - a cold front from Cuba that could pass over Haiti',
'Is the Hurricane over or is it not over',
'Looking for someone but no name',
'UN reports Leogane 80-90 destroyed. Only Hospital St. Croix functioning. Needs supplies desperately.',
'says: west side of Haiti, rest of the country today and tonight']
Fonction de classification Softmax dans un réseau neuronal

Pour la classification multi-étiquettes, un échantillon de données peut appartenir à plusieurs classes. A partir de l’exemple ci-dessus, votre modèle peut classer, pour le même échantillon, les classes: Voiture ET Personne (en imaginant que chaque échantillon est une image pouvant contenir ces 3 classes).

Dans l’ensemble de données étudié, il existe 36 classes différentes, dont 35 d’entre elles ont un sortie binaire: 0 ou 1; et 1 d’entre eux a 3 classes possibles (un cas multiclasse): 0, 1 ou 2.

Comment Keras gère-t-il les pertes multiples?

Du Documentation Keras, « … La valeur de perte qui sera minimisée par le modèle sera alors la somme pondérée de toutes les pertes individuelles, pondérée par le loss_weightscoefficients.« . Par conséquent, la perte finale est une somme pondérée de chaque perte, transmise au loss paramètre.

Dans le cas étudié, deux pertes différentes seront utilisées:

  • Pour le classes binaires, la métrique utilisée sera la binary_accuracy avec le correspondant binary_crossentropyperte. Puisqu’il n’y a que deux classes possibles pour chaque sortie (0 ou 1), le sigmoid sera utilisée comme fonction d’activation.
  • Pour le multiclasse production, la métrique utilisée sera la sparse_categorical_accuracy avec le correspondant sparse_categorical_crossentropy perte. Pour cette sortie, il existe 3 classes possibles: 0, 1 et 2, de cette façon le softmax la fonction d’activation sera utilisée. Différemment du classique categorical_crossentropy perte, le premier ne nécessite pas la sortie Oui être codé à chaud. Par conséquent, au lieu de transformer la sortie en: [1, 0, 0], [0, 1, 0] et [0, 0, 1], nous pouvons le laisser sous forme d’entiers: [0], [1] et [2]. Il est important de souligner que les deux pertes partagent la même équation:
Fonction de perte pour la crossentropie catégorielle et la crossentropie catégorique éparse

Mots d’arrêt (mots les plus courants dans une langue) la suppression et la lemmatisation ont également été appliquées à l’ensemble de données.

Les exemples de texte sont formatés en tenseurs qui peuvent être introduits dans un réseau de neurones à l’aide des utilitaires Keras:

La procédure ci-dessus comprend principalement 3 étapes:

  • Tout d’abord, une instance de Tokenizer est installée (fit_on_texts) au corpus créant un index de vocabulaire basé sur la fréquence des mots. Chaque mot est mappé à un index, donc chaque mot obtient une valeur entière unique, un entier inférieur signifie des mots plus fréquents. La taille des mots à conserver est définie par le num_words paramètre, c’est-à-dire la taille du vocabulaire. Seuls les mots les plus courants seront conservés. Dans notre jeu de données, les mots ont été mappés comme suit:
print(tokenizer.word_index){'water': 1, 'people': 2, 'food': 3, 'need': 4, 'help': 5, 'please': 6, 'earthquake': 7, 'would': 8, 'area': 9, 'like': 10, 'said': 11, 'country': 12,...}
  • Les phrases de l’entrée sont ensuite mappées en nombres entiers à l’aide du tokenizer.texts_to_sequences méthode. De notre exemple:
'weather update cold front cuba could pa haiti'

est mappé à:

[138, 1480, 335, 863, 2709, 80, 411, 18]
  • Enfin, pour créer des plongements, toutes nos phrases doivent être de même longueur. Par conséquent, nous utilisons le pad_sequencespour remplir chaque phrase avec zéro.

Pour résumer ce que nous avons jusqu’à présent:

  • chaque échantillon d’entrée est un vecteur d’entiers de taille MAXLEN (50)
  • chaque échantillon sera classé en 36 classes différentes dont 35 d’entre elles ont un sortie binaire: 0 ou 1; et 1 d’entre eux a 3 classes possibles (un cas multiclasse): 0, 1 ou 2.

Architecture du modèle

La couche Embedding prend en entrée:

  • input_dim: la taille du vocabulaire que nous avons choisie
  • output_dim: la taille de l’incorporation. Dans notre cas, il était réglé sur 50d.
  • longueur_entrée: Longueur des séquences d’entrée. Dans notre cas: MAXLEN

Une couche convolutionnelle a été ajoutée avant le LSTM afin d’accélérer le temps d’entraînement. CNN est plus susceptible d’extraire des éléments locaux et profonds des phrases. Vous pouvez en savoir plus sur la combinaison CNN et RNN dans Cet article.

Couche de sortie

Étant donné que l’ensemble de données est fortement déséquilibré, class_weight paramètre a été ajouté afin de réduire les distributions déséquilibrées. UNE Couche dense sera créé pour chaque sortie. Les sorties seront stockées dans un tableau, tandis que les métriques et les pertes, pour chaque sortie, seront stockées dans les dictionnaires correspondants.

Le code ci-dessus parcourt chacune des colonnes binaires de sortie et crée une couche dense, enregistrant la métrique et la perte correspondantes dans un dictionnaire.

Le code ci-dessous applique le même processus à la colonne de sortie multiclasse unique.

Pour chaque sortie, nous définissons ensuite le poids de chaque classe dans un format de dictionnaire:

Nous pouvons alors instancier une classe Model et former notre modèle:

Le modèle suit le format:

Représentation graphique du RNN

Apparemment, Keras a un question ouverte avec class_weights et binary_crossentropy pour les sorties multi-étiquettes. La solution proposée ci-dessus, en ajoutant une couche dense par sortie, est une solution valable.

Vous pouvez vérifier le code complet, avec une analyse supplémentaire, dans Ici! Dans ce post, nous avons formé nos propres plongements, dans le GitHub Repo, vous pouvez vérifier le même modèle recyclé en utilisant Vecteurs GloVe pré-formés.