Machine Learning – Classification des textes, Modélisation de la langue avec fast.ai – Apprendre une langue étrangère

Application des dernières techniques d'apprentissage en profondeur pour le traitement de texte

Javaid Nabi

Ttransférer l'apprentissage est Une technique où, au lieu de former un modèle à partir de rien, nous réutilisons un modèle pré-formé, puis l'ajustons pour une autre tâche connexe. Il a eu beaucoup de succès dans les applications de vision par ordinateur. Dans le traitement du langage naturel (NLP), l’apprentissage par transfert était principalement limité à l’utilisation d’embeddages de mots pré-formés. Recherche dans le domaine de l'utilisation modélisation du langage pendant la pré-formation, les résultats les plus récents pour la plupart des tâches de la PNL ont été considérablement renforcés, tels que la classification des textes, l'inférence en langage naturel et la réponse aux questions par le biais de diverses approches telles que ULMFiT, OpenAI Transformer, ELMO et. Le BERT de Google AI.

Dans cet article, nous aborderons les limites de l'approche d'intégration de mots dans l'apprentissage par transfert pour les problèmes de PNL et l'utilisation du modèle de langage pour créer un classifieur de texte à l'aide de la bibliothèque fast.ai.

Transférer l'apprentissage avec les données linguistiques

Les algorithmes d'incorporation de mots word2vec et GloVe permettent de mapper des mots dans un espace vectoriel continu de grande dimension, où différents mots ayant une signification similaire ont une représentation vectorielle similaire. Ces mots incorporés, pré-entraînés sur de grandes quantités de données non étiquetées, sont utilisés pour initialiser la première couche d’un réseau neuronal appelée couche d’incorporation, le reste du modèle étant ensuite formé aux données d’une tâche particulière. Ce type d’apprentissage par transfert dans les problèmes de PNL est peu profond comme l'apprentissage est transféré à la première couche du modèle, le reste du réseau doit encore être formé à partir de zéro. Un modèle initialisé avec des mots imbriqués doit apprendre à partir de zéro non seulement pour lever les mots des ambiguïtés, mais aussi pour tirer le sens d'une séquence de mots. Pour ce faire, les modèles de PNL initialisés avec ces représentations peu profondes nécessitent un jeu de données volumineux pour obtenir de bonnes performances, ce qui peut entraîner des coûts de calcul très importants. [1].

Modélisation de la langue

La modélisation du langage a pour objectif principal la compréhension du langage. Elle nécessite la modélisation de phénomènes langagiers complexes pour traiter des problèmes de compréhension du langage complexes tels que la traduction, la réponse à une question et l'analyse de sentiments. Un modèle de langage tente d'apprendre la structure du langage naturel par le biais de représentations hiérarchiques. Il contient donc à la fois des entités de bas niveau (représentations de mots) et des entités de haut niveau (signification sémantique). Une caractéristique clé de la modélisation du langage est qu’il est génératif, ce qui signifie qu’il vise à prédire le mot suivant à partir d’une séquence de mots précédente. Il est capable de le faire parce que les modèles de langage sont généralement formés de manière non supervisée sur de très grands ensembles de données et qu'il peut donc «apprendre» les caractéristiques syntaxiques du langage d'une manière beaucoup plus profonde que les mots incorporés. [2].

Pour prédire le mot suivant d'une phrase, le modèle doit en réalité en savoir beaucoup sur la langue et sur le monde. Voici un exemple:

  • "Je voudrais manger un ___ chaud": évidemment, "chien", non?
  • “C'était un ___ chaud”: Probablement “jour”

Comme vous pouvez le constater, il n’ya pas assez d’informations ici pour décider du mot probablement suivant. Mais avec un réseau de neurones, vous pouvez absolument, pourvu que vous entraîniez un réseau de neurones pour prédire le mot suivant d'une phrase, alors vous avez beaucoup d'informations. [3].

AI rapide

fastai La bibliothèque se concentre sur l’utilisation de modèles de langage pré-formés et leur réglage, en trois étapes:

  1. Pré-traitement des données dans un minimum de code.
  2. Créer un modèle de langage avec des poids pré-formés que vous pouvez ajuster à votre jeu de données.
  3. Créer d'autres modèles tel que classificateurs sur le modèle de langue.

Environnement

Avant de continuer, nous devons configurer l'environnement pour fast.ai.

Installation et mise à jour

Pour installer fastai:

installer - pytorque - fastai pytorque

