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 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.

Cài đặt

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

import tensorflow as tf
from tensorflow.keras.layers.experimental import preprocessing

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 preprocessing.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 preprocessing.StringLookup lớp:

ids_from_chars = preprocessing.StringLookup(
    vocabulary=list(vocab), mask_token=None)

Nó chuyển đổi mã thông báo biểu mẫu 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 preprocessing.StringLookup(..., invert=True) .

chars_from_ids = tf.keras.layers.experimental.preprocessing.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)

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 shapes: ((64, 100), (64, 100)), types: (tf.int64, tf.int64)>

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([59, 27, 54, 42, 13, 61, 35, 33, 38, 42, 43, 58, 13, 27, 56, 26, 41,
       24,  7, 37, 27, 18, 11, 39,  9,  3,  5, 10, 18,  8, 12, 51, 43, 65,
       21, 30, 34, 12, 31, 46, 13, 37, 37, 31, 34,  9, 31, 51, 49,  7, 14,
        8, 54, 55, 37, 33, 27, 42, 59, 12, 46, 64, 12, 12, 39, 52, 40, 15,
       28, 22, 18, 44,  0, 59, 42, 45, 60,  8,  7, 35, 36, 31, 26, 50, 52,
       58,  8, 58, 51, 46, 16, 57, 34,  5,  4,  6, 10, 34, 60, 61])

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"ing thee on thy way:\nHad I thy youth and cause, I would not stay.\n\nHENRY BOLINGBROKE:\nThen, England'"

Next Char Predictions:
 b"tNoc?vVTYcds?NqMbK,XNE:Z.!&3E-;ldzHQU;Rg?XXRU.Rlj,A-opXTNct;gy;;ZmaBOIEe[UNK]tcfu-,VWRMkms-slgCrU&$'3Uuv"

Đà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.1905313

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.05788

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 [==============================] - 6s 24ms/step - loss: 2.7344
Epoch 2/20
172/172 [==============================] - 5s 23ms/step - loss: 1.9993
Epoch 3/20
172/172 [==============================] - 5s 23ms/step - loss: 1.7208
Epoch 4/20
172/172 [==============================] - 5s 23ms/step - loss: 1.5577
Epoch 5/20
172/172 [==============================] - 5s 23ms/step - loss: 1.4558
Epoch 6/20
172/172 [==============================] - 5s 23ms/step - loss: 1.3881
Epoch 7/20
172/172 [==============================] - 5s 23ms/step - loss: 1.3343
Epoch 8/20
172/172 [==============================] - 5s 23ms/step - loss: 1.2912
Epoch 9/20
172/172 [==============================] - 5s 24ms/step - loss: 1.2494
Epoch 10/20
172/172 [==============================] - 5s 23ms/step - loss: 1.2103
Epoch 11/20
172/172 [==============================] - 5s 23ms/step - loss: 1.1705
Epoch 12/20
172/172 [==============================] - 5s 23ms/step - loss: 1.1301
Epoch 13/20
172/172 [==============================] - 5s 23ms/step - loss: 1.0873
Epoch 14/20
172/172 [==============================] - 5s 23ms/step - loss: 1.0424
Epoch 15/20
172/172 [==============================] - 5s 23ms/step - loss: 0.9931
Epoch 16/20
172/172 [==============================] - 5s 23ms/step - loss: 0.9430
Epoch 17/20
172/172 [==============================] - 5s 23ms/step - loss: 0.8900
Epoch 18/20
172/172 [==============================] - 5s 23ms/step - loss: 0.8370
Epoch 19/20
172/172 [==============================] - 5s 23ms/step - loss: 0.7858
Epoch 20/20
172/172 [==============================] - 5s 23ms/step - loss: 0.7349

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 lại dự đoán và trạng thá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:
The sue, come not how to use your approach.

ABHORSON:
Grace it is! And see thou shalt win the world.
Farewell, and till I would allow it,
For his remembrance withal more no bleed
Shall be zellass'd may prove in sleep: 'tis notimilian,
And this befall not vexation and did
Tent before his friends at ghief. Yes, good
Come full of Edward's changelous, soon the King of Serio,
The ranks before i' the queen: poor thing is it, my lord,
To three herseip in the churchyard;
For who I miscalous be, as those looks,
Sir STook in parent, and the great deblings
nanger is the chiefest humble wear.
Boats that do love him in his head;
And thus I convey'd again to teach perfembrance of their blush.
Now, with grieves a grey of his oath-sativel,
So call him his good will.

ANTONIO:
Not out o' disorate institution.
A foel greate! do who think you, I say, or aught but
Your dimorously chope here, thou hast done; who canops he
unto these kites and bring from London be the heavy day.

QUEEN ELIZABETH:
As much  

________________________________________________________________________________

Run time: 2.309905767440796

