Giúp bảo vệ Great Barrier Reef với TensorFlow trên Kaggle Tham Challenge

Tạo văn bản bằng RNN

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải xuống sổ ghi chép

Hướng dẫn này trình bày cách tạo văn bản bằng RNN dựa trên ký tự. Bạn sẽ làm việc với một tập dữ liệu bằng văn bản của Shakespeare từ Andrej Karpathy của Hiệu quả không hợp lý của tái Neural Networks . Đưa ra một chuỗi ký tự từ dữ liệu này ("Shakespear"), đào tạo một mô hình để dự đoán ký tự tiếp theo trong chuỗi ("e"). Các chuỗi văn bản dài hơn có thể được tạo ra bằng cách gọi mô hình lặp đi lặp lại.

Hướng dẫn này bao gồm mã Runnable thực hiện sử dụng tf.kerasthực hiện háo hức . Sau đây là kết quả đầu ra mẫu khi mô hình trong hướng dẫn này được đào tạo trong 30 kỷ và bắt đầu bằng lời nhắc "Q":

QUEENE:
I had thought thou hadst a Roman; for the oracle,
Thus by All bids the man against the word,
Which are so weak of care, by old care done;
Your children were in your holy love,
And the precipitation through the bleeding throne.

BISHOP OF ELY:
Marry, and will, my lord, to weep in such a one were prettiest;
Yet now I was adopted heir
Of the world's lamentable day,
To watch the next way with his father with his face?

ESCALUS:
The cause why then we are all resolved more sons.

VOLUMNIA:
O, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, it is no sin it should be dead,
And love and pale as any will to that word.

QUEEN ELIZABETH:
But how long have I heard the soul for this world,
And show his hands of life be proved to stand.

PETRUCHIO:
I say he look'd on, if I must be content
To stay him from the fatal of our country's bliss.
His lordship pluck'd from this sentence then for prey,
And then let us twain, being the moon,
were she such a case as fills m

Trong khi một số câu sai ngữ pháp, hầu hết không có ý nghĩa. Mô hình chưa học nghĩa của từ, nhưng hãy xem xét:

  • Mô hình dựa trên nhân vật. Khi bắt đầu đào tạo, người mẫu không biết cách đánh vần một từ tiếng Anh, hoặc các từ đó thậm chí là một đơn vị văn bản.

  • Cấu trúc của đầu ra giống như một vở kịch — các khối văn bản thường bắt đầu bằng tên người nói, bằng tất cả các chữ cái in hoa tương tự như tập dữ liệu.

  • Như được minh họa bên dưới, mô hình được đào tạo trên các lô văn bản nhỏ (mỗi lô 100 ký tự) và vẫn có thể tạo ra một chuỗi văn bản dài hơn với cấu trúc mạch lạc.

Thành lập

Nhập TensorFlow và các thư viện khác

import tensorflow as tf

import numpy as np
import os
import time

Tải xuống bộ dữ liệu Shakespeare

Thay đổi dòng sau để chạy mã này trên dữ liệu của riêng bạn.

path_to_file = tf.keras.utils.get_file('shakespeare.txt', 'https://storage.googleapis.com/download.tensorflow.org/data/shakespeare.txt')
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/shakespeare.txt
1122304/1115394 [==============================] - 0s 0us/step
1130496/1115394 [==============================] - 0s 0us/step

Đọc dữ liệu

Đầu tiên, hãy xem văn bản:

# Read, then decode for py2 compat.
text = open(path_to_file, 'rb').read().decode(encoding='utf-8')
# length of text is the number of characters in it
print(f'Length of text: {len(text)} characters')
Length of text: 1115394 characters
# Take a look at the first 250 characters in text
print(text[:250])
First Citizen:
Before we proceed any further, hear me speak.

All:
Speak, speak.

First Citizen:
You are all resolved rather to die than to famish?

All:
Resolved. resolved.

First Citizen:
First, you know Caius Marcius is chief enemy to the people.
# The unique characters in the file
vocab = sorted(set(text))
print(f'{len(vocab)} unique characters')
65 unique characters

Xử lý văn bản

Vectơ hóa văn bản

Trước khi đào tạo, bạn cần chuyển đổi các chuỗi thành một biểu diễn số.

Các tf.keras.layers.StringLookup lớp có thể chuyển đổi từng nhân vật vào một ID số. Nó chỉ cần văn bản được chia thành các mã thông báo trước.

example_texts = ['abcdefg', 'xyz']

chars = tf.strings.unicode_split(example_texts, input_encoding='UTF-8')
chars
<tf.RaggedTensor [[b'a', b'b', b'c', b'd', b'e', b'f', b'g'], [b'x', b'y', b'z']]>

Bây giờ tạo ra tf.keras.layers.StringLookup lớp:

ids_from_chars = tf.keras.layers.StringLookup(
    vocabulary=list(vocab), mask_token=None)

Nó chuyển đổi từ mã thông báo thành ID ký tự:

ids = ids_from_chars(chars)
ids
<tf.RaggedTensor [[40, 41, 42, 43, 44, 45, 46], [63, 64, 65]]>

Vì mục tiêu của hướng dẫn này là tạo văn bản, điều quan trọng là phải đảo ngược biểu diễn này và khôi phục các chuỗi mà con người có thể đọc được từ nó. Đối với điều này bạn có thể sử dụng tf.keras.layers.StringLookup(..., invert=True) .