Si vous souhaitez essayer des options prêtes à l'emploi:

  • Colab: Gratuit, nécessite l'installation de fast.ai
  • Kaggle Kernels: Gratuit, Aucune installation requise, mais pas officiellement supportée
  • Floydhub; Aucune installation requise, crédit gratuit de 2 heures pour le processeur et de 2 pour le processeur graphique

J’ai utilisé Colab pour l’apprentissage initial, mais j’ai rencontré beaucoup de problèmes «déconnectés». Kaggle est une autre bonne option aussi. Floydhub a bien fonctionné, mais après des crédits gratuits, vous devez payer pour l’utilisation. Après avoir configuré votre environnement, laissez-nous procéder pour une action.

Construire un classificateur de texte

Laissez-nous construire un classificateur de texte pour classer les sentiments du jeu de données de film IMDB en utilisant les techniques décrites jusqu'à présent. Le jeu de données IMDb contient 25 000 critiques de films pour la formation et 25 000 pour les tests. Nous avons déjà les données IMDb téléchargées et sauvegardées au format CSV du message précédent. Laissez-nous charger les données dans un dataframe,

«1» sentiment positif et «0» sentiment négatif

en utilisant le morceau de code ci-dessous.

df_imdb = pd.read_csv (chemin / 'movies_data.csv')
df_imdb.head ()
#Chargement de quelques échantillons d'entraînement et de validation, pour une formation rapide
trn_texts = df_imdb.loc[10000:14999, 'review'].valeurs
trn_labels = df_imdb.loc[10000:14999, 'sentiment'].valeurs
val_texts = df_imdb.loc[36000:38999, 'review'].valeurs
val_labels = df_imdb.loc[36000:38999, 'sentiment'].valeurs
np.random.seed (42)
trn_idx = np.random.permutation (len (trn_texts))
val_idx = np.random.permutation (len (val_texts))
trn_texts = trn_texts[trn_idx]
val_texts = val_texts[val_idx]
trn_labels = trn_labels[trn_idx]
val_labels = val_labels[val_idx]
noms_colonne = ['labels','text']
df_trn = pd.DataFrame ('text': trn_texts, 'labels': trn_labels, columns = noms_col)
df_val = pd.DataFrame ('text': val_texts, 'labels': val_labels, columns = noms_col)

Nous utilisons 5000 [2500 each label] de la formation et 3000[1500 each label] à partir d'exemples de validation. J'utilise un ensemble plus petit pour terminer la formation plus rapidement. Veuillez utiliser l'ensemble de données complet pour améliorer les performances.

Étape 1: prétraitement des données

Créer un jeu de données à partir de vos textes bruts est très simple. La bibliothèque fournit des API très faciles à utiliser [4], en fonction de la structure de nos données, créer une classe de données TextDataBunch pour le traitement de texte, from_csv, from_folder,from_df reportez-vous à la documentation pour plus de détails. Ici nous allons utiliser la méthode from_df du TextLMDataBunch pour créer un groupe de données spécifique au modèle de langage:

# Données du modèle de langage
data_lm = TextLMDataBunch.from_df ('./', train_df = df_trn, valid_df = df_val)

Cela fait tout le prétraitement nécessaire en coulisse. Voyons comment les données sont encodées par fast.ai

data_lm.show_batch ()

