Génération de texte Tensorflow2.0 Shakespeare fonctionne


Nous utiliserons l'ensemble de données des travaux de Shakespeare fourni par Andrej Karpathy dans "Efficacité déraisonnable des réseaux de neurones récurrents". Étant donné une séquence de caractères dans ces données ("Shakespear"), entraînez un modèle pour prédire le caractère suivant dans la séquence ("e"). En appelant à plusieurs reprises le modèle, des séquences de texte plus longues peuvent être générées.

1. Importer des données

Veuillez vous référer à la huitième partie du résumé de la méthode de chargement et de prétraitement de Tensorflow2.0 : importation de texte (pour la génération de texte).

2. Créez un modèle

Utilisez tf.keras.Sequential pour définir le modèle. Dans cet exemple, nous avons utilisé trois couches pour définir le modèle:

  • tf.keras.layers.Embedding: couche d'entrée. Un tableau de comparaison entraînable qui mappe le nombre de chaque caractère à un vecteur de dimensions embedding_dim.
  • tf.keras.layers.GRU: type de RNN dont la taille est spécifiée par units = rnn_units.
  • tf.keras.layers.Dense: couche de sortie avec sortie vocab_size.
vocab_size = len(vocab)  # 词集的长度
embedding_dim = 256  # 嵌入的维度
rnn_units = 1024  # RNN 的单元数量

def build_model(vocab_size, embedding_dim, rnn_units, batch_size):
  model = tf.keras.Sequential([
    tf.keras.layers.Embedding(vocab_size, embedding_dim,
                              batch_input_shape=[batch_size, None]),
    tf.keras.layers.GRU(rnn_units,
                        return_sequences=True,
                        stateful=True,
                        recurrent_initializer='glorot_uniform'),
    tf.keras.layers.Dense(vocab_size)
  ])
  return model
model = build_model(vocab_size=len(vocab),
  					embedding_dim=embedding_dim,
  					rnn_units=rnn_units,
  					batch_size=BATCH_SIZE)
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding (Embedding)        (64, None, 256)           16640     
_________________________________________________________________
gru (GRU)                    (64, None, 1024)          3938304   
_________________________________________________________________
dense (Dense)                (64, None, 65)            66625     
=================================================================
Total params: 4,021,569
Trainable params: 4,021,569
Non-trainable params: 0
_________________________________________________________________

Pour chaque caractère, le modèle recherche l'incorporation, exécute le GRU comme entrée pour un pas de temps et utilise la couche dense pour générer une régression logistique pour prédire la probabilité de log du caractère suivant.
Insérez la description de l'image ici

3. Formation

3.1 Compiler le modèle

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

3.2 Point de contrôle de configuration

# 检查点保存至的目录
checkpoint_dir = './training_checkpoints'

# 检查点的文件名
checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt_{epoch}")

checkpoint_callback=tf.keras.callbacks.ModelCheckpoint(
    filepath=checkpoint_prefix,
    save_weights_only=True)

3.3 Formation du modèle

history = model.fit(dataset, epochs=examples_per_epoch, callbacks=[checkpoint_callback])

4. Prévisions

Le bloc de code suivant est utilisé pour générer du texte:

  • Définissez d'abord la chaîne de départ, initialisez l'état RNN et définissez le nombre de caractères à générer.
  • Utilisez la chaîne de départ et l'état RNN pour obtenir la distribution prévue du caractère suivant.
  • Ensuite, la distribution de classification est utilisée pour calculer l'indice du caractère prédit. Utilisez ce caractère prédit comme prochaine entrée du modèle.
  • Le statut RNN retourné par le modèle est renvoyé au modèle. Maintenant, le modèle a plus de contexte à apprendre qu'un seul personnage. Après avoir prédit le caractère suivant, l'état RNN modifié est renvoyé au modèle. C'est ainsi que le modèle apprend en obtenant constamment plus de contexte des personnages prédits précédemment.
    Insérez la description de l'image ici