chars_from_ids = tf.keras.layers.StringLookup(
    vocabulary=ids_from_chars.get_vocabulary(), invert=True, mask_token=None)

Lớp này phục hồi các nhân vật từ các vectơ của các ID, và trả về chúng như là một tf.RaggedTensor ký tự:

chars = chars_from_ids(ids)
chars
<tf.RaggedTensor [[b'a', b'b', b'c', b'd', b'e', b'f', b'g'], [b'x', b'y', b'z']]>

Bạn có thể tf.strings.reduce_join tham gia các nhân vật trở thành chuỗi.

tf.strings.reduce_join(chars, axis=-1).numpy()
array([b'abcdefg', b'xyz'], dtype=object)
def text_from_ids(ids):
  return tf.strings.reduce_join(chars_from_ids(ids), axis=-1)

Nhiệm vụ dự đoán

Cho một ký tự hoặc một chuỗi ký tự, ký tự tiếp theo có thể xảy ra nhất là gì? Đây là nhiệm vụ bạn đang đào tạo người mẫu để thực hiện. Đầu vào cho mô hình sẽ là một chuỗi các ký tự và bạn huấn luyện mô hình để dự đoán đầu ra — ký tự sau tại mỗi bước thời gian.

Vì các RNN duy trì trạng thái bên trong phụ thuộc vào các phần tử đã nhìn thấy trước đó, với tất cả các ký tự được tính cho đến thời điểm này, ký tự tiếp theo là gì?

Tạo các ví dụ và mục tiêu đào tạo

Tiếp theo chia văn bản thành các chuỗi ví dụ. Mỗi chuỗi đầu vào sẽ chứa seq_length nhân vật trong văn bản.

Đối với mỗi chuỗi đầu vào, các mục tiêu tương ứng chứa cùng độ dài văn bản, ngoại trừ việc dịch chuyển một ký tự sang bên phải.

Vì vậy, phá vỡ văn bản vào khối của seq_length+1 . Ví dụ, nói seq_length là 4 và văn bản của chúng tôi là "Hello". Chuỗi đầu vào sẽ là "Địa ngục" và chuỗi mục tiêu "ello".

Để làm được sử dụng đầu tiên này tf.data.Dataset.from_tensor_slices chức năng để chuyển đổi các vector văn bản vào một dòng chỉ số nhân vật.

all_ids = ids_from_chars(tf.strings.unicode_split(text, 'UTF-8'))
all_ids
<tf.Tensor: shape=(1115394,), dtype=int64, numpy=array([19, 48, 57, ..., 46,  9,  1])>
ids_dataset = tf.data.Dataset.from_tensor_slices(all_ids)
for ids in ids_dataset.take(10):
    print(chars_from_ids(ids).numpy().decode('utf-8'))
F
i
r
s
t
 
C
i
t
i
seq_length = 100
examples_per_epoch = len(text)//(seq_length+1)

Các batch phương pháp cho phép bạn dễ dàng chuyển đổi các đặc điểm cá nhân để trình tự của kích thước mong muốn.

sequences = ids_dataset.batch(seq_length+1, drop_remainder=True)

for seq in sequences.take(1):
  print(chars_from_ids(seq))
tf.Tensor(
[b'F' b'i' b'r' b's' b't' b' ' b'C' b'i' b't' b'i' b'z' b'e' b'n' b':'
 b'\n' b'B' b'e' b'f' b'o' b'r' b'e' b' ' b'w' b'e' b' ' b'p' b'r' b'o'
 b'c' b'e' b'e' b'd' b' ' b'a' b'n' b'y' b' ' b'f' b'u' b'r' b't' b'h'
 b'e' b'r' b',' b' ' b'h' b'e' b'a' b'r' b' ' b'm' b'e' b' ' b's' b'p'
 b'e' b'a' b'k' b'.' b'\n' b'\n' b'A' b'l' b'l' b':' b'\n' b'S' b'p' b'e'
 b'a' b'k' b',' b' ' b's' b'p' b'e' b'a' b'k' b'.' b'\n' b'\n' b'F' b'i'
 b'r' b's' b't' b' ' b'C' b'i' b't' b'i' b'z' b'e' b'n' b':' b'\n' b'Y'
 b'o' b'u' b' '], shape=(101,), dtype=string)
2022-01-14 12:12:45.336250: W tensorflow/core/data/root_dataset.cc:200] Optimization loop failed: CANCELLED: Operation was cancelled

Sẽ dễ dàng hơn để xem điều này đang làm gì nếu bạn nối các mã thông báo trở lại thành chuỗi:

for seq in sequences.take(5):
  print(text_from_ids(seq).numpy())
b'First Citizen:\nBefore we proceed any further, hear me speak.\n\nAll:\nSpeak, speak.\n\nFirst Citizen:\nYou '
b'are all resolved rather to die than to famish?\n\nAll:\nResolved. resolved.\n\nFirst Citizen:\nFirst, you k'
b"now Caius Marcius is chief enemy to the people.\n\nAll:\nWe know't, we know't.\n\nFirst Citizen:\nLet us ki"
b"ll him, and we'll have corn at our own price.\nIs't a verdict?\n\nAll:\nNo more talking on't; let it be d"
b'one: away, away!\n\nSecond Citizen:\nOne word, good citizens.\n\nFirst Citizen:\nWe are accounted poor citi'

