[PYTHON] Une histoire qui a trébuché lorsque j'ai créé un bot de chat avec Transformer

introduction

C'est une histoire sur laquelle je suis tombée lorsque j'ai essayé l'apprentissage automatique pour le traitement du langage naturel pour la première fois. Notez le processus jusqu'à la production. Au moment de publier l'article, cela ne fonctionnait pas bien, donc d'un autre côté, ce ne serait qu'un enseignant. Si vous voulez savoir comment bien le faire, veuillez consulter ici.

Spécifications de l'auteur

Ce sera un article d'un tel apprenti ingénieur papier. Si vous pensez que ce n'est pas très utile, nous vous recommandons de revenir au navigateur.

Examiner l'apprentissage automatique dans la zone de traitement du langage naturel

À l'origine, je touchais à l'apprentissage automatique lui-même. Cependant, comme je n'ai aucune expérience dans le traitement du langage naturel, j'ai décidé de collecter des informations et des connaissances pour le moment.

La première chose dans laquelle j'ai sauté, c'est que le BERT de Google était incroyable. J'ai donc vérifié la structure et le mécanisme d'apprentissage, mais c'était dans un état complètement "??????".

Quoi qu'il en soit, BERT semble être incroyable. Ensuite, j'ai décidé de faire quelque chose en l'utilisant et j'ai décidé de créer un chatbot.

J'ai également envisagé d'utiliser les derniers XLNet et ALBERT. Cependant, il n'y avait rien, y compris le BERT, qui pourrait être facilement modifié pour moi-même.

En particulier, le référentiel BERT de Github, qui est officieusement fourni par Google, et la classification des phrases semblaient faciles, mais cela semblait être un obstacle de taille pour effectuer d'autres tâches qui semblaient inattendues. Par conséquent, j'ai cherché une autre mesure.

Chapitre 1 Section 2 Je ne sais pas à droite ou à gauche, mais faisons un chatbot pour le moment