Nous pouvons voir qu'un certain nombre de balises sont appliquées aux mots, comme indiqué ci-dessus. Ceci permet de conserver toutes les informations pouvant être utilisées pour mieux comprendre le vocabulaire de la nouvelle tâche. Tous les signes de ponctuation, hashtags et caractères spéciaux sont également conservés. Le texte est codé avec différents jetons, comme ci-dessous:

  • xxbos: Début d'une phrase
  • xxfld: Représente différentes parties d’un document telles que le titre, le résumé, etc., chacune d’entre elles recevront un champ distinct et seront donc numérotées (par exemple, xxfld 1, xxfld 2).
  • xxup: S'il y a quelque chose en majuscule, ça devient plus bas et un jeton appelé xxup sera ajouté à cela. Les mots qui sont entièrement en majuscule, tels que «JE SUIS CRIENT», sont marqués comme «xxup i xxup am xxup crier
  • xxunk: jeton utilisé à la place d'un mot peu commun.
  • xxmaj: Le jeton indique qu'il y a une majuscule du mot. "Le" sera marqué comme "xxmaj le“.
  • xxrep: le jeton indique un mot répété, si vous avez 29 ! dans une rangée, (c'est-à-dire xxrep 29!).

Vocabulaire: La liste des jetons uniques possibles s'appelle le vocabulaire. Liste ci-dessous 20 premiers jetons uniques par ordre de fréquence:

data_lm.vocab.itos[:20]
['xxunk', 'xxpad', 'xxbos', 'xxfld', 'xxmaj', 'xxup', 'xxrep', xxwrep', 'the', '.', ',', 'a', 'and', 'of', 'to', 'is', 'it', 'in', i', 'this']

Numéricalisation: Enfin, il est plus facile pour la machine de traiter les nombres, donc remplacez les jetons par l’emplacement du jeton dans le vocabulaire:

La taille de vocabulaire par défaut est fixée à 60 000 mots et le nombre minimal de mots pour qu'un mot soit ajouté à vocab est de 2, afin d'éviter que la matrice de poids ne devienne énorme.

Enregistrer et charger: Nous pouvons enregistrer le groupe de données une fois le pré-traitement terminé. Nous pouvons également charger à tout moment.

# enregistrer et charger
data_lm.save (
'tmp_lm')
data_lm = TextClasDataBunch.load ('./', 'tmp_lm')

Étape 2: Créer un modèle de langage

Fast.ai a un modèle Wikitext pré-formé, consistant en un sous-ensemble pré-traité de 103 millions de jetons extraits de Wikipedia. C’est un modèle qui comprend beaucoup de choses sur le langage et beaucoup sur ce que décrit le langage. La prochaine étape consiste à affiner ce modèle et à transférer l’apprentissage pour créer un nouveau modèle de langage particulièrement efficace pour prédire le mot suivant de critiques de films.

Modèle de langage affiné

Il s'agit de la première étape de la formation, au cours de laquelle nous utilisons les poids de modèle linguistique pré-formés et les peaufinons avec les données de formation des critiques de films IMDb. Lorsque nous créons un apprenant, nous devons passer en deux choses:

  • Les données: les données de notre modèle de langue (data_lm)
  • Un modèle pré-formé: ici, le modèle pré-formé est le modèle Wikitext 103 qui sera téléchargé pour vous à partir de fastai.
# Modèle de langage
learner = language_model_learner (data_lm, pretrained_model = URLs.WT103_1, drop_mult = 0.5)

drop_mult , un hyper-paramètre, utilisé pour la régularisation, définit la quantité d’abandons. Si le modèle est en sur-ajustement, augmentez-le. Si vous sous-ajustez, vous pouvez en diminuer le nombre.

Comment ajuster le modèle pré-formé sur nos données de critique de film? L’hyper-paramètre du taux d’apprentissage est l’un des paramètres les plus importants pour la formation d’un modèle. Fast.ai fournit un utilitaire pratique (learn.lr_find) pour rechercher une gamme de taux d’apprentissage afin de trouver le meilleur pour notre jeu de données. Le détecteur de taux d'apprentissage augmentera le taux d'apprentissage après chaque mini-lot. Finalement, le taux d’apprentissage est trop élevé pour que les pertes s’aggravent. Examinons maintenant l’intrigue du taux d’apprentissage contre la perte et déterminez le point le plus bas (environ 1e-1 pour l'intrigue ci-dessous) et revenir en arrière d'une grandeur et choisir cela comme taux d'apprentissage (quelque chose autour de 1e-2).

Former le modèle:

Nous commençons à former le modèle avec un taux d'apprentissage 1e-2 en utilisant fit_one_cycle.

La bibliothèque fast.ai utilise les dernières techniques de recherche en apprentissage approfondi et un cycle d'apprentissage est tiré d'un article récent et s'est avéré à la fois plus précis et plus rapide que n'importe quelle approche précédente. Le premier argument «1» est le nombre de périodes. Nous obtenons une précision de 29% après avoir exécuté une seule époque.

Les dernières couches ont été formées et la plupart du modèle est resté tel quel. Mais ce que nous voulons vraiment, c’est d’entraîner l’ensemble du modèle. Normalement, après avoir peaufiné les dernières couches, nous allons ensuite dégeler (dégeler le modèle entier pour la formation) et former le tout.

learn.unfreeze ()
learn.fit_one_cycle (1, 1e-3)
époque train_loss valid_loss exact

1 3,897383 3,977569 0,302463

Précision = 0,3 signifie que le modèle devine correctement le mot suivant de la critique de film environ un tiers du temps. Cela semble être un nombre assez élevé. C’est donc un bon signe que mon modèle linguistique se débrouille plutôt bien.

Prédire avec le modèle de langage

Pour évaluer notre modèle de langage, nous pouvons maintenant exécuter learn.predict et passez le début d'une phrase et spécifiez le nombre de mots que nous voulons qu'elle devine.

C'est une réponse plutôt décente et qui ressemble à une grammaire correcte. Après ajustement, nous obtenons un modèle qui comprend bien les critiques de films et nous pouvons l’ajuster avec l’apprentissage par transfert pour classer les critiques de films comme positifs ou négatifs. Sauvegardons l’encodage du modèle à utiliser ultérieurement pour la classification.

learn.save_encoder ('fine_enc')

La partie du modèle qui comprend la phrase s'appelle le codeur. Nous l’avons donc réservé pour l’utiliser plus tard au cours de la phase de classification.

Création du classificateur

Nous sommes maintenant prêts à créer notre classificateur. La première étape consiste à créer un groupe de données, TextClasDataBunch, passer le vocabulaire du modèle de langage pour s'assurer que ce groupe de données aura exactement le même vocabulaire. Taille du lot bs être utilisé est fonction de la mémoire GPU dont vous disposez, pour un GPU de 16 Go, environ bs = 64 fonctionnera correctement. Vous pouvez trouver la taille du lot qui convient sur votre carte et l'utiliser en conséquence.

# Données du modèle de classificateur
data_clas = TextClasDataBunch.from_df ('./', train_df = df_trn, valid_df = df_val, vocab = data_lm.train_ds.vocab, bs = 32)

Enfin, nous allons créer un apprenant classificateur de texte. Charge dans notre modèle pré-train, la partie encodage que nous avons enregistrée précédemment 'Fine_enc'.

# Classificateur
classifier = text_classifier_learner (data_clas, drop_mult = 0.5)
classifier.load_encoder ('fine_enc')

Encore une fois, nous suivons la même procédure pour trouver le taux d’apprentissage et former le modèle.

Le taux d'apprentissage autour de 2e-2 semble juste, alors entraînons le classificateur:

Obtenez une précision de 85% en 16 minutes d’entraînement et en utilisant uniquement des échantillons d’entraînement 5K et de validation 3K. C'est le pouvoir de l'apprentissage par transfert.

Tracé de perte: Laissez-nous tracer la perte tout en formant le modèle:

La courbe de perte semble diminuer progressivement et n’a pas encore atteint le point de saturation. fastai calcule la moyenne mobile pondérée de manière exponentielle des pertes, ce qui facilite la lecture de ces graphiques [by making the curve smoother] dans le même temps, il se peut qu’il y ait un ou deux lots de retard.

Deep Learning Techniques de réglage hyper-paramètres

Laissez-nous comprendre les techniques que Fast.ai utilise ci-dessous pour obtenir des résultats aussi impressionnants.

Taux d’apprentissage discriminants: Appliquer différents taux d’apprentissage aux couches à mesure que vous passez de couche en couche. Lors de l’adaptation d’un modèle, vous pouvez établir une liste de taux d’apprentissage qui appliquera un taux différent à chaque programme. groupe de couches. Quand on travaille avec Apprenant sur lequel vous avez appelé Divisé, vous pouvez définir des hyper-paramètres de quatre manières différentes:

  1. param = [val1, val2 ..., valn] (n = nombre de groupes de couches)
  2. param = val
  3. param = slice (début, fin)
  4. param = slice (fin)

Si nous choisissons de le définir de la manière 1, nous devons spécifier un nombre de valeurs exactement égal au nombre de groupes de couches. Si nous choisissons de le définir de la manière 2, la valeur choisie sera répétée pour tous les groupes de couches. Si vous passez tranche (début, fin) alors le taux d'apprentissage du premier groupe est début, le dernier est finet les autres sont espacés régulièrement.

Si vous passez juste tranche (fin) alors le taux d'apprentissage du dernier groupe est finet tous les autres groupes sont fin / 10. Par exemple (pour notre apprenant qui a 3 groupes de couches):

learn.lr_range (tranche (1e-5,1e-3)), learn.lr_range (tranche (1e-3))(array ([1.e-05, 1.e-04, 1.e-03]), tableau ([0.0001, 0.0001, 0.001 ]))

Le bas et le haut de la tranche représentent la différence entre la rapidité d'apprentissage de la couche la plus basse du modèle et celle de la couche la plus élevée du modèle. D’une couche à l’autre, nous réduisons le taux d’apprentissage. Les taux d’apprentissage sont plus faibles pour les niveaux les plus bas afin de ne pas trop déranger les poids.

Fit un cycle

Qu'est-ce que fit_one_cycle ()? Il s’agit d’un cycle d’apprentissage: début bas, montée puis descente. Laissez-nous tracer le taux d'apprentissage par lot en utilisant plot_lr

à gauche: taux d'apprentissage d'un cycle, à droite: vitesse d'un cycle

Lorsque nous appelons fit_one_cycle, nous transmettons un taux d’apprentissage maximal. Le graphique de gauche montre l'évolution du taux d'apprentissage par rapport aux lots. L'apprentissage commence lentement et augmente environ la moitié du temps, puis diminue environ la moitié du temps. Au fur et à mesure que vous vous rapprochez de la réponse finale, vous devez modifier votre taux d’apprentissage pour l’affiner. Cela s'explique par le fait qu'au milieu de l'apprentissage, lorsque le taux d'apprentissage est plus élevé, le taux d'apprentissage fonctionne comme une méthode de régularisation et empêche le réseau de se surcharger. Cela aide le réseau à éviter les zones de perte raides et à mieux atterrir. Veuillez vous référer à cet article de Leslie Smith qui parle en détail du réglage des hyper-paramètres de réseaux neuronaux et vous pouvez trouver la plupart de ces idées mises en œuvre dans fastai.

Élan

Il y a encore un argument (mamans = (0.8,0.7)) Ommomentums est égal à 0,8,0,7. Fondamentalement pour la formation de réseaux de neurones récurrents (RNN), il est vraiment utile de réduire un peu l’élan. Le côté droit ci-dessus est l’intrigue de l’élan. Chaque fois que notre taux d'apprentissage est faible, notre élan est élevé. Pourquoi donc? Parce que lorsque vous apprenez un petit taux d’apprentissage, mais que vous continuez dans la même direction, vous pouvez aussi aller plus vite (plus d’élan). Mais comme vous apprenez un taux d’apprentissage élevé, mais que vous continuez dans la même direction, vous risquez de dépasser la cible, vous devez donc ralentir l’élan. Cette astuce peut vous aider à vous entraîner 10 fois plus vite.

Peaufiner plus loin:

Pour améliorer encore la précision, fast.ai fournit quelques astuces supplémentaires.freeze_to. Ne dégelez pas le tout mais dégelez une couche à la fois. L'approche ci-dessous fonctionne très bien et donne des résultats incroyables.

  • dégeler les deux dernières couches freeze_to (-2), entraînez-le un peu plus
  • dégeler la couche suivante freeze_to (-3), entraînez-le un peu plus
  • dégeler le tout dégeler(), entraînez-le un peu plus

Nous avons atteint une précision de 90%. La perte d'apprentissage est toujours supérieure à la perte de validation, nous ne sommes donc pas encore sur-équipés, il est encore possible d’améliorer la précision en exécutant plus d’époques.

Matrice de confusion

Dans les problèmes de classification, il est très utile d’utiliser une matrice de confusion qui indique pour chaque étiquette le nombre de fois qu’elle a été prédite correctement. Confusion-matrix est une bonne technique pour résumer les performances d'un algorithme de classification.

Nous utilisons ClassificationInterprétationclasse à faire le travail pour nous.

Laissez-nous utiliser notre classificateur et prédire une critique de film:

Ceci est prédit comme «0», critique négative. Fantastique!!!

Nous avons déjà effectué une classification des sentiments de la critique de film IMDb en utilisant l’approche classique de l’apprentissage automatique, puis en utilisant la méthode d’incorporation de mots. L’approche de modélisation linguistique en utilisant fast.ai est l’outil le plus simple et le plus puissant que j’ai rencontré. La bibliothèque fournit des méthodes très faciles à utiliser et avec quelques lignes de code, vous pouvez obtenir des résultats à la pointe de la technologie. S'il vous plaît se référer à cahier jupyter ici.

Conclusion

Nous avons brièvement discuté de l’utilisation de l’apprentissage par transfert dans les problèmes de PNL. Nous avons exploré en détail la bibliothèque fast.ai et différentes techniques de réglage hyper-paramètres. Nous avons créé un modèle de langage et l'avons appliqué plus tard au problème de classification de texte. J'espère que vous avez apprécié ce post et appris quelque chose de nouveau et d'utile.

Merci pour la lecture.

Références:

[1] http://ruder.io/nlp-imagenet/

[2] https://towardsdatascience.com/transfer-learning-in-nlp-for-tweet-stance-classification-8ab014da8dde

[3] https://course.fast.ai/

[4] https://docs.fast.ai/text.html

Articles Similaires

[1] https://towardsdatascience.com/transfer-learning-946518f95666

[2] https://medium.com/@nachiket.tanksale/finding-good-learning-rate-and-the-one-cycle-policy-7159fe1db5d6

[3] https://blog.floydhub.com/ten-techniques-from-fast-ai/

Laisser un commentaire