Đối với đào tạo bạn sẽ cần một bộ dữ liệu của (input, label) cặp. Trong trường hợp inputlabel là chuỗi. Tại mỗi bước, đầu vào là ký tự hiện tại và nhãn là ký tự tiếp theo.

Đây là một hàm nhận một chuỗi làm đầu vào, sao chép và dịch chuyển nó để căn chỉnh đầu vào và nhãn cho mỗi bước thời gian:

def split_input_target(sequence):
    input_text = sequence[:-1]
    target_text = sequence[1:]
    return input_text, target_text
split_input_target(list("Tensorflow"))
(['T', 'e', 'n', 's', 'o', 'r', 'f', 'l', 'o'],
 ['e', 'n', 's', 'o', 'r', 'f', 'l', 'o', 'w'])
dataset = sequences.map(split_input_target)
for input_example, target_example in dataset.take(1):
    print("Input :", text_from_ids(input_example).numpy())
    print("Target:", text_from_ids(target_example).numpy())
Input : b'First Citizen:\nBefore we proceed any further, hear me speak.\n\nAll:\nSpeak, speak.\n\nFirst Citizen:\nYou'
Target: b'irst Citizen:\nBefore we proceed any further, hear me speak.\n\nAll:\nSpeak, speak.\n\nFirst Citizen:\nYou '

Tạo các lô đào tạo

Bạn sử dụng tf.data để phân chia các văn bản vào trình tự quản lý được. Nhưng trước khi đưa dữ liệu này vào mô hình, bạn cần xáo trộn dữ liệu và đóng gói thành lô.

# Batch size
BATCH_SIZE = 64

# Buffer size to shuffle the dataset
# (TF data is designed to work with possibly infinite sequences,
# so it doesn't attempt to shuffle the entire sequence in memory. Instead,
# it maintains a buffer in which it shuffles elements).
BUFFER_SIZE = 10000

dataset = (
    dataset
    .shuffle(BUFFER_SIZE)
    .batch(BATCH_SIZE, drop_remainder=True)
    .prefetch(tf.data.experimental.AUTOTUNE))

dataset
<PrefetchDataset element_spec=(TensorSpec(shape=(64, 100), dtype=tf.int64, name=None), TensorSpec(shape=(64, 100), dtype=tf.int64, name=None))>

Xây dựng mô hình

Phần này định nghĩa các mô hình như một keras.Model lớp con (Chi tiết xem Làm lớp mới và mô hình qua subclassing ).

Mô hình này có ba lớp:

  • tf.keras.layers.Embedding : Lớp đầu vào. Một bảng tra cứu khả năng huấn luyện đó sẽ vạch từng nhân vật-ID để một vector với embedding_dim kích thước;
  • tf.keras.layers.GRU : Một loại RNN với kích thước units=rnn_units (Bạn cũng có thể sử dụng một lớp LSTM ở đây.)
  • tf.keras.layers.Dense : Lớp đầu ra, với vocab_size đầu ra. Nó xuất ra một logit cho mỗi ký tự trong từ vựng. Đây là khả năng ghi nhật ký của từng ký tự theo mô hình.
# Length of the vocabulary in chars
vocab_size = len(vocab)

# The embedding dimension
embedding_dim = 256

# Number of RNN units
rnn_units = 1024
class MyModel(tf.keras.Model):
  def __init__(self, vocab_size, embedding_dim, rnn_units):
    super().__init__(self)
    self.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim)
    self.gru = tf.keras.layers.GRU(rnn_units,
                                   return_sequences=True,
                                   return_state=True)
    self.dense = tf.keras.layers.Dense(vocab_size)

  def call(self, inputs, states=None, return_state=False, training=False):
    x = inputs
    x = self.embedding(x, training=training)
    if states is None:
      states = self.gru.get_initial_state(x)
    x, states = self.gru(x, initial_state=states, training=training)
    x = self.dense(x, training=training)

    if return_state:
      return x, states
    else:
      return x
model = MyModel(
    # Be sure the vocabulary size matches the `StringLookup` layers.
    vocab_size=len(ids_from_chars.get_vocabulary()),
    embedding_dim=embedding_dim,
    rnn_units=rnn_units)

Đối với mỗi ký tự, mô hình tìm kiếm việc nhúng, chạy GRU một bước thời gian với nhúng làm đầu vào và áp dụng lớp dày đặc để tạo nhật ký dự đoán khả năng xuất hiện nhật ký của ký tự tiếp theo:

Bản vẽ dữ liệu đi qua mô hình

Thử mô hình

Bây giờ hãy chạy mô hình để thấy rằng nó hoạt động như mong đợi.

Đầu tiên hãy kiểm tra hình dạng của đầu ra:

for input_example_batch, target_example_batch in dataset.take(1):
    example_batch_predictions = model(input_example_batch)
    print(example_batch_predictions.shape, "# (batch_size, sequence_length, vocab_size)")
(64, 100, 66) # (batch_size, sequence_length, vocab_size)

Trong ví dụ trên chiều dài chuỗi các đầu vào là 100 nhưng mô hình có thể chạy trên đầu vào của bất kỳ chiều dài:

model.summary()
Model: "my_model"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 embedding (Embedding)       multiple                  16896     
                                                                 
 gru (GRU)                   multiple                  3938304   
                                                                 
 dense (Dense)               multiple                  67650     
                                                                 
=================================================================
Total params: 4,022,850
Trainable params: 4,022,850
Non-trainable params: 0
_________________________________________________________________

Để nhận các dự đoán thực tế từ mô hình, bạn cần lấy mẫu từ phân phối đầu ra, để có được các chỉ số ký tự thực tế. Sự phân bố này được xác định bởi logits trên từ vựng ký tự.

Hãy thử nó cho ví dụ đầu tiên trong lô:

sampled_indices = tf.random.categorical(example_batch_predictions[0], num_samples=1)
sampled_indices = tf.squeeze(sampled_indices, axis=-1).numpy()

Điều này cung cấp cho chúng tôi, tại mỗi bước thời gian, dự đoán về chỉ số ký tự tiếp theo:

sampled_indices
array([ 3, 64, 58, 50, 52, 54,  5, 65, 44, 52, 11, 17, 16, 22, 62, 14, 19,
       26, 63,  2, 39, 19, 21, 14, 39, 46, 26, 53,  4, 16, 49, 43, 15, 53,
       31, 45,  2,  9, 43, 53,  6,  0, 43, 30, 24,  2, 35, 22, 23,  3, 17,
       15, 10, 30, 42, 48, 22,  1, 27, 52, 36, 51, 51, 43, 65, 39, 43, 38,
       39,  0,  2, 56, 49, 48, 31, 42, 51, 48,  7, 24, 33, 56, 58, 31, 51,
       61, 59, 61,  3, 65, 44, 14, 34, 30, 44, 27, 47, 18, 42, 15])

Giải mã những thứ này để xem văn bản được dự đoán bởi mô hình chưa được đào tạo này:

print("Input:\n", text_from_ids(input_example_batch[0]).numpy())
print()
print("Next Char Predictions:\n", text_from_ids(sampled_indices).numpy())
Input:
 b'genet.\nEdward for Edward pays a dying debt.\n\nQUEEN ELIZABETH:\nWilt thou, O God, fly from such gentle'

Next Char Predictions:
 b"!yskmo&zem:DCIwAFMx ZFHAZgMn$CjdBnRf .dn'[UNK]dQK VIJ!DB3QciI\nNmWlldzZdYZ[UNK] qjiRcli,KTqsRlvtv!zeAUQeNhEcB"

Đào tạo mô hình

Tại thời điểm này, vấn đề có thể được coi là một vấn đề phân loại tiêu chuẩn. Với trạng thái RNN trước đó và đầu vào ở bước thời gian này, hãy dự đoán lớp của ký tự tiếp theo.

Đính kèm một trình tối ưu hóa và một hàm mất mát

Các tiêu chuẩn tf.keras.losses.sparse_categorical_crossentropy chức năng mất việc trong trường hợp này bởi vì nó được áp dụng trên kích thước cuối cùng của dự đoán.

Bởi vì mô hình của bạn trả về logits, bạn cần phải thiết lập các from_logits cờ.

loss = tf.losses.SparseCategoricalCrossentropy(from_logits=True)
example_batch_loss = loss(target_example_batch, example_batch_predictions)
mean_loss = example_batch_loss.numpy().mean()
print("Prediction shape: ", example_batch_predictions.shape, " # (batch_size, sequence_length, vocab_size)")
print("Mean loss:        ", mean_loss)
Prediction shape:  (64, 100, 66)  # (batch_size, sequence_length, vocab_size)
Mean loss:         4.1900826

Một mô hình mới được khởi tạo không nên quá chắc chắn về chính nó, các bản ghi đầu ra đều phải có độ lớn tương tự nhau. Để xác nhận điều này, bạn có thể kiểm tra xem số mũ của tổn thất trung bình có xấp xỉ bằng kích thước từ vựng hay không. Mức lỗ cao hơn nhiều có nghĩa là mô hình chắc chắn về các câu trả lời sai của nó và được khởi tạo không tốt:

tf.exp(mean_loss).numpy()
66.028244

Cấu hình các thủ tục đào tạo bằng cách sử dụng tf.keras.Model.compile phương pháp. Sử dụng tf.keras.optimizers.Adam với đối số mặc định và hàm tổn thất.

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

Định cấu hình các điểm kiểm tra

Sử dụng một tf.keras.callbacks.ModelCheckpoint để đảm bảo rằng các điểm kiểm tra được lưu trong đào tạo:

# Directory where the checkpoints will be saved
checkpoint_dir = './training_checkpoints'
# Name of the checkpoint files
checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt_{epoch}")

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

Thực hiện đào tạo

Để giữ thời gian huấn luyện hợp lý, hãy sử dụng 10 kỷ nguyên để huấn luyện mô hình. Trong Colab, hãy đặt thời gian chạy thành GPU để đào tạo nhanh hơn.