Après avoir vérifié diverses choses, Personnes qui font de la traduction japonais-anglais avec Transformer et [Personnes qui créent des chatbots avec Transformer] ](Https://sekailab.com/wp/2019/03/27/transformer-general-responce-bot/).

Alors pourquoi ne pas essayer de créer un chatbot avec un transformateur? J'ai eu l'idée, alors j'ai décidé de la mettre en pratique.

Cliquez ici pour les matériaux utilisés cette fois

Préparation

Passons à la façon de le faire. Cette fois, il sera exécuté sur Google colab, il est donc supposé être au format notebook. Cliquez ici pour le code complet (https://github.com/NJIMAMTO/transformer-chat-bot/blob/master/transformer.ipynb)

D'abord à partir de l'installation du programme d'installation

!pip install keras-transformer

Ensuite, installez le morceau de phrase à utiliser comme locuteur

!pip install sentencepiece

Montez Google Drive ici (comment faire)

Ensuite, téléchargez le corpus et façonnez-le.

!git clone https://github.com/knok/make-meidai-dialogue.git

Accédez au répertoire dans lequel se trouve le référentiel.

cd "/content/drive/My Drive/Colab Notebooks/make-meidai-dialogue"

Exécutez makefile

!make all

Vous serez renvoyé au répertoire d'origine.

cd "/content/drive/My Drive/Colab Notebooks"

Le téléchargement du corpus et l'exécution de makefile généreront sequence.txt. Dans ce input:~~~~ output:~~~~ Puisque la phrase conversationnelle est écrite au format de, nous la formaterons afin qu'elle soit plus facile à utiliser à l'avenir.

input_corpus = []
output_corpus = []
for_spm_corpus = []
with open('/content/drive/My Drive/Colab Notebooks/make-meidai-dialogue/sequence.txt') as f:
  for s_line in f:

    if s_line.startswith('input: '):
      input_corpus.append(s_line[6:])
      for_spm_corpus.append(s_line[6:])

    elif s_line.startswith('output: '):
      output_corpus.append(s_line[7:])
      for_spm_corpus.append(s_line[7:])

with open('/content/drive/My Drive/Colab Notebooks/input_corpus.txt', 'w') as f:
  f.writelines(input_corpus)

with open('/content/drive/My Drive/Colab Notebooks/output_corpus.txt', 'w') as f:
  f.writelines(output_corpus)

with open('/content/drive/My Drive/Colab Notebooks/spm_corpus.txt', 'w') as f:
  f.writelines(for_spm_corpus)

Il est divisé en un texte pour l'entrée dans le transformateur et un texte pour la sortie, et un texte pour l'apprentissage avec l'entrée: et la sortie: parties supprimées pour l'apprentissage dans le morceau de phrase.

Préparation

Ensuite, utilisez le morceau de phrase pour diviser la conversation. Entraînons-nous en utilisant spm_corpus.txt.

import sentencepiece as spm

# train sentence piece
spm.SentencePieceTrainer.Train("--input=spm_corpus.txt --model_prefix=trained_model --vocab_size=8000 --bos_id=1 --eos_id=2 --pad_id=0 --unk_id=5")

Les détails sont omis car la méthode est décrite dans le référentiel officiel du morceau de phrase.

Écrivons la phrase une fois avec le morceau de phrase.

sp = spm.SentencePieceProcessor()
sp.Load("trained_model.model")

#test
print(sp.EncodeAsPieces("Oh c'est vrai"))
print(sp.EncodeAsPieces("je vois"))
print(sp.EncodeAsPieces("Alors qu'entendez-vous par là?"))
print(sp.DecodeIds([0,1,2,3,4,5]))

C'est le résultat de l'exécution.

['Oh oh', 'Telle chose', 'Hey']
['je vois', 'd'accord']
['▁', 'En d'autres termes', '、', 'Cette', 'tu', 'de', 'dire', 'Vouloir', 'C'est', 'Telle chose', 'Est-ce', '?']
、。 ⁇ 

Il s'avère qu'il est divisé comme ci-dessus.

Le contenu d'ici est une modification partielle du contenu écrit dans README.md de Keras Transformer.

Modifions maintenant le corpus dans un format adapté au rembourrage et aux transformateurs.

import numpy as np

# Generate toy data
encoder_inputs_no_padding = []
encoder_inputs, decoder_inputs, decoder_outputs = [], [], []
max_token_size = 168

with open('/content/drive/My Drive/Colab Notebooks/input_corpus.txt') as input_tokens, open('/content/drive/My Drive/Colab Notebooks/output_corpus.txt') as output_tokens:
  #Lire ligne par ligne du corpus
  input_tokens = input_tokens.readlines()
  output_tokens = output_tokens.readlines()

  for input_token, output_token in zip(input_tokens, output_tokens):
    if input_token or output_token:
      encode_tokens, decode_tokens = sp.EncodeAsPieces(input_token), sp.EncodeAsPieces(output_token)
      #Rembourrage
      encode_tokens = ['<s>'] + encode_tokens + ['</s>'] + ['<pad>'] * (max_token_size - len(encode_tokens))
      output_tokens = decode_tokens + ['</s>', '<pad>'] + ['<pad>'] * (max_token_size - len(decode_tokens))
      decode_tokens = ['<s>'] + decode_tokens + ['</s>']  + ['<pad>'] * (max_token_size - len(decode_tokens))

      
      encode_tokens = list(map(lambda x: sp.piece_to_id(x), encode_tokens))
      decode_tokens = list(map(lambda x: sp.piece_to_id(x), decode_tokens))
      output_tokens = list(map(lambda x: [sp.piece_to_id(x)], output_tokens))

      encoder_inputs_no_padding.append(input_token)
      encoder_inputs.append(encode_tokens)
      decoder_inputs.append(decode_tokens)
      decoder_outputs.append(output_tokens)
    else:
      break

#Convertir pour entrée dans le modèle d'entraînement
X = [np.asarray(encoder_inputs), np.asarray(decoder_inputs)]
Y = np.asarray(decoder_outputs)

Apprendre

Entraînons maintenant le transformateur.

from keras_transformer import get_model

# Build the model
model = get_model(
    token_num=sp.GetPieceSize(),
    embed_dim=32,
    encoder_num=2,
    decoder_num=2,
    head_num=4,
    hidden_dim=128,
    dropout_rate=0.05,
    use_same_embed=True,  # Use different embeddings for different languages
)

model.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',
)
model.summary()

# Train the model
model.fit(
    x=X,
    y=Y,
    epochs=10,
    batch_size=32,
)

C'est le résultat de l'exécution.

Epoch 1/10
33361/33361 [==============================] - 68s 2ms/step - loss: 0.2818
Epoch 2/10
33361/33361 [==============================] - 66s 2ms/step - loss: 0.2410
Epoch 3/10
33361/33361 [==============================] - 66s 2ms/step - loss: 0.2331
Epoch 4/10
33361/33361 [==============================] - 66s 2ms/step - loss: 0.2274
Epoch 5/10
33361/33361 [==============================] - 66s 2ms/step - loss: 0.2230
Epoch 6/10
33361/33361 [==============================] - 66s 2ms/step - loss: 0.2193
Epoch 7/10
33361/33361 [==============================] - 66s 2ms/step - loss: 0.2163
Epoch 8/10
33361/33361 [==============================] - 66s 2ms/step - loss: 0.2137
Epoch 9/10
33361/33361 [==============================] - 66s 2ms/step - loss: 0.2114
Epoch 10/10
33361/33361 [==============================] - 66s 2ms/step - loss: 0.2094

La perte n'a pas l'air mal.

Déduire

Faisons une inférence avec le modèle entraîné.

from keras_transformer import decode

input = "Il fait beau aujourd'hui, n'est-ce pas"
encode = sp.EncodeAsIds(input)

decoded = decode(
    model,
    encode,
    start_token=sp.bos_id(),
    end_token=sp.eos_id(),
    pad_token=sp.pad_id(),
    max_len=170
)

decoded = np.array(decoded,dtype=int)
decoded = decoded.tolist()
print(sp.decode(decoded))

C'est le résultat de l'exécution.

Hé, mais ça, ça, ça, ça, ça, ça, ça, ça, ça, ça, ça

Ça ... le résultat n'est pas du tout bon. C'est un obstacle à la communication.

Considération jusqu'à présent

Quelle était la cause de l'échec?

Etc. peut être donné en premier?

Pour améliorer les performances du modèle

J'ai donc essayé de syntoniser Optuna mais cela n'a pas fonctionné pour les raisons suivantes:

J'ai donc décidé d'essayer une autre méthode. La méthode qui a fonctionné est ici

Recommended Posts

Une histoire qui a trébuché lorsque j'ai créé un bot de chat avec Transformer
Une histoire à laquelle j'étais accro après la communication SFTP avec python
J'ai fait une loterie avec Python.
J'ai fait une minuterie pomodoro dure qui fonctionne avec CUI
J'ai créé un démon avec Python
J'ai créé un plug-in qui peut faire "Daruma-san tombé" avec Minecraft
Une histoire qui a disparu quand j'ai spécifié un chemin commençant par tilda (~) en python open
J'ai fait un package qui peut comparer des analyseurs morphologiques avec Python
Une histoire que j'ai corrigée lorsque j'ai obtenu le journal Lambda de Cloudwatch Logs
J'ai fait un shuffle qui peut être réinitialisé (inversé) avec Python
J'ai fait un programme qui calcule automatiquement le zodiaque avec tkinter
J'ai créé un chat chat bot avec Tensor2Tensor et cette fois cela a fonctionné
Histoire de trébucher sur l'installation de matplotlib
J'ai fait un compteur de caractères avec Python
Une histoire qui a trébuché sur un calcul de comparaison
J'ai fait une carte hexadécimale avec Python
J'ai fait un jeu de vie avec Numpy
J'ai fait un générateur Hanko avec GAN
J'ai fait un jeu rogue-like avec Python
J'ai fait un simple blackjack avec Python
J'ai créé un fichier de configuration avec Python
J'ai fait une application WEB avec Django
J'ai fait un simulateur de neurones avec Python
Lors de l'écriture dans un fichier csv avec python, une histoire que j'ai fait une légère erreur et n'a pas respecté la date de livraison
Une histoire qui n'a pas fonctionné lorsque j'ai essayé de me connecter avec le module de requêtes Python
J'ai créé un plug-in "EZPrinter" qui génère facilement des PDF cartographiques avec QGIS.
J'ai créé un bot Discord en Python qui se traduit quand il réagit
J'ai créé un outil qui facilite un peu la décompression avec CLI (Python3)
J'ai fait un module PyNanaco qui peut charger des crédits nanaco avec python
J'ai fait un robot de remplacement de tampon avec une ligne
J'ai fait une prévision météo de type bot avec Python.
J'ai créé une application graphique avec Python + PyQt5
Mémo qui a fait un graphique pour animer avec intrigue
J'ai essayé de créer un bloqueur de filles pourries sur Twitter avec Python ①
[Python] J'ai créé un téléchargeur Youtube avec Tkinter.
J'obtiens une UnicodeDecodeError lors de l'exécution avec mod_wsgi
J'ai fait un simple portefeuille de Bitcoin avec pycoin
J'ai créé un Bot LINE avec Serverless Framework!
J'ai fait un graphique de nombres aléatoires avec Numpy
J'ai fait un jeu de cueillette avec Python
Made Mattermost Bot avec Python (+ Flask)
Un mémo sur lequel je suis tombé par hasard en faisant une citation RT sur Twitter Bot
Une histoire qui ne s'est pas terminée par la sortie lors du tournage avec l'entrée de tuyau
〇✕ J'ai fait un jeu
[AWS] J'ai créé un BOT de rappel avec LINE WORKS
J'ai fait un Twitter BOT avec GAE (python) (avec une référence)
J'ai créé un bot de livre de compte de ménage avec LINE Bot
J'ai créé un serveur syslog prêt à l'emploi avec Play with Docker
J'ai fait un jeu d'éclairage de sapin de Noël avec Python
J'ai créé une fenêtre pour la sortie du journal avec Tkinter
J'ai créé une application de notification de nouvelles en ligne avec Python
J'ai créé une VM qui exécute OpenCV pour Python
Une histoire qui a eu du mal avec l'ensemble commun HTTP_PROXY = ~