Đ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:\nNot something;\nWhat satiey mounts, alish mercy!\n\nTRANIO:\nAn if thou hast made me? welcome home got by the thing\nThat you much shame speak upon't! Witch opposition\nWith them, and some access so roused?\n\nSIR SIET:\nWelcome, madam: to his conversation forgot!\nWhat if it should they bless us and the gods do grieve\nThe dignity of my pretty batches, and I'll lay\nAh, sigh of care, so unburious; how he meantile.\nIf I give them, and saved! what art\nthy treasury in this night, and so, my father hath been\nTo win thy amorous worldly lisch'd\nThat a wandering best of all my vowser ill towards.\nIs in your royal houses of his allies\nThat's he hath straitly general: Tybalts, which he died anon,\nLet to leck up the clouds, and therefore, and the\nqueen, you are to be my great refore. Pray you, Kate I doubt?\nWhat all affairs drown together, nor Eye,\nThe friarr, where'er a winged meant in true minister\nWorthy Senators: pate me, even like, first,\nBut for my arm'd blood-fall'd warlikes from the Tower:\nAs I wi"
 b"ROMEO:\nThey saw that which I should signify treason;\nThou'rt tired, too dear, and thou receivest to each a time\nTo salight shall have friendly loved.\n\nVIRGILIA:\nI do desire the quality of our kin.\n\nTYRREL:\nAy, but it is my wounded him.\n\nCOMINIUS:\nMarcius, ride, sir, your public is.\n\nVOLUMNIA:\nFarewell!\nI saw him I resolved to sleep,\nTo wish you please him in the very sile.\nBeing one but dread trades, and need from me,\n'Tis true the manner of thy soul, King Richard.'\nAnd signify to me, I am a great dove my regiol be:\nNot raised your pheasant crowns,\nBut send me groats to die: by this house,\nMy voice is mine, and not That valiant a few\ndrides me to work.\n\nYORK:\nThink not, sir, but you have in this accursed eldest.\n\nDERY ENIA:\nO, fire, fie, fie!\n\nRoman:\nI see there is a horse.\n\nNurse:\nThe softiles that\nfails, and leave good and unnatural language\nLe, you lie in time to come; for love forbear,\nAnd I am perveil'd to die.\n\nKING RICHARD III:\nWhy then pritthes make me, Boar, who had out\nat a vassal-"
 b"ROMEO:\nThe sweet'st commanded of these maiden-ly.\n\nBARDANES:\nAs good to see the breath of him as enemies;\nFor thou must swear absent her tybalt\nTo Honder on the partieg's word in honder,\nAs that we say, and feel't\nNot on their sufferance. Strike a past,\nInvest your guedness, and dried noble Edward's queen,\nThat press'd her fails we twink to draw.\n\nQEEN MARGARET:\nMy highness is the hand which I am heavenly;\nAnd when farewell, all turnsty Angelo!\nO, a horseman, and the king before mine.\n\nELBOW:\nAy, ay, the eastern in my comfort.\n\nISABELLA:\nThere milling them home: the rusty dulk ow what I have it,\nUrreaking steed should scarce through wither may Erward\nHas murdered and cut off my heart in such a sweet\nWould attam his head to come hither call our.\nHark you, pace up thy master's father's death,\nWhich he has done, Heaven in the trembling tears,\nAnd pass the present cip in the court o' the sup,\nWhether they dare perfimm'd, be need's good and\nmine. His fault rediscins him to\nraje, and spell of the "
 b"ROMEO:\nI shall resist it. Thou art these blood\nWhich now much mercelite toge worthy womb,\nWhere whom thou sta'bness me think that by all merry language\nMyself thy seast about his.\n\nFRIAR LAURENCE:\nHis majesty hath seized the throat and a pace from sulf\nAll that he was in his thankfulness,\nSo and no beef to-day my son Lerd night\nHave my eyes are Roman god he was a Richard duty,\nThou, madam, into his hands of an your course!\nWhat dogs this place?\n\nCORIOLANUS:\nHear's water! Come, How but Claudio and\nThe runs of his that account'st camon is\nA stranger in Rome; he scrape a braved before his\nears against him with a good duke. Farewell, good my lord,\nAnd he protectors on the bid thee bear,\nAccount him he ne'er look'd on sooth:\nSpeak to thy unfelting wind, itself shall be with the\nbows, should sing it: thou! alt do not such shore\nTo end the head, by their gentle words.\n\nBUCKINGHAM:\nBut first We have him to lay as he,\nNo hurble and as sovereignty, thereof,\nFindled, hewh two gager of my life:--\n\nKING "
 b"ROMEO:\nCome, come, my cousin. Fare you well, inducest office hase him.\n\nKING RICHARD III:\nTwose adam tilling, our countrymen are might\nwaits he.\n\nPAULINA:\nWhy, lady!\n\nEARO:\nAre mighty person.\n\nISARD III:\nAy, but there's all.\n\nFirst Servingman:\nNay, stay.\n\nServant:\nHast thou hadst chose the greates meet to hell?\nI'll lean upon you in a month. And that he has divided me\nThe otune away.\n\nANGELO:\nHow but alacement of the denitertion\nAnd free absolateful tides. Here's snarding\nWarrior the common fill: there shall be more,\nThan it ends it were a dran out with herse friends,\nBut lost thine own raty time to wail,\nWill taste of him a letter from his foe:\nLamest thou to Sicilia mean to me,\nBut dread to-day; there lie us wrong,\nLives a devil give at the throne;\nWord you three quarters and instruction gently length.\nI cry unto Bolingbroke, trusted this our command.\n\nDORSET:\nComfure do limit, or be here alone; or that he is,\nBetter her that you live from an enemy to the\nlasting last.\n\nSAMPSON:\nTwelvey Gl"], shape=(5,), dtype=string) 