EPOCHS = 20
history = model.fit(dataset, epochs=EPOCHS, callbacks=[checkpoint_callback])
Epoch 1/20
172/172 [==============================] - 7s 25ms/step - loss: 2.7056
Epoch 2/20
172/172 [==============================] - 5s 24ms/step - loss: 1.9838
Epoch 3/20
172/172 [==============================] - 5s 24ms/step - loss: 1.7074
Epoch 4/20
172/172 [==============================] - 5s 24ms/step - loss: 1.5489
Epoch 5/20
172/172 [==============================] - 5s 24ms/step - loss: 1.4498
Epoch 6/20
172/172 [==============================] - 5s 24ms/step - loss: 1.3825
Epoch 7/20
172/172 [==============================] - 5s 24ms/step - loss: 1.3300
Epoch 8/20
172/172 [==============================] - 5s 24ms/step - loss: 1.2846
Epoch 9/20
172/172 [==============================] - 5s 24ms/step - loss: 1.2441
Epoch 10/20
172/172 [==============================] - 5s 24ms/step - loss: 1.2030
Epoch 11/20
172/172 [==============================] - 5s 24ms/step - loss: 1.1641
Epoch 12/20
172/172 [==============================] - 5s 24ms/step - loss: 1.1223
Epoch 13/20
172/172 [==============================] - 6s 24ms/step - loss: 1.0786
Epoch 14/20
172/172 [==============================] - 5s 24ms/step - loss: 1.0316
Epoch 15/20
172/172 [==============================] - 6s 24ms/step - loss: 0.9826
Epoch 16/20
172/172 [==============================] - 5s 24ms/step - loss: 0.9326
Epoch 17/20
172/172 [==============================] - 5s 24ms/step - loss: 0.8790
Epoch 18/20
172/172 [==============================] - 5s 24ms/step - loss: 0.8260
Epoch 19/20
172/172 [==============================] - 5s 24ms/step - loss: 0.7759
Epoch 20/20
172/172 [==============================] - 5s 24ms/step - loss: 0.7256

Tạo văn bản

Cách đơn giản nhất để tạo văn bản với mô hình này là chạy nó trong một vòng lặp và theo dõi trạng thái bên trong của mô hình khi bạn thực thi nó.

Để tạo văn bản, đầu ra của mô hình được đưa trở lại đầu vào

Mỗi lần bạn gọi mô hình, bạn chuyển một số văn bản và trạng thái bên trong. Mô hình trả về một dự đoán cho ký tự tiếp theo và trạng thái mới của nó. Chuyển dự đoán và trạng thái trở lại để tiếp tục tạo văn bản.

Sau đây là một dự đoán bước duy nhất:

class OneStep(tf.keras.Model):
  def __init__(self, model, chars_from_ids, ids_from_chars, temperature=1.0):
    super().__init__()
    self.temperature = temperature
    self.model = model
    self.chars_from_ids = chars_from_ids
    self.ids_from_chars = ids_from_chars

    # Create a mask to prevent "[UNK]" from being generated.
    skip_ids = self.ids_from_chars(['[UNK]'])[:, None]
    sparse_mask = tf.SparseTensor(
        # Put a -inf at each bad index.
        values=[-float('inf')]*len(skip_ids),
        indices=skip_ids,
        # Match the shape to the vocabulary
        dense_shape=[len(ids_from_chars.get_vocabulary())])
    self.prediction_mask = tf.sparse.to_dense(sparse_mask)

  @tf.function
  def generate_one_step(self, inputs, states=None):
    # Convert strings to token IDs.
    input_chars = tf.strings.unicode_split(inputs, 'UTF-8')
    input_ids = self.ids_from_chars(input_chars).to_tensor()

    # Run the model.
    # predicted_logits.shape is [batch, char, next_char_logits]
    predicted_logits, states = self.model(inputs=input_ids, states=states,
                                          return_state=True)
    # Only use the last prediction.
    predicted_logits = predicted_logits[:, -1, :]
    predicted_logits = predicted_logits/self.temperature
    # Apply the prediction mask: prevent "[UNK]" from being generated.
    predicted_logits = predicted_logits + self.prediction_mask

    # Sample the output logits to generate token IDs.
    predicted_ids = tf.random.categorical(predicted_logits, num_samples=1)
    predicted_ids = tf.squeeze(predicted_ids, axis=-1)

    # Convert from token ids to characters
    predicted_chars = self.chars_from_ids(predicted_ids)

    # Return the characters and model state.
    return predicted_chars, states
one_step_model = OneStep(model, chars_from_ids, ids_from_chars)

Chạy nó trong một vòng lặp để tạo ra một số văn bản. Nhìn vào văn bản đã tạo, bạn sẽ thấy mô hình biết khi nào nên viết hoa, tạo đoạn văn và bắt chước từ vựng viết giống như Shakespeare. Với thời lượng luyện tập ít nên chưa học được cách tạo câu mạch lạc.

start = time.time()
states = None
next_char = tf.constant(['ROMEO:'])
result = [next_char]

for n in range(1000):
  next_char, states = one_step_model.generate_one_step(next_char, states=states)
  result.append(next_char)

result = tf.strings.join(result)
end = time.time()
print(result[0].numpy().decode('utf-8'), '\n\n' + '_'*80)
print('\nRun time:', end - start)
ROMEO:
But I do lose his land, and get a summer ruin.

SICINIUS:
That's your beave.

BIONDELLO:
Ha? Rucher that dost thou art again to provide,
In thy right injurious princely number.
Dear resembrance at this Antium, York as a man
That 'leven your steel pedlars mounted.
Sad, he hath privilege with the causer.

