![]() | ![]() | ![]() | ![]() |
이 가이드에서는 Transformer 모델 을 학습시켜 포르투갈어를 영어로 번역합니다. 이것은 텍스트 생성 및 주의에 대한 지식을 가정하는 고급 예제입니다.
Transformer 모델의 핵심 아이디어는 입력 시퀀스의 다른 위치에 주의를 기울여 해당 시퀀스의 표현을 계산하는 능력 인 자기주의 입니다. Transformer는 자기주의 레이어 스택을 생성하며 아래의 Scaled dot product Attention 및 Multi-head Attention 섹션에서 설명합니다.
대신에 자기 관심 층의 스택을 사용하여 변압기 모델 핸들 변수 크기의 입력 RNNs 또는 CNNs를 . 이 일반 아키텍처에는 다음과 같은 여러 장점이 있습니다.
- 데이터 전체의 시간적 / 공간적 관계에 대한 가정을하지 않습니다. 이것은 일련의 개체 (예 : StarCraft 유닛 )를 처리하는 데 이상적입니다.
- 레이어 출력은 RNN과 같은 시리즈 대신 병렬로 계산할 수 있습니다.
- 멀리있는 항목은 많은 RNN 단계 또는 컨볼 루션 레이어를 통과하지 않고도 서로의 출력에 영향을 미칠 수 있습니다 (예 : Scene Memory Transformer 참조).
- 장거리 의존성을 배울 수 있습니다. 이것은 많은 시퀀스 작업의 도전입니다.
이 아키텍처의 단점은 다음과 같습니다.
- 시계열의 경우 시간 단계에 대한 출력은 입력과 현재 숨겨진 상태 만이 아닌 전체 기록 에서 계산됩니다. 이것은 덜 효율적일 수 있습니다.
- 입력이 시간적 / 공간적 관계, 텍스트와 같은 일부 위치 부호화 추가해야 경우가 있는가 또는 모델 효과적으로 단어의 가방을 볼 것이다.
이 노트북에서 모델을 학습 한 후 포르투갈어 문장을 입력하고 영어 번역을 반환 할 수 있습니다.
# Pin matplotlib version to 3.2.2 since in the latest version
# transformer.ipynb fails with the following error:
# https://stackoverflow.com/questions/62953704/valueerror-the-number-of-fixedlocator-locations-5-usually-from-a-call-to-set
pip install -q matplotlib==3.2.2
import tensorflow_datasets as tfds
import tensorflow as tf
import time
import numpy as np
import matplotlib.pyplot as plt
입력 파이프 라인 설정
TFDS 를 사용하여 TED Talks Open Translation Project 에서 포르투갈어-영어 번역 데이터 셋 을로드합니다.
이 데이터 세트에는 약 50000 개의 교육 예제, 1100 개의 검증 예제 및 2000 개의 테스트 예제가 포함되어 있습니다.
examples, metadata = tfds.load('ted_hrlr_translate/pt_to_en', with_info=True,
as_supervised=True)
train_examples, val_examples = examples['train'], examples['validation']
Downloading and preparing dataset 124.94 MiB (download: 124.94 MiB, generated: Unknown size, total: 124.94 MiB) to /home/kbuilder/tensorflow_datasets/ted_hrlr_translate/pt_to_en/1.0.0... Dataset ted_hrlr_translate downloaded and prepared to /home/kbuilder/tensorflow_datasets/ted_hrlr_translate/pt_to_en/1.0.0. Subsequent calls will reuse this data.
훈련 데이터 세트에서 사용자 지정 하위 단어 토크 나이저를 만듭니다.
tokenizer_en = tfds.deprecated.text.SubwordTextEncoder.build_from_corpus(
(en.numpy() for pt, en in train_examples), target_vocab_size=2**13)
tokenizer_pt = tfds.deprecated.text.SubwordTextEncoder.build_from_corpus(
(pt.numpy() for pt, en in train_examples), target_vocab_size=2**13)
sample_string = 'Transformer is awesome.'
tokenized_string = tokenizer_en.encode(sample_string)
print ('Tokenized string is {}'.format(tokenized_string))
original_string = tokenizer_en.decode(tokenized_string)
print ('The original string: {}'.format(original_string))
assert original_string == sample_string
Tokenized string is [7915, 1248, 7946, 7194, 13, 2799, 7877] The original string: Transformer is awesome.
토크 나이 저는 단어가 사전에없는 경우 문자열을 하위 단어로 분할하여 문자열을 인코딩합니다.
for ts in tokenized_string:
print ('{} ----> {}'.format(ts, tokenizer_en.decode([ts])))
7915 ----> T 1248 ----> ran 7946 ----> s 7194 ----> former 13 ----> is 2799 ----> awesome 7877 ----> .
BUFFER_SIZE = 20000
BATCH_SIZE = 64
입력 및 대상에 시작 및 종료 토큰을 추가하십시오.
def encode(lang1, lang2):
lang1 = [tokenizer_pt.vocab_size] + tokenizer_pt.encode(
lang1.numpy()) + [tokenizer_pt.vocab_size+1]
lang2 = [tokenizer_en.vocab_size] + tokenizer_en.encode(
lang2.numpy()) + [tokenizer_en.vocab_size+1]
return lang1, lang2
Dataset.map
을 사용 Dataset.map
함수를 데이터 세트의 각 요소에 적용하려고합니다. Dataset.map
은 그래프 모드에서 실행됩니다.
- 그래프 텐서는 값이 없습니다.
- 그래프 모드에서는 TensorFlow Ops 및 함수 만 사용할 수 있습니다.
따라서이 함수를 직접 .map
할 수 없습니다. tf.py_function
으로 래핑해야합니다. tf.py_function
은 일반 텐서 (값 및 .numpy()
메서드에 액세스)를 래핑 된 파이썬 함수에 전달합니다.
def tf_encode(pt, en):
result_pt, result_en = tf.py_function(encode, [pt, en], [tf.int64, tf.int64])
result_pt.set_shape([None])
result_en.set_shape([None])
return result_pt, result_en
MAX_LENGTH = 40
def filter_max_length(x, y, max_length=MAX_LENGTH):
return tf.logical_and(tf.size(x) <= max_length,
tf.size(y) <= max_length)
train_dataset = train_examples.map(tf_encode)
train_dataset = train_dataset.filter(filter_max_length)
# cache the dataset to memory to get a speedup while reading from it.
train_dataset = train_dataset.cache()
train_dataset = train_dataset.shuffle(BUFFER_SIZE).padded_batch(BATCH_SIZE)
train_dataset = train_dataset.prefetch(tf.data.AUTOTUNE)
val_dataset = val_examples.map(tf_encode)
val_dataset = val_dataset.filter(filter_max_length).padded_batch(BATCH_SIZE)
pt_batch, en_batch = next(iter(val_dataset))
pt_batch, en_batch
(<tf.Tensor: shape=(64, 38), dtype=int64, numpy= array([[8214, 342, 3032, ..., 0, 0, 0], [8214, 95, 198, ..., 0, 0, 0], [8214, 4479, 7990, ..., 0, 0, 0], ..., [8214, 584, 12, ..., 0, 0, 0], [8214, 59, 1548, ..., 0, 0, 0], [8214, 118, 34, ..., 0, 0, 0]])>, <tf.Tensor: shape=(64, 40), dtype=int64, numpy= array([[8087, 98, 25, ..., 0, 0, 0], [8087, 12, 20, ..., 0, 0, 0], [8087, 12, 5453, ..., 0, 0, 0], ..., [8087, 18, 2059, ..., 0, 0, 0], [8087, 16, 1436, ..., 0, 0, 0], [8087, 15, 57, ..., 0, 0, 0]])>)
위치 인코딩
이 모델에는 반복 또는 컨볼 루션이 포함되어 있지 않으므로 위치 인코딩이 추가되어 문장에서 단어의 상대적 위치에 대한 정보를 모델에 제공합니다.
위치 인코딩 벡터가 임베딩 벡터에 추가됩니다. 임베딩은 유사한 의미의 토큰이 서로 더 가까워지는 d 차원 공간의 토큰을 나타냅니다. 그러나 임베딩은 문장에서 단어의 상대적 위치를 인코딩하지 않습니다. 따라서 위치 인코딩을 추가하면 단어 의 의미와 문장에서의 위치 , d 차원 공간의 유사성에 따라 단어가 서로 더 가까워집니다.
자세한 내용은 위치 인코딩 에 대한 노트북을 참조하십시오. 위치 인코딩을 계산하는 공식은 다음과 같습니다.
def get_angles(pos, i, d_model):
angle_rates = 1 / np.power(10000, (2 * (i//2)) / np.float32(d_model))
return pos * angle_rates
def positional_encoding(position, d_model):
angle_rads = get_angles(np.arange(position)[:, np.newaxis],
np.arange(d_model)[np.newaxis, :],
d_model)
# apply sin to even indices in the array; 2i
angle_rads[:, 0::2] = np.sin(angle_rads[:, 0::2])
# apply cos to odd indices in the array; 2i+1
angle_rads[:, 1::2] = np.cos(angle_rads[:, 1::2])
pos_encoding = angle_rads[np.newaxis, ...]
return tf.cast(pos_encoding, dtype=tf.float32)
pos_encoding = positional_encoding(50, 512)
print (pos_encoding.shape)
plt.pcolormesh(pos_encoding[0], cmap='RdBu')
plt.xlabel('Depth')
plt.xlim((0, 512))
plt.ylabel('Position')
plt.colorbar()
plt.show()
(1, 50, 512)
마스킹
시퀀스 배치에서 모든 패드 토큰을 마스킹합니다. 모델이 패딩을 입력으로 취급하지 않도록합니다. 마스크는 패드 값 0
이있는 위치를 나타냅니다. 해당 위치에 1
을 출력하고 그렇지 않으면 0
출력합니다.
def create_padding_mask(seq):
seq = tf.cast(tf.math.equal(seq, 0), tf.float32)
# add extra dimensions to add the padding
# to the attention logits.
return seq[:, tf.newaxis, tf.newaxis, :] # (batch_size, 1, 1, seq_len)
x = tf.constant([[7, 6, 0, 0, 1], [1, 2, 3, 0, 0], [0, 0, 0, 4, 5]])
create_padding_mask(x)
<tf.Tensor: shape=(3, 1, 1, 5), dtype=float32, numpy= array([[[[0., 0., 1., 1., 0.]]], [[[0., 0., 0., 1., 1.]]], [[[1., 1., 1., 0., 0.]]]], dtype=float32)>
미리보기 마스크는 시퀀스에서 미래 토큰을 마스킹하는 데 사용됩니다. 즉, 마스크는 사용해서는 안되는 항목을 나타냅니다.
즉, 세 번째 단어를 예측하려면 첫 번째 단어와 두 번째 단어 만 사용됩니다. 네 번째 단어를 예측하는 것과 유사하게 첫 번째, 두 번째 및 세 번째 단어 만 사용됩니다.
def create_look_ahead_mask(size):
mask = 1 - tf.linalg.band_part(tf.ones((size, size)), -1, 0)
return mask # (seq_len, seq_len)
x = tf.random.uniform((1, 3))
temp = create_look_ahead_mask(x.shape[1])
temp
<tf.Tensor: shape=(3, 3), dtype=float32, numpy= array([[0., 1., 1.], [0., 0., 1.], [0., 0., 0.]], dtype=float32)>
배율 내적주의
변환기가 사용하는주의 함수는 Q (쿼리), K (키), V (값)의 세 가지 입력을받습니다. 주의 가중치를 계산하는 데 사용되는 방정식은 다음과 같습니다.
내적 관심도는 깊이의 제곱근 계수로 조정됩니다. 이는 깊이 값이 크면 내적이 크기가 커지므로 기울기가 작은 소프트 맥스 함수를 밀어서 매우 단단한 소프트 맥스가됩니다.
예를 들어, Q
와 K
의 평균이 0이고 분산이 1이라고 가정합니다. 행렬 곱셈은 평균이 0이고 분산이 dk
입니다. 따라서 Q
와 K
의 matmul은 평균이 0이고 분산이 1이어야하고 더 부드러운 소프트 맥스를 얻으므로 dk
제곱근이 스케일링에 사용됩니다 (다른 숫자는 아님).
마스크에는 -1e9 (음의 무한대에 가까움)가 곱해집니다. 이것은 마스크가 Q와 K의 스케일 된 행렬 곱셈으로 합산되고 소프트 맥스 직전에 적용되기 때문에 수행됩니다. 목표는 이러한 셀을 제로화하는 것이며 소프트 맥스에 대한 큰 음의 입력은 출력에서 거의 제로에 가깝습니다.
def scaled_dot_product_attention(q, k, v, mask):
"""Calculate the attention weights.
q, k, v must have matching leading dimensions.
k, v must have matching penultimate dimension, i.e.: seq_len_k = seq_len_v.
The mask has different shapes depending on its type(padding or look ahead)
but it must be broadcastable for addition.
Args:
q: query shape == (..., seq_len_q, depth)
k: key shape == (..., seq_len_k, depth)
v: value shape == (..., seq_len_v, depth_v)
mask: Float tensor with shape broadcastable
to (..., seq_len_q, seq_len_k). Defaults to None.
Returns:
output, attention_weights
"""
matmul_qk = tf.matmul(q, k, transpose_b=True) # (..., seq_len_q, seq_len_k)
# scale matmul_qk
dk = tf.cast(tf.shape(k)[-1], tf.float32)
scaled_attention_logits = matmul_qk / tf.math.sqrt(dk)
# add the mask to the scaled tensor.
if mask is not None:
scaled_attention_logits += (mask * -1e9)
# softmax is normalized on the last axis (seq_len_k) so that the scores
# add up to 1.
attention_weights = tf.nn.softmax(scaled_attention_logits, axis=-1) # (..., seq_len_q, seq_len_k)
output = tf.matmul(attention_weights, v) # (..., seq_len_q, depth_v)
return output, attention_weights
소프트 맥스 정규화가 K에서 수행되므로 해당 값은 Q에 부여되는 중요도를 결정합니다.
출력은주의 가중치와 V (값) 벡터의 곱셈을 나타냅니다. 이렇게하면 집중하려는 단어가 그대로 유지되고 관련없는 단어는 제거됩니다.
def print_out(q, k, v):
temp_out, temp_attn = scaled_dot_product_attention(
q, k, v, None)
print ('Attention weights are:')
print (temp_attn)
print ('Output is:')
print (temp_out)
np.set_printoptions(suppress=True)
temp_k = tf.constant([[10,0,0],
[0,10,0],
[0,0,10],
[0,0,10]], dtype=tf.float32) # (4, 3)
temp_v = tf.constant([[ 1,0],
[ 10,0],
[ 100,5],
[1000,6]], dtype=tf.float32) # (4, 2)
# This `query` aligns with the second `key`,
# so the second `value` is returned.
temp_q = tf.constant([[0, 10, 0]], dtype=tf.float32) # (1, 3)
print_out(temp_q, temp_k, temp_v)
Attention weights are: tf.Tensor([[0. 1. 0. 0.]], shape=(1, 4), dtype=float32) Output is: tf.Tensor([[10. 0.]], shape=(1, 2), dtype=float32)
# This query aligns with a repeated key (third and fourth),
# so all associated values get averaged.
temp_q = tf.constant([[0, 0, 10]], dtype=tf.float32) # (1, 3)
print_out(temp_q, temp_k, temp_v)
Attention weights are: tf.Tensor([[0. 0. 0.5 0.5]], shape=(1, 4), dtype=float32) Output is: tf.Tensor([[550. 5.5]], shape=(1, 2), dtype=float32)
# This query aligns equally with the first and second key,
# so their values get averaged.
temp_q = tf.constant([[10, 10, 0]], dtype=tf.float32) # (1, 3)
print_out(temp_q, temp_k, temp_v)
Attention weights are: tf.Tensor([[0.5 0.5 0. 0. ]], shape=(1, 4), dtype=float32) Output is: tf.Tensor([[5.5 0. ]], shape=(1, 2), dtype=float32)
모든 쿼리를 함께 전달하십시오.
temp_q = tf.constant([[0, 0, 10], [0, 10, 0], [10, 10, 0]], dtype=tf.float32) # (3, 3)
print_out(temp_q, temp_k, temp_v)
Attention weights are: tf.Tensor( [[0. 0. 0.5 0.5] [0. 1. 0. 0. ] [0.5 0.5 0. 0. ]], shape=(3, 4), dtype=float32) Output is: tf.Tensor( [[550. 5.5] [ 10. 0. ] [ 5.5 0. ]], shape=(3, 2), dtype=float32)
다중 머리주의
다중 머리주의는 네 부분으로 구성됩니다.
- 선형 레이어 및 헤드로 분할됩니다.
- 확장 된 내적주의.
- 머리의 연결.
- 최종 선형 레이어.
각 다중 헤드주의 블록에는 세 가지 입력이 있습니다. Q (쿼리), K (키), V (값). 이들은 선형 (Dense) 레이어를 통과하여 여러 개의 헤드로 분할됩니다.
위에서 정의한 scaled_dot_product_attention
은 각 헤드에 적용됩니다 (효율성을 위해 방송 됨). 주의 단계에서 적절한 마스크를 사용해야합니다. 그런 다음 각 헤드에 대한주의 출력이 연결되고 ( tf.transpose
및 tf.reshape
) 최종 Dense
레이어를 통과합니다.
하나의 어텐션 헤드 대신 Q, K, V는 모델이 서로 다른 표현 공간의 서로 다른 위치에있는 정보에 공동으로 참여할 수 있기 때문에 여러 개의 헤드로 분할됩니다. 분할 후 각 머리는 차원이 감소하므로 총 계산 비용은 전체 차원의 단일 머리주의와 동일합니다.
class MultiHeadAttention(tf.keras.layers.Layer):
def __init__(self, d_model, num_heads):
super(MultiHeadAttention, self).__init__()
self.num_heads = num_heads
self.d_model = d_model
assert d_model % self.num_heads == 0
self.depth = d_model // self.num_heads
self.wq = tf.keras.layers.Dense(d_model)
self.wk = tf.keras.layers.Dense(d_model)
self.wv = tf.keras.layers.Dense(d_model)
self.dense = tf.keras.layers.Dense(d_model)
def split_heads(self, x, batch_size):
"""Split the last dimension into (num_heads, depth).
Transpose the result such that the shape is (batch_size, num_heads, seq_len, depth)
"""
x = tf.reshape(x, (batch_size, -1, self.num_heads, self.depth))
return tf.transpose(x, perm=[0, 2, 1, 3])
def call(self, v, k, q, mask):
batch_size = tf.shape(q)[0]
q = self.wq(q) # (batch_size, seq_len, d_model)
k = self.wk(k) # (batch_size, seq_len, d_model)
v = self.wv(v) # (batch_size, seq_len, d_model)
q = self.split_heads(q, batch_size) # (batch_size, num_heads, seq_len_q, depth)
k = self.split_heads(k, batch_size) # (batch_size, num_heads, seq_len_k, depth)
v = self.split_heads(v, batch_size) # (batch_size, num_heads, seq_len_v, depth)
# scaled_attention.shape == (batch_size, num_heads, seq_len_q, depth)
# attention_weights.shape == (batch_size, num_heads, seq_len_q, seq_len_k)
scaled_attention, attention_weights = scaled_dot_product_attention(
q, k, v, mask)
scaled_attention = tf.transpose(scaled_attention, perm=[0, 2, 1, 3]) # (batch_size, seq_len_q, num_heads, depth)
concat_attention = tf.reshape(scaled_attention,
(batch_size, -1, self.d_model)) # (batch_size, seq_len_q, d_model)
output = self.dense(concat_attention) # (batch_size, seq_len_q, d_model)
return output, attention_weights
시도 할 MultiHeadAttention
레이어를 만듭니다. 시퀀스의 각 위치 y
에서 MultiHeadAttention
은 시퀀스의 다른 모든 위치에서 8 개의주의 헤드를 모두 실행하여 각 위치에서 동일한 길이의 새 벡터를 반환합니다.
temp_mha = MultiHeadAttention(d_model=512, num_heads=8)
y = tf.random.uniform((1, 60, 512)) # (batch_size, encoder_sequence, d_model)
out, attn = temp_mha(y, k=y, q=y, mask=None)
out.shape, attn.shape
(TensorShape([1, 60, 512]), TensorShape([1, 8, 60, 60]))
포인트 현명한 피드 포워드 네트워크
포인트 현명 피드 포워드 네트워크는 ReLU 활성화가 중간에있는 두 개의 완전히 연결된 계층으로 구성됩니다.
def point_wise_feed_forward_network(d_model, dff):
return tf.keras.Sequential([
tf.keras.layers.Dense(dff, activation='relu'), # (batch_size, seq_len, dff)
tf.keras.layers.Dense(d_model) # (batch_size, seq_len, d_model)
])
sample_ffn = point_wise_feed_forward_network(512, 2048)
sample_ffn(tf.random.uniform((64, 50, 512))).shape
TensorShape([64, 50, 512])
인코더 및 디코더
변환기 모델 은주의 모델로 시퀀싱하기 위해 표준 시퀀스 와 동일한 일반 패턴을 따릅니다.
- 입력 문장은 시퀀스의 각 단어 / 토큰에 대한 출력을 생성하는
N
인코더 레이어를 통해 전달됩니다. - 디코더는 다음 단어를 예측하기 위해 인코더의 출력과 자체 입력 (자기주의)을 처리합니다.
인코더 레이어
각 인코더 계층은 하위 계층으로 구성됩니다.
- 다중 머리주의 (패딩 마스크 포함)
- 포인트 현명한 피드 포워드 네트워크.
이러한 각 하위 계층에는 계층 정규화가 뒤 따르는 잔여 연결이 있습니다. 잔여 연결은 딥 네트워크에서 사라지는 기울기 문제를 방지하는 데 도움이됩니다.
각 하위 계층의 출력은 LayerNorm(x + Sublayer(x))
입니다. 정규화는 d_model
(마지막) 축에서 수행됩니다. 변압기에는 N 개의 인코더 레이어가 있습니다.
class EncoderLayer(tf.keras.layers.Layer):
def __init__(self, d_model, num_heads, dff, rate=0.1):
super(EncoderLayer, self).__init__()
self.mha = MultiHeadAttention(d_model, num_heads)
self.ffn = point_wise_feed_forward_network(d_model, dff)
self.layernorm1 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
self.layernorm2 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
self.dropout1 = tf.keras.layers.Dropout(rate)
self.dropout2 = tf.keras.layers.Dropout(rate)
def call(self, x, training, mask):
attn_output, _ = self.mha(x, x, x, mask) # (batch_size, input_seq_len, d_model)
attn_output = self.dropout1(attn_output, training=training)
out1 = self.layernorm1(x + attn_output) # (batch_size, input_seq_len, d_model)
ffn_output = self.ffn(out1) # (batch_size, input_seq_len, d_model)
ffn_output = self.dropout2(ffn_output, training=training)
out2 = self.layernorm2(out1 + ffn_output) # (batch_size, input_seq_len, d_model)
return out2
sample_encoder_layer = EncoderLayer(512, 8, 2048)
sample_encoder_layer_output = sample_encoder_layer(
tf.random.uniform((64, 43, 512)), False, None)
sample_encoder_layer_output.shape # (batch_size, input_seq_len, d_model)
TensorShape([64, 43, 512])
디코더 레이어
각 디코더 계층은 하위 계층으로 구성됩니다.
- 마스킹 된 멀티 헤드 어텐션 (미리보기 마스크 및 패딩 마스크 포함)
- 다중 머리주의 (패딩 마스크 포함). V (값) 및 K (키)는 엔코더 출력 을 입력으로받습니다. Q (쿼리)는 마스킹 된 다중 머리주의 하위 계층에서 출력을 수신합니다 .
- 포인트 현명한 피드 포워드 네트워크
이러한 각 하위 계층에는 계층 정규화가 뒤 따르는 잔여 연결이 있습니다. 각 하위 계층의 출력은 LayerNorm(x + Sublayer(x))
입니다. 정규화는 d_model
(마지막) 축에서 수행됩니다.
트랜스포머에는 N 개의 디코더 레이어가 있습니다.
Q가 디코더의 첫 번째주의 블록에서 출력을 수신하고 K가 인코더 출력을 수신 할 때주의 가중치는 인코더의 출력을 기반으로 디코더의 입력에 주어진 중요도를 나타냅니다. 즉, 디코더는 인코더 출력을보고 자체 출력에 자동으로 참석하여 다음 단어를 예측합니다. 스케일 된 내적주의 섹션에서 위의 데모를 참조하십시오.
class DecoderLayer(tf.keras.layers.Layer):
def __init__(self, d_model, num_heads, dff, rate=0.1):
super(DecoderLayer, self).__init__()
self.mha1 = MultiHeadAttention(d_model, num_heads)
self.mha2 = MultiHeadAttention(d_model, num_heads)
self.ffn = point_wise_feed_forward_network(d_model, dff)
self.layernorm1 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
self.layernorm2 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
self.layernorm3 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
self.dropout1 = tf.keras.layers.Dropout(rate)
self.dropout2 = tf.keras.layers.Dropout(rate)
self.dropout3 = tf.keras.layers.Dropout(rate)
def call(self, x, enc_output, training,
look_ahead_mask, padding_mask):
# enc_output.shape == (batch_size, input_seq_len, d_model)
attn1, attn_weights_block1 = self.mha1(x, x, x, look_ahead_mask) # (batch_size, target_seq_len, d_model)
attn1 = self.dropout1(attn1, training=training)
out1 = self.layernorm1(attn1 + x)
attn2, attn_weights_block2 = self.mha2(
enc_output, enc_output, out1, padding_mask) # (batch_size, target_seq_len, d_model)
attn2 = self.dropout2(attn2, training=training)
out2 = self.layernorm2(attn2 + out1) # (batch_size, target_seq_len, d_model)
ffn_output = self.ffn(out2) # (batch_size, target_seq_len, d_model)
ffn_output = self.dropout3(ffn_output, training=training)
out3 = self.layernorm3(ffn_output + out2) # (batch_size, target_seq_len, d_model)
return out3, attn_weights_block1, attn_weights_block2
sample_decoder_layer = DecoderLayer(512, 8, 2048)
sample_decoder_layer_output, _, _ = sample_decoder_layer(
tf.random.uniform((64, 50, 512)), sample_encoder_layer_output,
False, None, None)
sample_decoder_layer_output.shape # (batch_size, target_seq_len, d_model)
TensorShape([64, 50, 512])
인코더
Encoder
는 다음으로 구성됩니다.
- 입력 임베딩
- 위치 인코딩
- N 인코더 레이어
입력은 위치 인코딩과 합산되는 임베딩을 통해 이루어집니다. 이 합산의 출력은 인코더 계층에 대한 입력입니다. 인코더의 출력은 디코더에 대한 입력입니다.
class Encoder(tf.keras.layers.Layer):
def __init__(self, num_layers, d_model, num_heads, dff, input_vocab_size,
maximum_position_encoding, rate=0.1):
super(Encoder, self).__init__()
self.d_model = d_model
self.num_layers = num_layers
self.embedding = tf.keras.layers.Embedding(input_vocab_size, d_model)
self.pos_encoding = positional_encoding(maximum_position_encoding,
self.d_model)
self.enc_layers = [EncoderLayer(d_model, num_heads, dff, rate)
for _ in range(num_layers)]
self.dropout = tf.keras.layers.Dropout(rate)
def call(self, x, training, mask):
seq_len = tf.shape(x)[1]
# adding embedding and position encoding.
x = self.embedding(x) # (batch_size, input_seq_len, d_model)
x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32))
x += self.pos_encoding[:, :seq_len, :]
x = self.dropout(x, training=training)
for i in range(self.num_layers):
x = self.enc_layers[i](x, training, mask)
return x # (batch_size, input_seq_len, d_model)
sample_encoder = Encoder(num_layers=2, d_model=512, num_heads=8,
dff=2048, input_vocab_size=8500,
maximum_position_encoding=10000)
temp_input = tf.random.uniform((64, 62), dtype=tf.int64, minval=0, maxval=200)
sample_encoder_output = sample_encoder(temp_input, training=False, mask=None)
print (sample_encoder_output.shape) # (batch_size, input_seq_len, d_model)
(64, 62, 512)
디코더
Decoder
는 다음으로 구성됩니다.
- 출력 임베딩
- 위치 인코딩
- N 디코더 레이어
대상은 위치 인코딩으로 합산되는 임베딩을 통과합니다. 이 합산의 출력은 디코더 계층에 대한 입력입니다. 디코더의 출력은 최종 선형 레이어에 대한 입력입니다.
class Decoder(tf.keras.layers.Layer):
def __init__(self, num_layers, d_model, num_heads, dff, target_vocab_size,
maximum_position_encoding, rate=0.1):
super(Decoder, self).__init__()
self.d_model = d_model
self.num_layers = num_layers
self.embedding = tf.keras.layers.Embedding(target_vocab_size, d_model)
self.pos_encoding = positional_encoding(maximum_position_encoding, d_model)
self.dec_layers = [DecoderLayer(d_model, num_heads, dff, rate)
for _ in range(num_layers)]
self.dropout = tf.keras.layers.Dropout(rate)
def call(self, x, enc_output, training,
look_ahead_mask, padding_mask):
seq_len = tf.shape(x)[1]
attention_weights = {}
x = self.embedding(x) # (batch_size, target_seq_len, d_model)
x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32))
x += self.pos_encoding[:, :seq_len, :]
x = self.dropout(x, training=training)
for i in range(self.num_layers):
x, block1, block2 = self.dec_layers[i](x, enc_output, training,
look_ahead_mask, padding_mask)
attention_weights['decoder_layer{}_block1'.format(i+1)] = block1
attention_weights['decoder_layer{}_block2'.format(i+1)] = block2
# x.shape == (batch_size, target_seq_len, d_model)
return x, attention_weights
sample_decoder = Decoder(num_layers=2, d_model=512, num_heads=8,
dff=2048, target_vocab_size=8000,
maximum_position_encoding=5000)
temp_input = tf.random.uniform((64, 26), dtype=tf.int64, minval=0, maxval=200)
output, attn = sample_decoder(temp_input,
enc_output=sample_encoder_output,
training=False,
look_ahead_mask=None,
padding_mask=None)
output.shape, attn['decoder_layer2_block2'].shape
(TensorShape([64, 26, 512]), TensorShape([64, 8, 26, 62]))
변환기 만들기
Transformer는 인코더, 디코더 및 최종 선형 레이어로 구성됩니다. 디코더의 출력은 선형 레이어에 대한 입력이며 출력이 반환됩니다.
class Transformer(tf.keras.Model):
def __init__(self, num_layers, d_model, num_heads, dff, input_vocab_size,
target_vocab_size, pe_input, pe_target, rate=0.1):
super(Transformer, self).__init__()
self.encoder = Encoder(num_layers, d_model, num_heads, dff,
input_vocab_size, pe_input, rate)
self.decoder = Decoder(num_layers, d_model, num_heads, dff,
target_vocab_size, pe_target, rate)
self.final_layer = tf.keras.layers.Dense(target_vocab_size)
def call(self, inp, tar, training, enc_padding_mask,
look_ahead_mask, dec_padding_mask):
enc_output = self.encoder(inp, training, enc_padding_mask) # (batch_size, inp_seq_len, d_model)
# dec_output.shape == (batch_size, tar_seq_len, d_model)
dec_output, attention_weights = self.decoder(
tar, enc_output, training, look_ahead_mask, dec_padding_mask)
final_output = self.final_layer(dec_output) # (batch_size, tar_seq_len, target_vocab_size)
return final_output, attention_weights
sample_transformer = Transformer(
num_layers=2, d_model=512, num_heads=8, dff=2048,
input_vocab_size=8500, target_vocab_size=8000,
pe_input=10000, pe_target=6000)
temp_input = tf.random.uniform((64, 38), dtype=tf.int64, minval=0, maxval=200)
temp_target = tf.random.uniform((64, 36), dtype=tf.int64, minval=0, maxval=200)
fn_out, _ = sample_transformer(temp_input, temp_target, training=False,
enc_padding_mask=None,
look_ahead_mask=None,
dec_padding_mask=None)
fn_out.shape # (batch_size, tar_seq_len, target_vocab_size)
TensorShape([64, 36, 8000])
초 매개 변수 설정
이 예제를 작고 비교적 빠르게 유지하기 위해 num_layers, d_model 및 dff 의 값을 줄였습니다.
변압기의 기본 모델에 사용 된 값은 다음과 같습니다. num_layers = 6 , d_model = 512 , dff = 2048 . 다른 모든 버전의 변압기에 대한 문서 를 참조하십시오.
num_layers = 4
d_model = 128
dff = 512
num_heads = 8
input_vocab_size = tokenizer_pt.vocab_size + 2
target_vocab_size = tokenizer_en.vocab_size + 2
dropout_rate = 0.1
옵티 마이저
논문 의 공식에 따라 맞춤 학습률 스케줄러와 함께 Adam 최적화 프로그램을 사용합니다.
class CustomSchedule(tf.keras.optimizers.schedules.LearningRateSchedule):
def __init__(self, d_model, warmup_steps=4000):
super(CustomSchedule, self).__init__()
self.d_model = d_model
self.d_model = tf.cast(self.d_model, tf.float32)
self.warmup_steps = warmup_steps
def __call__(self, step):
arg1 = tf.math.rsqrt(step)
arg2 = step * (self.warmup_steps ** -1.5)
return tf.math.rsqrt(self.d_model) * tf.math.minimum(arg1, arg2)
learning_rate = CustomSchedule(d_model)
optimizer = tf.keras.optimizers.Adam(learning_rate, beta_1=0.9, beta_2=0.98,
epsilon=1e-9)
temp_learning_rate_schedule = CustomSchedule(d_model)
plt.plot(temp_learning_rate_schedule(tf.range(40000, dtype=tf.float32)))
plt.ylabel("Learning Rate")
plt.xlabel("Train Step")
Text(0.5, 0, 'Train Step')
손실 및 지표
타겟 시퀀스가 패딩되기 때문에 손실을 계산할 때 패딩 마스크를 적용하는 것이 중요합니다.
loss_object = tf.keras.losses.SparseCategoricalCrossentropy(
from_logits=True, reduction='none')
def loss_function(real, pred):
mask = tf.math.logical_not(tf.math.equal(real, 0))
loss_ = loss_object(real, pred)
mask = tf.cast(mask, dtype=loss_.dtype)
loss_ *= mask
return tf.reduce_sum(loss_)/tf.reduce_sum(mask)
def accuracy_function(real, pred):
accuracies = tf.equal(real, tf.argmax(pred, axis=2))
mask = tf.math.logical_not(tf.math.equal(real, 0))
accuracies = tf.math.logical_and(mask, accuracies)
accuracies = tf.cast(accuracies, dtype=tf.float32)
mask = tf.cast(mask, dtype=tf.float32)
return tf.reduce_sum(accuracies)/tf.reduce_sum(mask)
train_loss = tf.keras.metrics.Mean(name='train_loss')
train_accuracy = tf.keras.metrics.Mean(name='train_accuracy')
교육 및 체크 포인트
transformer = Transformer(num_layers, d_model, num_heads, dff,
input_vocab_size, target_vocab_size,
pe_input=input_vocab_size,
pe_target=target_vocab_size,
rate=dropout_rate)
def create_masks(inp, tar):
# Encoder padding mask
enc_padding_mask = create_padding_mask(inp)
# Used in the 2nd attention block in the decoder.
# This padding mask is used to mask the encoder outputs.
dec_padding_mask = create_padding_mask(inp)
# Used in the 1st attention block in the decoder.
# It is used to pad and mask future tokens in the input received by
# the decoder.
look_ahead_mask = create_look_ahead_mask(tf.shape(tar)[1])
dec_target_padding_mask = create_padding_mask(tar)
combined_mask = tf.maximum(dec_target_padding_mask, look_ahead_mask)
return enc_padding_mask, combined_mask, dec_padding_mask
체크 포인트 경로와 체크 포인트 관리자를 생성합니다. 이는 n
epoch마다 체크 포인트를 저장하는 데 사용됩니다.
checkpoint_path = "./checkpoints/train"
ckpt = tf.train.Checkpoint(transformer=transformer,
optimizer=optimizer)
ckpt_manager = tf.train.CheckpointManager(ckpt, checkpoint_path, max_to_keep=5)
# if a checkpoint exists, restore the latest checkpoint.
if ckpt_manager.latest_checkpoint:
ckpt.restore(ckpt_manager.latest_checkpoint)
print ('Latest checkpoint restored!!')
대상은 tar_inp와 tar_real로 나뉩니다. tar_inp는 디코더에 대한 입력으로 전달됩니다. tar_real
동일한 입력이 1만큼 시프트이다 : 각 위치에서 tar_input
, tar_real
예측되어야하는 다음의 토큰을 포함한다.
예를 들어, sentence
= "SOS 정글의 사자는 EOS를 자고 있습니다"
tar_inp
= "SOS 정글의 사자가 자고 있습니다."
tar_real
= "정글의 사자가 EOS를 자고 있습니다"
변환기는 자동 회귀 모델입니다. 한 번에 한 부분을 예측하고 지금까지의 출력을 사용하여 다음에 수행 할 작업을 결정합니다.
훈련 중에이 예제는 교사 강제를 사용합니다 ( 텍스트 생성 튜토리얼 에서와 같이). 교사 강제는 모델이 현재 시간 단계에서 예측하는 내용에 관계없이 실제 출력을 다음 시간 단계로 전달합니다.
변환기가 각 단어를 예측할 때 자기주의를 통해 입력 시퀀스의 이전 단어를보고 다음 단어를 더 잘 예측할 수 있습니다.
모델이 예상 출력을 엿보는 것을 방지하기 위해 모델은 미리보기 마스크를 사용합니다.
EPOCHS = 20
# The @tf.function trace-compiles train_step into a TF graph for faster
# execution. The function specializes to the precise shape of the argument
# tensors. To avoid re-tracing due to the variable sequence lengths or variable
# batch sizes (the last batch is smaller), use input_signature to specify
# more generic shapes.
train_step_signature = [
tf.TensorSpec(shape=(None, None), dtype=tf.int64),
tf.TensorSpec(shape=(None, None), dtype=tf.int64),
]
@tf.function(input_signature=train_step_signature)
def train_step(inp, tar):
tar_inp = tar[:, :-1]
tar_real = tar[:, 1:]
enc_padding_mask, combined_mask, dec_padding_mask = create_masks(inp, tar_inp)
with tf.GradientTape() as tape:
predictions, _ = transformer(inp, tar_inp,
True,
enc_padding_mask,
combined_mask,
dec_padding_mask)
loss = loss_function(tar_real, predictions)
gradients = tape.gradient(loss, transformer.trainable_variables)
optimizer.apply_gradients(zip(gradients, transformer.trainable_variables))
train_loss(loss)
train_accuracy(accuracy_function(tar_real, predictions))
포르투갈어가 입력 언어로 사용되고 영어가 대상 언어로 사용됩니다.
for epoch in range(EPOCHS):
start = time.time()
train_loss.reset_states()
train_accuracy.reset_states()
# inp -> portuguese, tar -> english
for (batch, (inp, tar)) in enumerate(train_dataset):
train_step(inp, tar)
if batch % 50 == 0:
print ('Epoch {} Batch {} Loss {:.4f} Accuracy {:.4f}'.format(
epoch + 1, batch, train_loss.result(), train_accuracy.result()))
if (epoch + 1) % 5 == 0:
ckpt_save_path = ckpt_manager.save()
print ('Saving checkpoint for epoch {} at {}'.format(epoch+1,
ckpt_save_path))
print ('Epoch {} Loss {:.4f} Accuracy {:.4f}'.format(epoch + 1,
train_loss.result(),
train_accuracy.result()))
print ('Time taken for 1 epoch: {} secs\n'.format(time.time() - start))
Epoch 1 Batch 0 Loss 9.0325 Accuracy 0.0000 Epoch 1 Batch 50 Loss 8.9631 Accuracy 0.0029 Epoch 1 Batch 100 Loss 8.8625 Accuracy 0.0285 Epoch 1 Batch 150 Loss 8.7535 Accuracy 0.0396 Epoch 1 Batch 200 Loss 8.6247 Accuracy 0.0465 Epoch 1 Batch 250 Loss 8.4712 Accuracy 0.0555 Epoch 1 Batch 300 Loss 8.2956 Accuracy 0.0660 Epoch 1 Batch 350 Loss 8.1095 Accuracy 0.0753 Epoch 1 Batch 400 Loss 7.9295 Accuracy 0.0823 Epoch 1 Batch 450 Loss 7.7644 Accuracy 0.0879 Epoch 1 Batch 500 Loss 7.6171 Accuracy 0.0927 Epoch 1 Batch 550 Loss 7.4840 Accuracy 0.0983 Epoch 1 Batch 600 Loss 7.3578 Accuracy 0.1048 Epoch 1 Batch 650 Loss 7.2364 Accuracy 0.1117 Epoch 1 Batch 700 Loss 7.1232 Accuracy 0.1185 Epoch 1 Loss 7.1188 Accuracy 0.1187 Time taken for 1 epoch: 54.0901415348053 secs Epoch 2 Batch 0 Loss 5.5828 Accuracy 0.1969 Epoch 2 Batch 50 Loss 5.4646 Accuracy 0.2218 Epoch 2 Batch 100 Loss 5.4122 Accuracy 0.2249 Epoch 2 Batch 150 Loss 5.3780 Accuracy 0.2278 Epoch 2 Batch 200 Loss 5.3342 Accuracy 0.2315 Epoch 2 Batch 250 Loss 5.2924 Accuracy 0.2352 Epoch 2 Batch 300 Loss 5.2508 Accuracy 0.2393 Epoch 2 Batch 350 Loss 5.2157 Accuracy 0.2424 Epoch 2 Batch 400 Loss 5.1816 Accuracy 0.2459 Epoch 2 Batch 450 Loss 5.1515 Accuracy 0.2492 Epoch 2 Batch 500 Loss 5.1203 Accuracy 0.2523 Epoch 2 Batch 550 Loss 5.0920 Accuracy 0.2552 Epoch 2 Batch 600 Loss 5.0661 Accuracy 0.2579 Epoch 2 Batch 650 Loss 5.0418 Accuracy 0.2604 Epoch 2 Batch 700 Loss 5.0186 Accuracy 0.2627 Epoch 2 Loss 5.0179 Accuracy 0.2628 Time taken for 1 epoch: 30.69964909553528 secs Epoch 3 Batch 0 Loss 4.6354 Accuracy 0.3023 Epoch 3 Batch 50 Loss 4.6234 Accuracy 0.3012 Epoch 3 Batch 100 Loss 4.6082 Accuracy 0.3021 Epoch 3 Batch 150 Loss 4.6073 Accuracy 0.3030 Epoch 3 Batch 200 Loss 4.5980 Accuracy 0.3043 Epoch 3 Batch 250 Loss 4.5887 Accuracy 0.3054 Epoch 3 Batch 300 Loss 4.5753 Accuracy 0.3069 Epoch 3 Batch 350 Loss 4.5617 Accuracy 0.3084 Epoch 3 Batch 400 Loss 4.5476 Accuracy 0.3099 Epoch 3 Batch 450 Loss 4.5342 Accuracy 0.3112 Epoch 3 Batch 500 Loss 4.5243 Accuracy 0.3122 Epoch 3 Batch 550 Loss 4.5141 Accuracy 0.3134 Epoch 3 Batch 600 Loss 4.5010 Accuracy 0.3148 Epoch 3 Batch 650 Loss 4.4917 Accuracy 0.3158 Epoch 3 Batch 700 Loss 4.4797 Accuracy 0.3170 Epoch 3 Loss 4.4795 Accuracy 0.3170 Time taken for 1 epoch: 30.95038342475891 secs Epoch 4 Batch 0 Loss 3.9974 Accuracy 0.3544 Epoch 4 Batch 50 Loss 4.2098 Accuracy 0.3431 Epoch 4 Batch 100 Loss 4.1827 Accuracy 0.3466 Epoch 4 Batch 150 Loss 4.1836 Accuracy 0.3471 Epoch 4 Batch 200 Loss 4.1799 Accuracy 0.3473 Epoch 4 Batch 250 Loss 4.1675 Accuracy 0.3486 Epoch 4 Batch 300 Loss 4.1581 Accuracy 0.3501 Epoch 4 Batch 350 Loss 4.1447 Accuracy 0.3516 Epoch 4 Batch 400 Loss 4.1289 Accuracy 0.3538 Epoch 4 Batch 450 Loss 4.1132 Accuracy 0.3559 Epoch 4 Batch 500 Loss 4.0977 Accuracy 0.3581 Epoch 4 Batch 550 Loss 4.0811 Accuracy 0.3601 Epoch 4 Batch 600 Loss 4.0648 Accuracy 0.3623 Epoch 4 Batch 650 Loss 4.0508 Accuracy 0.3644 Epoch 4 Batch 700 Loss 4.0378 Accuracy 0.3662 Epoch 4 Loss 4.0372 Accuracy 0.3663 Time taken for 1 epoch: 30.76306676864624 secs Epoch 5 Batch 0 Loss 3.7628 Accuracy 0.3862 Epoch 5 Batch 50 Loss 3.7014 Accuracy 0.4030 Epoch 5 Batch 100 Loss 3.6951 Accuracy 0.4051 Epoch 5 Batch 150 Loss 3.6715 Accuracy 0.4084 Epoch 5 Batch 200 Loss 3.6619 Accuracy 0.4105 Epoch 5 Batch 250 Loss 3.6462 Accuracy 0.4131 Epoch 5 Batch 300 Loss 3.6403 Accuracy 0.4145 Epoch 5 Batch 350 Loss 3.6238 Accuracy 0.4168 Epoch 5 Batch 400 Loss 3.6115 Accuracy 0.4186 Epoch 5 Batch 450 Loss 3.5990 Accuracy 0.4200 Epoch 5 Batch 500 Loss 3.5902 Accuracy 0.4215 Epoch 5 Batch 550 Loss 3.5806 Accuracy 0.4228 Epoch 5 Batch 600 Loss 3.5705 Accuracy 0.4240 Epoch 5 Batch 650 Loss 3.5612 Accuracy 0.4252 Epoch 5 Batch 700 Loss 3.5494 Accuracy 0.4267 Saving checkpoint for epoch 5 at ./checkpoints/train/ckpt-1 Epoch 5 Loss 3.5493 Accuracy 0.4267 Time taken for 1 epoch: 31.12636709213257 secs Epoch 6 Batch 0 Loss 3.2444 Accuracy 0.4605 Epoch 6 Batch 50 Loss 3.2155 Accuracy 0.4619 Epoch 6 Batch 100 Loss 3.2090 Accuracy 0.4631 Epoch 6 Batch 150 Loss 3.2024 Accuracy 0.4633 Epoch 6 Batch 200 Loss 3.1966 Accuracy 0.4648 Epoch 6 Batch 250 Loss 3.1929 Accuracy 0.4655 Epoch 6 Batch 300 Loss 3.1881 Accuracy 0.4664 Epoch 6 Batch 350 Loss 3.1832 Accuracy 0.4674 Epoch 6 Batch 400 Loss 3.1761 Accuracy 0.4685 Epoch 6 Batch 450 Loss 3.1699 Accuracy 0.4688 Epoch 6 Batch 500 Loss 3.1650 Accuracy 0.4696 Epoch 6 Batch 550 Loss 3.1592 Accuracy 0.4705 Epoch 6 Batch 600 Loss 3.1530 Accuracy 0.4717 Epoch 6 Batch 650 Loss 3.1471 Accuracy 0.4723 Epoch 6 Batch 700 Loss 3.1409 Accuracy 0.4731 Epoch 6 Loss 3.1406 Accuracy 0.4731 Time taken for 1 epoch: 30.89075517654419 secs Epoch 7 Batch 0 Loss 2.7938 Accuracy 0.5259 Epoch 7 Batch 50 Loss 2.8191 Accuracy 0.5065 Epoch 7 Batch 100 Loss 2.8050 Accuracy 0.5093 Epoch 7 Batch 150 Loss 2.8151 Accuracy 0.5085 Epoch 7 Batch 200 Loss 2.8113 Accuracy 0.5093 Epoch 7 Batch 250 Loss 2.8064 Accuracy 0.5101 Epoch 7 Batch 300 Loss 2.8001 Accuracy 0.5109 Epoch 7 Batch 350 Loss 2.7923 Accuracy 0.5123 Epoch 7 Batch 400 Loss 2.7791 Accuracy 0.5138 Epoch 7 Batch 450 Loss 2.7733 Accuracy 0.5146 Epoch 7 Batch 500 Loss 2.7688 Accuracy 0.5154 Epoch 7 Batch 550 Loss 2.7602 Accuracy 0.5166 Epoch 7 Batch 600 Loss 2.7542 Accuracy 0.5175 Epoch 7 Batch 650 Loss 2.7497 Accuracy 0.5184 Epoch 7 Batch 700 Loss 2.7439 Accuracy 0.5193 Epoch 7 Loss 2.7436 Accuracy 0.5194 Time taken for 1 epoch: 31.79271173477173 secs Epoch 8 Batch 0 Loss 2.5171 Accuracy 0.5501 Epoch 8 Batch 50 Loss 2.4147 Accuracy 0.5562 Epoch 8 Batch 100 Loss 2.4221 Accuracy 0.5555 Epoch 8 Batch 150 Loss 2.4131 Accuracy 0.5580 Epoch 8 Batch 200 Loss 2.4173 Accuracy 0.5570 Epoch 8 Batch 250 Loss 2.4214 Accuracy 0.5569 Epoch 8 Batch 300 Loss 2.4305 Accuracy 0.5555 Epoch 8 Batch 350 Loss 2.4305 Accuracy 0.5555 Epoch 8 Batch 400 Loss 2.4273 Accuracy 0.5560 Epoch 8 Batch 450 Loss 2.4261 Accuracy 0.5563 Epoch 8 Batch 500 Loss 2.4245 Accuracy 0.5567 Epoch 8 Batch 550 Loss 2.4233 Accuracy 0.5572 Epoch 8 Batch 600 Loss 2.4182 Accuracy 0.5582 Epoch 8 Batch 650 Loss 2.4162 Accuracy 0.5585 Epoch 8 Batch 700 Loss 2.4147 Accuracy 0.5589 Epoch 8 Loss 2.4139 Accuracy 0.5590 Time taken for 1 epoch: 31.114221572875977 secs Epoch 9 Batch 0 Loss 2.0796 Accuracy 0.6034 Epoch 9 Batch 50 Loss 2.1062 Accuracy 0.5978 Epoch 9 Batch 100 Loss 2.1268 Accuracy 0.5934 Epoch 9 Batch 150 Loss 2.1465 Accuracy 0.5914 Epoch 9 Batch 200 Loss 2.1525 Accuracy 0.5908 Epoch 9 Batch 250 Loss 2.1578 Accuracy 0.5902 Epoch 9 Batch 300 Loss 2.1590 Accuracy 0.5899 Epoch 9 Batch 350 Loss 2.1592 Accuracy 0.5898 Epoch 9 Batch 400 Loss 2.1598 Accuracy 0.5899 Epoch 9 Batch 450 Loss 2.1614 Accuracy 0.5898 Epoch 9 Batch 500 Loss 2.1632 Accuracy 0.5897 Epoch 9 Batch 550 Loss 2.1625 Accuracy 0.5899 Epoch 9 Batch 600 Loss 2.1655 Accuracy 0.5897 Epoch 9 Batch 650 Loss 2.1659 Accuracy 0.5896 Epoch 9 Batch 700 Loss 2.1671 Accuracy 0.5896 Epoch 9 Loss 2.1671 Accuracy 0.5896 Time taken for 1 epoch: 31.18158221244812 secs Epoch 10 Batch 0 Loss 1.8438 Accuracy 0.6431 Epoch 10 Batch 50 Loss 1.9301 Accuracy 0.6210 Epoch 10 Batch 100 Loss 1.9432 Accuracy 0.6182 Epoch 10 Batch 150 Loss 1.9503 Accuracy 0.6175 Epoch 10 Batch 200 Loss 1.9521 Accuracy 0.6180 Epoch 10 Batch 250 Loss 1.9540 Accuracy 0.6173 Epoch 10 Batch 300 Loss 1.9551 Accuracy 0.6174 Epoch 10 Batch 350 Loss 1.9615 Accuracy 0.6167 Epoch 10 Batch 400 Loss 1.9619 Accuracy 0.6165 Epoch 10 Batch 450 Loss 1.9636 Accuracy 0.6167 Epoch 10 Batch 500 Loss 1.9685 Accuracy 0.6160 Epoch 10 Batch 550 Loss 1.9700 Accuracy 0.6159 Epoch 10 Batch 600 Loss 1.9750 Accuracy 0.6153 Epoch 10 Batch 650 Loss 1.9787 Accuracy 0.6150 Epoch 10 Batch 700 Loss 1.9803 Accuracy 0.6147 Saving checkpoint for epoch 10 at ./checkpoints/train/ckpt-2 Epoch 10 Loss 1.9804 Accuracy 0.6147 Time taken for 1 epoch: 31.05565071105957 secs Epoch 11 Batch 0 Loss 1.6855 Accuracy 0.6649 Epoch 11 Batch 50 Loss 1.7798 Accuracy 0.6409 Epoch 11 Batch 100 Loss 1.7849 Accuracy 0.6394 Epoch 11 Batch 150 Loss 1.7887 Accuracy 0.6387 Epoch 11 Batch 200 Loss 1.7986 Accuracy 0.6376 Epoch 11 Batch 250 Loss 1.8039 Accuracy 0.6371 Epoch 11 Batch 300 Loss 1.8087 Accuracy 0.6361 Epoch 11 Batch 350 Loss 1.8122 Accuracy 0.6354 Epoch 11 Batch 400 Loss 1.8157 Accuracy 0.6352 Epoch 11 Batch 450 Loss 1.8157 Accuracy 0.6352 Epoch 11 Batch 500 Loss 1.8214 Accuracy 0.6344 Epoch 11 Batch 550 Loss 1.8249 Accuracy 0.6340 Epoch 11 Batch 600 Loss 1.8275 Accuracy 0.6339 Epoch 11 Batch 650 Loss 1.8327 Accuracy 0.6333 Epoch 11 Batch 700 Loss 1.8357 Accuracy 0.6329 Epoch 11 Loss 1.8357 Accuracy 0.6329 Time taken for 1 epoch: 31.027227878570557 secs Epoch 12 Batch 0 Loss 1.6143 Accuracy 0.6664 Epoch 12 Batch 50 Loss 1.6444 Accuracy 0.6597 Epoch 12 Batch 100 Loss 1.6483 Accuracy 0.6591 Epoch 12 Batch 150 Loss 1.6596 Accuracy 0.6571 Epoch 12 Batch 200 Loss 1.6646 Accuracy 0.6567 Epoch 12 Batch 250 Loss 1.6728 Accuracy 0.6555 Epoch 12 Batch 300 Loss 1.6742 Accuracy 0.6554 Epoch 12 Batch 350 Loss 1.6771 Accuracy 0.6547 Epoch 12 Batch 400 Loss 1.6812 Accuracy 0.6543 Epoch 12 Batch 450 Loss 1.6868 Accuracy 0.6532 Epoch 12 Batch 500 Loss 1.6895 Accuracy 0.6529 Epoch 12 Batch 550 Loss 1.6949 Accuracy 0.6522 Epoch 12 Batch 600 Loss 1.7010 Accuracy 0.6515 Epoch 12 Batch 650 Loss 1.7086 Accuracy 0.6504 Epoch 12 Batch 700 Loss 1.7139 Accuracy 0.6499 Epoch 12 Loss 1.7141 Accuracy 0.6499 Time taken for 1 epoch: 30.62126898765564 secs Epoch 13 Batch 0 Loss 1.4501 Accuracy 0.6824 Epoch 13 Batch 50 Loss 1.5419 Accuracy 0.6747 Epoch 13 Batch 100 Loss 1.5441 Accuracy 0.6730 Epoch 13 Batch 150 Loss 1.5583 Accuracy 0.6700 Epoch 13 Batch 200 Loss 1.5641 Accuracy 0.6695 Epoch 13 Batch 250 Loss 1.5682 Accuracy 0.6690 Epoch 13 Batch 300 Loss 1.5721 Accuracy 0.6683 Epoch 13 Batch 350 Loss 1.5766 Accuracy 0.6680 Epoch 13 Batch 400 Loss 1.5813 Accuracy 0.6676 Epoch 13 Batch 450 Loss 1.5896 Accuracy 0.6664 Epoch 13 Batch 500 Loss 1.5922 Accuracy 0.6661 Epoch 13 Batch 550 Loss 1.5978 Accuracy 0.6654 Epoch 13 Batch 600 Loss 1.6030 Accuracy 0.6646 Epoch 13 Batch 650 Loss 1.6082 Accuracy 0.6639 Epoch 13 Batch 700 Loss 1.6134 Accuracy 0.6633 Epoch 13 Loss 1.6134 Accuracy 0.6634 Time taken for 1 epoch: 30.817842721939087 secs Epoch 14 Batch 0 Loss 1.3038 Accuracy 0.7251 Epoch 14 Batch 50 Loss 1.4288 Accuracy 0.6897 Epoch 14 Batch 100 Loss 1.4507 Accuracy 0.6881 Epoch 14 Batch 150 Loss 1.4641 Accuracy 0.6851 Epoch 14 Batch 200 Loss 1.4735 Accuracy 0.6847 Epoch 14 Batch 250 Loss 1.4773 Accuracy 0.6839 Epoch 14 Batch 300 Loss 1.4825 Accuracy 0.6828 Epoch 14 Batch 350 Loss 1.4890 Accuracy 0.6819 Epoch 14 Batch 400 Loss 1.4937 Accuracy 0.6808 Epoch 14 Batch 450 Loss 1.4998 Accuracy 0.6798 Epoch 14 Batch 500 Loss 1.5044 Accuracy 0.6792 Epoch 14 Batch 550 Loss 1.5087 Accuracy 0.6785 Epoch 14 Batch 600 Loss 1.5150 Accuracy 0.6773 Epoch 14 Batch 650 Loss 1.5209 Accuracy 0.6766 Epoch 14 Batch 700 Loss 1.5267 Accuracy 0.6759 Epoch 14 Loss 1.5264 Accuracy 0.6760 Time taken for 1 epoch: 30.76487922668457 secs Epoch 15 Batch 0 Loss 1.3602 Accuracy 0.7020 Epoch 15 Batch 50 Loss 1.3786 Accuracy 0.6978 Epoch 15 Batch 100 Loss 1.3675 Accuracy 0.6994 Epoch 15 Batch 150 Loss 1.3881 Accuracy 0.6961 Epoch 15 Batch 200 Loss 1.3986 Accuracy 0.6947 Epoch 15 Batch 250 Loss 1.4042 Accuracy 0.6937 Epoch 15 Batch 300 Loss 1.4095 Accuracy 0.6929 Epoch 15 Batch 350 Loss 1.4175 Accuracy 0.6917 Epoch 15 Batch 400 Loss 1.4202 Accuracy 0.6913 Epoch 15 Batch 450 Loss 1.4256 Accuracy 0.6906 Epoch 15 Batch 500 Loss 1.4271 Accuracy 0.6904 Epoch 15 Batch 550 Loss 1.4337 Accuracy 0.6895 Epoch 15 Batch 600 Loss 1.4401 Accuracy 0.6885 Epoch 15 Batch 650 Loss 1.4460 Accuracy 0.6876 Epoch 15 Batch 700 Loss 1.4515 Accuracy 0.6868 Saving checkpoint for epoch 15 at ./checkpoints/train/ckpt-3 Epoch 15 Loss 1.4519 Accuracy 0.6868 Time taken for 1 epoch: 30.835017681121826 secs Epoch 16 Batch 0 Loss 1.1559 Accuracy 0.7455 Epoch 16 Batch 50 Loss 1.2853 Accuracy 0.7131 Epoch 16 Batch 100 Loss 1.3070 Accuracy 0.7094 Epoch 16 Batch 150 Loss 1.3140 Accuracy 0.7080 Epoch 16 Batch 200 Loss 1.3281 Accuracy 0.7059 Epoch 16 Batch 250 Loss 1.3378 Accuracy 0.7040 Epoch 16 Batch 300 Loss 1.3457 Accuracy 0.7029 Epoch 16 Batch 350 Loss 1.3470 Accuracy 0.7029 Epoch 16 Batch 400 Loss 1.3514 Accuracy 0.7023 Epoch 16 Batch 450 Loss 1.3575 Accuracy 0.7011 Epoch 16 Batch 500 Loss 1.3623 Accuracy 0.7004 Epoch 16 Batch 550 Loss 1.3688 Accuracy 0.6993 Epoch 16 Batch 600 Loss 1.3738 Accuracy 0.6985 Epoch 16 Batch 650 Loss 1.3789 Accuracy 0.6978 Epoch 16 Batch 700 Loss 1.3835 Accuracy 0.6972 Epoch 16 Loss 1.3842 Accuracy 0.6970 Time taken for 1 epoch: 30.86835026741028 secs Epoch 17 Batch 0 Loss 1.1976 Accuracy 0.7252 Epoch 17 Batch 50 Loss 1.2320 Accuracy 0.7229 Epoch 17 Batch 100 Loss 1.2459 Accuracy 0.7198 Epoch 17 Batch 150 Loss 1.2615 Accuracy 0.7170 Epoch 17 Batch 200 Loss 1.2671 Accuracy 0.7155 Epoch 17 Batch 250 Loss 1.2781 Accuracy 0.7137 Epoch 17 Batch 300 Loss 1.2837 Accuracy 0.7124 Epoch 17 Batch 350 Loss 1.2856 Accuracy 0.7121 Epoch 17 Batch 400 Loss 1.2926 Accuracy 0.7109 Epoch 17 Batch 450 Loss 1.2976 Accuracy 0.7103 Epoch 17 Batch 500 Loss 1.3044 Accuracy 0.7092 Epoch 17 Batch 550 Loss 1.3103 Accuracy 0.7080 Epoch 17 Batch 600 Loss 1.3158 Accuracy 0.7072 Epoch 17 Batch 650 Loss 1.3188 Accuracy 0.7069 Epoch 17 Batch 700 Loss 1.3237 Accuracy 0.7062 Epoch 17 Loss 1.3240 Accuracy 0.7062 Time taken for 1 epoch: 31.70491647720337 secs Epoch 18 Batch 0 Loss 1.3016 Accuracy 0.7197 Epoch 18 Batch 50 Loss 1.1798 Accuracy 0.7305 Epoch 18 Batch 100 Loss 1.1901 Accuracy 0.7291 Epoch 18 Batch 150 Loss 1.1978 Accuracy 0.7277 Epoch 18 Batch 200 Loss 1.2066 Accuracy 0.7257 Epoch 18 Batch 250 Loss 1.2141 Accuracy 0.7243 Epoch 18 Batch 300 Loss 1.2225 Accuracy 0.7227 Epoch 18 Batch 350 Loss 1.2288 Accuracy 0.7215 Epoch 18 Batch 400 Loss 1.2353 Accuracy 0.7203 Epoch 18 Batch 450 Loss 1.2398 Accuracy 0.7195 Epoch 18 Batch 500 Loss 1.2441 Accuracy 0.7186 Epoch 18 Batch 550 Loss 1.2516 Accuracy 0.7174 Epoch 18 Batch 600 Loss 1.2581 Accuracy 0.7164 Epoch 18 Batch 650 Loss 1.2648 Accuracy 0.7154 Epoch 18 Batch 700 Loss 1.2693 Accuracy 0.7148 Epoch 18 Loss 1.2694 Accuracy 0.7148 Time taken for 1 epoch: 30.78923749923706 secs Epoch 19 Batch 0 Loss 1.0897 Accuracy 0.7513 Epoch 19 Batch 50 Loss 1.1161 Accuracy 0.7400 Epoch 19 Batch 100 Loss 1.1371 Accuracy 0.7369 Epoch 19 Batch 150 Loss 1.1537 Accuracy 0.7339 Epoch 19 Batch 200 Loss 1.1645 Accuracy 0.7322 Epoch 19 Batch 250 Loss 1.1728 Accuracy 0.7307 Epoch 19 Batch 300 Loss 1.1812 Accuracy 0.7293 Epoch 19 Batch 350 Loss 1.1851 Accuracy 0.7283 Epoch 19 Batch 400 Loss 1.1890 Accuracy 0.7277 Epoch 19 Batch 450 Loss 1.1922 Accuracy 0.7273 Epoch 19 Batch 500 Loss 1.1964 Accuracy 0.7265 Epoch 19 Batch 550 Loss 1.2038 Accuracy 0.7251 Epoch 19 Batch 600 Loss 1.2107 Accuracy 0.7238 Epoch 19 Batch 650 Loss 1.2152 Accuracy 0.7232 Epoch 19 Batch 700 Loss 1.2193 Accuracy 0.7224 Epoch 19 Loss 1.2199 Accuracy 0.7223 Time taken for 1 epoch: 31.050918340682983 secs Epoch 20 Batch 0 Loss 1.0248 Accuracy 0.7491 Epoch 20 Batch 50 Loss 1.1020 Accuracy 0.7435 Epoch 20 Batch 100 Loss 1.1042 Accuracy 0.7420 Epoch 20 Batch 150 Loss 1.1102 Accuracy 0.7407 Epoch 20 Batch 200 Loss 1.1199 Accuracy 0.7385 Epoch 20 Batch 250 Loss 1.1271 Accuracy 0.7371 Epoch 20 Batch 300 Loss 1.1352 Accuracy 0.7358 Epoch 20 Batch 350 Loss 1.1401 Accuracy 0.7349 Epoch 20 Batch 400 Loss 1.1419 Accuracy 0.7348 Epoch 20 Batch 450 Loss 1.1476 Accuracy 0.7338 Epoch 20 Batch 500 Loss 1.1544 Accuracy 0.7325 Epoch 20 Batch 550 Loss 1.1585 Accuracy 0.7320 Epoch 20 Batch 600 Loss 1.1650 Accuracy 0.7309 Epoch 20 Batch 650 Loss 1.1699 Accuracy 0.7301 Epoch 20 Batch 700 Loss 1.1764 Accuracy 0.7291 Saving checkpoint for epoch 20 at ./checkpoints/train/ckpt-4 Epoch 20 Loss 1.1765 Accuracy 0.7290 Time taken for 1 epoch: 30.766892671585083 secs
평가
평가에는 다음 단계가 사용됩니다.
- 포르투갈어 토크 나이저 (
tokenizer_pt
)를 사용하여 입력 문장을 인코딩합니다. 또한 입력이 모델이 학습 된 것과 동일하도록 시작 및 종료 토큰을 추가하십시오. 이것은 인코더 입력입니다. - 디코더 입력은
start token == tokenizer_en.vocab_size
입니다. - 패딩 마스크와 미리보기 마스크를 계산합니다.
- 그런 다음
decoder
는encoder output
과 자체 출력 (자기주의)을보고 예측을 출력합니다. - 마지막 단어를 선택하고 그 argmax를 계산하십시오.
- 예측 된 단어를 디코더에 전달할 때 디코더 입력에 연결합니다.
- 이 접근 방식에서 디코더는 예측 한 이전 단어를 기반으로 다음 단어를 예측합니다.
def evaluate(inp_sentence):
start_token = [tokenizer_pt.vocab_size]
end_token = [tokenizer_pt.vocab_size + 1]
# inp sentence is portuguese, hence adding the start and end token
inp_sentence = start_token + tokenizer_pt.encode(inp_sentence) + end_token
encoder_input = tf.expand_dims(inp_sentence, 0)
# as the target is english, the first word to the transformer should be the
# english start token.
decoder_input = [tokenizer_en.vocab_size]
output = tf.expand_dims(decoder_input, 0)
for i in range(MAX_LENGTH):
enc_padding_mask, combined_mask, dec_padding_mask = create_masks(
encoder_input, output)
# predictions.shape == (batch_size, seq_len, vocab_size)
predictions, attention_weights = transformer(encoder_input,
output,
False,
enc_padding_mask,
combined_mask,
dec_padding_mask)
# select the last word from the seq_len dimension
predictions = predictions[: ,-1:, :] # (batch_size, 1, vocab_size)
predicted_id = tf.cast(tf.argmax(predictions, axis=-1), tf.int32)
# return the result if the predicted_id is equal to the end token
if predicted_id == tokenizer_en.vocab_size+1:
return tf.squeeze(output, axis=0), attention_weights
# concatentate the predicted_id to the output which is given to the decoder
# as its input.
output = tf.concat([output, predicted_id], axis=-1)
return tf.squeeze(output, axis=0), attention_weights
def plot_attention_weights(attention, sentence, result, layer):
fig = plt.figure(figsize=(16, 8))
sentence = tokenizer_pt.encode(sentence)
attention = tf.squeeze(attention[layer], axis=0)
for head in range(attention.shape[0]):
ax = fig.add_subplot(2, 4, head+1)
# plot the attention weights
ax.matshow(attention[head][:-1, :], cmap='viridis')
fontdict = {'fontsize': 10}
ax.set_xticks(range(len(sentence)+2))
ax.set_yticks(range(len(result)))
ax.set_ylim(len(result)-1.5, -0.5)
ax.set_xticklabels(
['<start>']+[tokenizer_pt.decode([i]) for i in sentence]+['<end>'],
fontdict=fontdict, rotation=90)
ax.set_yticklabels([tokenizer_en.decode([i]) for i in result
if i < tokenizer_en.vocab_size],
fontdict=fontdict)
ax.set_xlabel('Head {}'.format(head+1))
plt.tight_layout()
plt.show()
def translate(sentence, plot=''):
result, attention_weights = evaluate(sentence)
predicted_sentence = tokenizer_en.decode([i for i in result
if i < tokenizer_en.vocab_size])
print('Input: {}'.format(sentence))
print('Predicted translation: {}'.format(predicted_sentence))
if plot:
plot_attention_weights(attention_weights, sentence, result, plot)
translate("este é um problema que temos que resolver.")
print ("Real translation: this is a problem we have to solve .")
Input: este é um problema que temos que resolver. Predicted translation: this is a problem that we have to solve one . Real translation: this is a problem we have to solve .
translate("os meus vizinhos ouviram sobre esta ideia.")
print ("Real translation: and my neighboring homes heard about this idea .")
Input: os meus vizinhos ouviram sobre esta ideia. Predicted translation: my neighbors heard about this idea . Real translation: and my neighboring homes heard about this idea .
translate("vou então muito rapidamente partilhar convosco algumas histórias de algumas coisas mágicas que aconteceram.")
print ("Real translation: so i 'll just share with you some stories very quickly of some magical things that have happened .")
Input: vou então muito rapidamente partilhar convosco algumas histórias de algumas coisas mágicas que aconteceram. Predicted translation: so i 'm going to really quickly share with you some magic stories that happened to happen . Real translation: so i 'll just share with you some stories very quickly of some magical things that have happened .
디코더의 다른 레이어와주의 블록을 plot
매개 변수에 전달할 수 있습니다.
translate("este é o primeiro livro que eu fiz.", plot='decoder_layer4_block2')
print ("Real translation: this is the first book i've ever done.")
Input: este é o primeiro livro que eu fiz. Predicted translation: this is the first book i made .
Real translation: this is the first book i've ever done.
요약
이 자습서에서는 위치 인코딩, 다중 머리주의, 마스킹의 중요성 및 변환기를 만드는 방법에 대해 배웠습니다.
다른 데이터 세트를 사용하여 변환기를 훈련 시키십시오. 위의 하이퍼 파라미터를 변경하여 기본 트랜스포머 또는 트랜스포머 XL을 생성 할 수도 있습니다. 여기에 정의 된 레이어를 사용하여 BERT 를 만들고 최첨단 모델을 학습 할 수도 있습니다. 또한 빔 검색을 구현하여 더 나은 예측을 얻을 수 있습니다.