________________________________________________________________________________

Run time: 2.2617812156677246

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 0x7f64b8efd8d0>, because it is not built.
2021-11-02 15:29:21.050569: W tensorflow/python/util/util.cc:348] 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_and_return_conditional_losses, gru_cell_layer_call_fn, gru_cell_layer_call_fn, gru_cell_layer_call_and_return_conditional_losses, gru_cell_layer_call_and_return_conditional_losses while saving (showing 5 of 5). 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:
Thou hast hawds charled you as a pair
of the queen's proud with our loves agains:
'Will't plove my

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.7227
<keras.callbacks.History at 0x7f64b8d084d0>

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.1971
Epoch 1 Batch 50 Loss 2.0726
Epoch 1 Batch 100 Loss 1.9573
Epoch 1 Batch 150 Loss 1.8796

Epoch 1 Loss: 1.9933
Time taken for 1 epoch 5.73 sec
________________________________________________________________________________
Epoch 2 Batch 0 Loss 1.8402
Epoch 2 Batch 50 Loss 1.6867
Epoch 2 Batch 100 Loss 1.6755
Epoch 2 Batch 150 Loss 1.6431

Epoch 2 Loss: 1.7131
Time taken for 1 epoch 5.42 sec
________________________________________________________________________________
Epoch 3 Batch 0 Loss 1.6155
Epoch 3 Batch 50 Loss 1.5543
Epoch 3 Batch 100 Loss 1.5555
Epoch 3 Batch 150 Loss 1.4958

Epoch 3 Loss: 1.5506
Time taken for 1 epoch 5.49 sec
________________________________________________________________________________
Epoch 4 Batch 0 Loss 1.5002
Epoch 4 Batch 50 Loss 1.4714
Epoch 4 Batch 100 Loss 1.4583
Epoch 4 Batch 150 Loss 1.3976

Epoch 4 Loss: 1.4505
Time taken for 1 epoch 5.40 sec
________________________________________________________________________________
Epoch 5 Batch 0 Loss 1.3637
Epoch 5 Batch 50 Loss 1.3797
Epoch 5 Batch 100 Loss 1.3884
Epoch 5 Batch 150 Loss 1.3380

Epoch 5 Loss: 1.3832
Time taken for 1 epoch 5.69 sec
________________________________________________________________________________
Epoch 6 Batch 0 Loss 1.3181
Epoch 6 Batch 50 Loss 1.3470
Epoch 6 Batch 100 Loss 1.3422
Epoch 6 Batch 150 Loss 1.3169

Epoch 6 Loss: 1.3304
Time taken for 1 epoch 5.29 sec
________________________________________________________________________________
Epoch 7 Batch 0 Loss 1.2529
Epoch 7 Batch 50 Loss 1.2987
Epoch 7 Batch 100 Loss 1.2781
Epoch 7 Batch 150 Loss 1.2782

Epoch 7 Loss: 1.2858
Time taken for 1 epoch 5.40 sec
________________________________________________________________________________
Epoch 8 Batch 0 Loss 1.2430
Epoch 8 Batch 50 Loss 1.2477
Epoch 8 Batch 100 Loss 1.2942
Epoch 8 Batch 150 Loss 1.2492

Epoch 8 Loss: 1.2442
Time taken for 1 epoch 5.33 sec
________________________________________________________________________________
Epoch 9 Batch 0 Loss 1.1563
Epoch 9 Batch 50 Loss 1.2002
Epoch 9 Batch 100 Loss 1.2727
Epoch 9 Batch 150 Loss 1.2236

Epoch 9 Loss: 1.2045
Time taken for 1 epoch 5.42 sec
________________________________________________________________________________
Epoch 10 Batch 0 Loss 1.1448
Epoch 10 Batch 50 Loss 1.1910
Epoch 10 Batch 100 Loss 1.1831
Epoch 10 Batch 150 Loss 1.1736

Epoch 10 Loss: 1.1655
Time taken for 1 epoch 5.59 sec
________________________________________________________________________________