NORTHUMBERLAND:
The lords o'clock my sovereign slay;
You say do so young master. Come, let's go
Avoid with brittle fifteen years; therefore I wail, for he
is your before, sir, I will deep thing and rich my steal father.
Then, till he be that must be done: Henry, such a peast,
Our doings were free,' quoth he that Clifford say so himself.
If I be here to make thee jardon, 'milis,
And cannot but better wed this withded; but,
I'll pawn the platts, to France Henry's forward come?

BENVOLIO:
Twice one defend,
Or wail not be; this last of endless creatures
We may title out above to due, a feast.

Tailor:
Such a more mortal to your death
Taking this forward injury, that did, but hears
Bearing  

________________________________________________________________________________

Run time: 2.630192518234253

Điều đơn giản nhất bạn có thể làm để cải thiện kết quả là đào tạo nó lâu hơn (thử EPOCHS = 30 ).

Bạn cũng có thể thử nghiệm với một chuỗi bắt đầu khác, thử thêm một lớp RNN khác để cải thiện độ chính xác của mô hình hoặc điều chỉnh thông số nhiệt độ để tạo ra nhiều hơn hoặc ít hơn các dự đoán ngẫu nhiên.

Nếu bạn muốn mô hình để tạo văn bản nhanh hơn là điều dễ nhất bạn có thể làm là hàng loạt các thế hệ văn bản. Trong ví dụ dưới đây, mô hình tạo ra 5 đầu ra trong cùng khoảng thời gian cần thiết để tạo ra 1 ở trên.

start = time.time()
states = None
next_char = tf.constant(['ROMEO:', 'ROMEO:', 'ROMEO:', 'ROMEO:', 'ROMEO:'])
result = [next_char]

for n in range(1000):
  next_char, states = one_step_model.generate_one_step(next_char, states=states)
  result.append(next_char)

result = tf.strings.join(result)
end = time.time()
print(result, '\n\n' + '_'*80)
print('\nRun time:', end - start)
tf.Tensor(
[b"ROMEO:\nThe Duke of Norfolk, when ang low-hingded is a\ndangerous tongue; thou hast never in our tale\n'side, and talk of wine and me. Leave me, and\nI wish thy breathing: he hath had no poison\nMust call Edward's faces, and that sends the roan drowning tears.\nThe sum our lovers bride, or bid me speak.\n\nBUCKINGHAM:\nWelcome, great bring our contents.\n\nCAMILLO:\nThe kings of Coriolanus!\n\nVOLUMNIA:\nAnd, by a dish, sort words in person.\n\nBRUTUS:\nGo ask.\n\nMARIANA:\nThen with a grains what thine eyes say\nWill you done free speech lies?\n\nLADY CAPULET:\nI know not what to be proud?\nFow, I do bit speak a worthy feast; but tweit me\nForbid-hearken more deeds do that presently to't in no\nmore mad off, what a subjected\nregion and the devil serve my name world's dead,\nAnd till the portier rare my brows, not with this fable,\nnurse, for he is come to swear and spee himself and France:\nClarence hath all postery of the marriage\nBoth have but a rather.\n\nDUKE VINCENTIO:\nYou have lats in the charm? the two brittle gale\n"
 b"ROMEO:\nThey are but foolish tox, that you rogues!\n\nARCHIDAMUS:\nWell, why lie yon ege you for that name; for forward of the father\nWoeed out me in the invited suffer: if\nThe Volsces have by me with twenty thousand men?\nBut he, my lord, with honourable forfeit,\nWhich ebbles your partiest, will do you\nTo make the measure of a weal Lord Hastings;\nI will not judger in Bohemia.\n\nCOMINIUS:\nGo, be gone, let's he for her success.\n\nMIRANDA:\nYou have told something only poored?\nWhere then Ramentione hath wrong'd himself.\n\nKING RICHARD III:\nHe was not may be, do not bellay. Here comest thou not:\nWhat a medler sticks your daughter and my slave,\nAs if thy words may talk for love, thy knee\nCitsand in't, for fair lady's husband,\nTo entail yield Lohe Becomes your bosom's side;\ncannot hold out alone. Farewell: my swift is several tone,\nThat rests more cause to go walk by to her hearing a trabe,\nOr ever eished him that walk'd you, whiles he yields\nSmiles as easy ansien and be true.\n\nDUCHESS OF YORK:\nAll men, I"
 b"ROMEO:\nBut rather we have eved the ground\nbelieve thee, horse! what has left in the city butchers.\n\nDUKE VINCENTIO:\nA goddess helprous Derby, and yet no parley, complet\nThe valiant part Campish. Tell me, mark I commine\nYour changet over-little.\n\nPOMPEY:\nI would fail sir, and here I leave you, sir.\n\nVINCENTIO:\nLet a mark to-morrow to be ta'en true; be gone.\n\nShepherd:\nNo, he doth no daughter to part.\n\nPAULINA:\nWhere is my lord Ged breed!\nO go, no visage, and fear:\nYou are school'd, methinks, and finds enough.\nWhat, are you heep? when valiant Bilond, owe hour,\nSince presently the lording jewels each part\nThe honour's emilia. A scurcely, which are\nthey are, which Hasby Buckingham deposed?\n\nRome:\nAy, to thy child is frame of death,\nBut death to part of satisffiting.\n\nNORTHUMBERLAND:\nNay, but sad, I'ld not be so troop;\nShow me them speak. This way, let's hand thy pride.\n\nHENRY BOLINGBROKE:\nHe did, my ladying and dig friend,\nNor to thy heart were god, that I have seen in\ntwenty humours live. For j"
 b"ROMEO:\nThe mayor alieas! no senses of spleen,\nWhile I am come to Padua and gallows Claudio; we is there\nA shimble witness to this father's death\n'seep lusty to Covents, alive,\nSend by the father bear themselves; for I am law,\nAnd there not mine is no other beauteous days!\n\nJOHN OF GAUNT:\nO, but O, the account I would content\na boain-to bed; there as good news will it purge;\nFor then the unstable's accept of teet, and aged\nThan one but follow'd that he did the house\nto make a papse tread on to dispatch his power to bid\nOf the tribunes of ut my sweet revolting.\n\nVOLUMNIA:\nMy husband come I heard you as from an\nangry and a father before him\nTo be so boundly, as affairs\nShall rest by back from grief and fortune shall be talk.\n\nGLOUCESTER:\nLook, horse! Viseria feet us on the child,\nVerily, and tell him heap of brief.\nFor I woo'll so it is.\n\nPOMPEY:\nBut can you not forgot your hends are pack'd?\n\nBIONDELLO:\nO, what a spenat lay be born ta'll fim,\nHave a burthen and a second Kate of France,\nAnd call"
 b"ROMEO:\nBut I do defend my lotgern any in the county.\n\nJULIET:\nI would the duke way dog! This vullain and all his\nfriends, nature bids thy pinish whom, by, boshing rewards.\nCome, my Lord Northumberland.\n\nPRINCE EDWARD:\nWatch this follows many more than this! O ho!\n\nNORFOLK:\nSpurs, praise I seal of trial. Hadst thou wilt amender:\nGood Poase and thy voice indeeds as year.\n\nKING RICHARD III:\nAnd do, my lord. Lord Angelo, have I pronound\nMy swinter saust and jegla.\n\nPRINCE:\nLet's fit how thy peace hath been bring me to my life.\nBut now I am a lover and that grace to her tears.\nAh, for like deep dead, and I then live.\nAlack, he'll prove you the king's side,\nI poison, think you, on what a fed afford a hearted faults\nAs I else hand of secret.\n\nLODSE:\nStopp'd in such a slanderous coward!\n\nDUCHESS OF YORK:\nGive me my boon, I'll rust, but that I did for the\nnoble priest let mall in Coriol whipping news,\nSwarn hurts in every purged further;\nLooks wink,--for shame, this lark doth among these wars,\nHis ac"], shape=(5,), dtype=string) 

