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.
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.
À 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.
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
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.
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)
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.
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.
Quelle était la cause de l'échec?
Etc. peut être donné en premier?
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