Comme le montre la figure ci-dessus, la fonction que nous voulons atteindre ici est de saisir un échantillon avec n caractères. Le modèle affichera un caractère après chaque caractère saisi, c'est-à-dire un total de n caractères, puis utilisera les n caractères nouvellement obtenus comme Entrez, entrez à nouveau le modèle, répétez cette étape un nombre spécifié de fois.

Étant donné que la taille du lot doit être spécifiée lors de la définition de l' état masqué GRU , seule une taille de lot fixe peut être acceptée une fois le modèle établi.

Pour exécuter le modèle avec différentes tailles de lots , nous devons reconstruire le modèle et restaurer les poids à partir du point de contrôle.

4.1 Reconstruire le modèle

tf.train.latest_checkpoint(checkpoint_dir)
model = build_model(vocab_size, embedding_dim, rnn_units, batch_size=1)

model.load_weights(tf.train.latest_checkpoint(checkpoint_dir))

model.build(tf.TensorShape([1, None]))
model.summary()
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_1 (Embedding)      (1, None, 256)            16640     
_________________________________________________________________
gru_1 (GRU)                  (1, None, 1024)           3938304   
_________________________________________________________________
dense_1 (Dense)              (1, None, 65)             66625     
=================================================================
Total params: 4,021,569
Trainable params: 4,021,569
Non-trainable params: 0
_________________________________________________________________

4.2 Générer du texte

def generate_text(model, start_string):
  # 评估步骤(用学习过的模型生成文本)

  # 要生成的字符个数
  num_generate = 1000

  # 将起始字符串转换为数字(向量化)
  input_eval = [char2idx[s] for s in start_string]
  input_eval = tf.expand_dims(input_eval, 0)

  # 空字符串用于存储结果
  text_generated = []

  # 这里批大小为 1
  model.reset_states()
  for i in range(num_generate):
      predictions = model(input_eval)
      # 删除批次的维度
      predictions = tf.squeeze(predictions, 0)

      # 用分类分布预测模型返回的字符
      predicted_id = tf.random.categorical(predictions, num_samples=1)[-1,0].numpy()

      # 把预测字符和前面的隐藏状态一起传递给模型作为下一个输入
      input_eval = tf.expand_dims([predicted_id], 0)

      text_generated.append(idx2char[predicted_id])

  return (start_string + ''.join(text_generated))

print(generate_text(model, start_string=u"ROMEO: "))

Entrez 7 caractères ici, puis la forme de chaque sortie de modèle est (1, 7, 65), nous n'avons besoin que des deux dernières dimensions (7, 65), utilisez donc la fonction tf.squeeze pour supprimer la première dimension; tf.random.categorical fonction pour déterminer l'indice correspondant à la probabilité maximale dans chaque ligne, puis ressaisissez cet indice (après avoir ajouté la première dimension) en entrée, répétez les étapes ci-dessus jusqu'à ce que les 1000 caractères spécifiés soient prédits.

Le résultat final:

ROMEO: it may be see, I say.
Elong where I have sea loved for such heart
As of all desperate in your colls?
On how much to purwed esumptrues as we,
But taker appearing our great Isabel,;
Of your brother's needs.
I cannot but one hour, by nimwo and ribs
After 't? O Pedur, break our manory,
The shadot bestering eyes write; onfility;
Indeed I am possips And feated with others and throw it?

CAPULET:
O, not the ut with mine own sort.
But, with your souls, sir, well we would he,
And videwith the sungesoy begins, revell;
Much it in secart.

PROSPERO:
Villain, I darry record;
In sea--lodies, nor that I do I were stir,
You appointed with that sed their o tailor and hope left fear'd,
I so; that your looks stand up,
Comes I truly see this last weok not the
sul us.

CAMILLO:
You did and ever sea,
Into these hours: awake! Ro with mine enemies,
Were werx'd in everlawacted man been to alter
As Lewis could smile to his.

Farthus:
Marry! I'll do lose a man see me
To no drinking often hat back on an illing mo
Publié 142 articles originaux · loué 39 · 110 000 vues

Je suppose que tu aimes

Origine blog.csdn.net/qq_36758914/article/details/105453192
conseillé
Classement