________________________________________________________________________________

Run time: 2.452502489089966

Xuất trình tạo

Mô hình đơn bước này có thể dễ dàng lưu và phục hồi , cho phép bạn sử dụng nó ở bất cứ đâu một tf.saved_model được chấp nhận.

tf.saved_model.save(one_step_model, 'one_step')
one_step_reloaded = tf.saved_model.load('one_step')
WARNING:tensorflow:Skipping full serialization of Keras layer <__main__.OneStep object at 0x7f2dec122490>, because it is not built.
2022-01-14 12:14:46.156693: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
WARNING:absl:Found untraced functions such as gru_cell_layer_call_fn, gru_cell_layer_call_and_return_conditional_losses while saving (showing 2 of 2). These functions will not be directly callable after loading.
INFO:tensorflow:Assets written to: one_step/assets
INFO:tensorflow:Assets written to: one_step/assets
states = None
next_char = tf.constant(['ROMEO:'])
result = [next_char]

for n in range(100):
  next_char, states = one_step_reloaded.generate_one_step(next_char, states=states)
  result.append(next_char)

print(tf.strings.join(result)[0].numpy().decode("utf-8"))
ROMEO:
Why dost thou dissemble.

BRUTUS:
But, O, prite, hath becall'd it;
And so, have patience:
'Tis like

Nâng cao: Đào tạo tùy chỉnh

Quy trình đào tạo ở trên rất đơn giản, nhưng không giúp bạn kiểm soát nhiều. Nó sử dụng tính năng ép buộc của giáo viên để ngăn chặn các dự đoán xấu được đưa trở lại mô hình, vì vậy mô hình không bao giờ học cách phục hồi sau những sai lầm.

Vì vậy, bây giờ bạn đã thấy cách chạy mô hình theo cách thủ công, tiếp theo, bạn sẽ triển khai vòng lặp đào tạo. Điều này cho phép một điểm bắt đầu nếu, ví dụ, bạn muốn thực hiện chương trình giảng dạy học tập để giúp ổn định đầu ra vòng hở của mô hình.

Phần quan trọng nhất của vòng lặp huấn luyện tùy chỉnh là chức năng bước huấn luyện.

Sử dụng tf.GradientTape để theo dõi các gradient. Bạn có thể tìm hiểu thêm về phương pháp này bằng cách đọc các hướng dẫn thực hiện háo hức .

Thủ tục cơ bản là:

  1. Thực hiện mô hình và tính toán sự mất mát dưới một tf.GradientTape .
  2. Tính toán các bản cập nhật và áp dụng chúng cho mô hình bằng trình tối ưu hóa.
class CustomTraining(MyModel):
  @tf.function
  def train_step(self, inputs):
      inputs, labels = inputs
      with tf.GradientTape() as tape:
          predictions = self(inputs, training=True)
          loss = self.loss(labels, predictions)
      grads = tape.gradient(loss, model.trainable_variables)
      self.optimizer.apply_gradients(zip(grads, model.trainable_variables))

      return {'loss': loss}

Việc thực hiện trên của train_step phương pháp sau Keras' train_step ước . Đây là tùy chọn, nhưng nó cho phép bạn thay đổi hành vi của bước đào tạo và vẫn sử dụng keras' Model.compileModel.fit phương pháp.

model = CustomTraining(
    vocab_size=len(ids_from_chars.get_vocabulary()),
    embedding_dim=embedding_dim,
    rnn_units=rnn_units)
model.compile(optimizer = tf.keras.optimizers.Adam(),
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True))
model.fit(dataset, epochs=1)
172/172 [==============================] - 7s 24ms/step - loss: 2.6896
<keras.callbacks.History at 0x7f2d98313ed0>

Hoặc nếu bạn cần kiểm soát nhiều hơn, bạn có thể viết vòng lặp đào tạo tùy chỉnh hoàn chỉnh của riêng mình:

EPOCHS = 10

mean = tf.metrics.Mean()

for epoch in range(EPOCHS):
    start = time.time()

    mean.reset_states()
    for (batch_n, (inp, target)) in enumerate(dataset):
        logs = model.train_step([inp, target])
        mean.update_state(logs['loss'])

        if batch_n % 50 == 0:
            template = f"Epoch {epoch+1} Batch {batch_n} Loss {logs['loss']:.4f}"
            print(template)

    # saving (checkpoint) the model every 5 epochs
    if (epoch + 1) % 5 == 0:
        model.save_weights(checkpoint_prefix.format(epoch=epoch))

    print()
    print(f'Epoch {epoch+1} Loss: {mean.result().numpy():.4f}')
    print(f'Time taken for 1 epoch {time.time() - start:.2f} sec')
    print("_"*80)

model.save_weights(checkpoint_prefix.format(epoch=epoch))
Epoch 1 Batch 0 Loss 2.1657
Epoch 1 Batch 50 Loss 2.0466
Epoch 1 Batch 100 Loss 1.9395
Epoch 1 Batch 150 Loss 1.8729

Epoch 1 Loss: 1.9635
Time taken for 1 epoch 6.03 sec
________________________________________________________________________________
Epoch 2 Batch 0 Loss 1.7759
Epoch 2 Batch 50 Loss 1.7126
Epoch 2 Batch 100 Loss 1.6657
Epoch 2 Batch 150 Loss 1.6516

Epoch 2 Loss: 1.6907
Time taken for 1 epoch 5.30 sec
________________________________________________________________________________
Epoch 3 Batch 0 Loss 1.5436
Epoch 3 Batch 50 Loss 1.5582
Epoch 3 Batch 100 Loss 1.5763
Epoch 3 Batch 150 Loss 1.5273

Epoch 3 Loss: 1.5359
Time taken for 1 epoch 5.21 sec
________________________________________________________________________________
Epoch 4 Batch 0 Loss 1.4566
Epoch 4 Batch 50 Loss 1.4341
Epoch 4 Batch 100 Loss 1.4065
Epoch 4 Batch 150 Loss 1.4215

Epoch 4 Loss: 1.4411
Time taken for 1 epoch 5.17 sec
________________________________________________________________________________
Epoch 5 Batch 0 Loss 1.3676
Epoch 5 Batch 50 Loss 1.3668
Epoch 5 Batch 100 Loss 1.3656
Epoch 5 Batch 150 Loss 1.3548

Epoch 5 Loss: 1.3761
Time taken for 1 epoch 5.42 sec
________________________________________________________________________________
Epoch 6 Batch 0 Loss 1.2972
Epoch 6 Batch 50 Loss 1.3501
Epoch 6 Batch 100 Loss 1.3261
Epoch 6 Batch 150 Loss 1.3215

Epoch 6 Loss: 1.3257
Time taken for 1 epoch 5.31 sec
________________________________________________________________________________
Epoch 7 Batch 0 Loss 1.2677
Epoch 7 Batch 50 Loss 1.2358
Epoch 7 Batch 100 Loss 1.2528
Epoch 7 Batch 150 Loss 1.2749

Epoch 7 Loss: 1.2818
Time taken for 1 epoch 5.46 sec
________________________________________________________________________________
Epoch 8 Batch 0 Loss 1.2007
Epoch 8 Batch 50 Loss 1.2336
Epoch 8 Batch 100 Loss 1.2466
Epoch 8 Batch 150 Loss 1.2282

Epoch 8 Loss: 1.2404
Time taken for 1 epoch 5.28 sec
________________________________________________________________________________
Epoch 9 Batch 0 Loss 1.1911
Epoch 9 Batch 50 Loss 1.1818
Epoch 9 Batch 100 Loss 1.1954
Epoch 9 Batch 150 Loss 1.2156

Epoch 9 Loss: 1.2019
Time taken for 1 epoch 5.27 sec
________________________________________________________________________________
Epoch 10 Batch 0 Loss 1.1061
Epoch 10 Batch 50 Loss 1.1386
Epoch 10 Batch 100 Loss 1.1444
Epoch 10 Batch 150 Loss 1.1587

Epoch 10 Loss: 1.1627
Time taken for 1 epoch 5.58 sec
________________________________________________________________________________