NLP中的transformer实现

Transformer自注意力机制详解 然后,对每一组查询向量Qi、键向量Ki和值向量Vi分别进行上述自注意力机制的计算过程,得到h个不同的注意力输出Zi。其中,qi表示第i个位置的查询向量,kiT表示第j个位置的键向量的转置,dk表示键向量的维度大小。通过计算查询向量和所有其他位置的键向量之间的点积,并除以缩放因子,我们可以得到一个注意力分数矩阵attn_scores,其中每个元素表示两个位置之间的相似度。自注意力机制的计算过程主要包括以下几个步骤:生成查询向量、键向量和值向量,计算注意力分数,计算注意力权重,以及计算注意力输出。 阅读详情
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
import sklearn
import numpy as np
import pandas as pd
import os
import sys
import time
import tensorflow as tf
from tensorflow import keras
print(tf.__version__)
print(sys.version_info)
2.0.0
sys.version_info(major=3, minor=6, micro=10, releaselevel='final', serial=0)
for i in mpl,np,pd,sklearn,tf,keras:
    print(i.__name__,i.__version__)
matplotlib 3.1.3
numpy 1.18.1
pandas 1.0.3
sklearn 0.22.1
tensorflow 2.0.0
tensorflow_core.keras 2.2.4-tf
import tensorflow_datasets as tfds
examples, info = tfds.load(name = 'ted_hrlr_translate/pt_to_en',shuffle_files=True, with_info=True,as_supervised=True)
train_examples, val_examples = examples['train'], examples['validation']
print(info)
tfds.core.DatasetInfo(
    name='ted_hrlr_translate',
    version=0.0.1,
    description='Data sets derived from TED talk transcripts for comparing similar language pairs
where one is high resource and the other is low resource.
',
    urls=['https://github.com/neulab/word-embeddings-for-nmt'],
    features=Translation({
        'en': Text(shape=(), dtype=tf.string),
        'pt': Text(shape=(), dtype=tf.string),
    }),
    total_num_examples=54781,
    splits={
        'test': 1803,
        'train': 51785,
        'validation': 1193,
    },
    supervised_keys=('pt', 'en'),
    citation="""@inproceedings{Ye2018WordEmbeddings,
      author  = {Ye, Qi and Devendra, Sachan and Matthieu, Felix and Sarguna, Padmanabhan and Graham, Neubig},
      title   = {When and Why are pre-trained word embeddings useful for Neural Machine Translation},
      booktitle = {HLT-NAACL},
      year    = {2018},
      }""",
    redistribution_info=,
)
for pt,en in train_examples.take(5):
    print(pt.numpy())
    print(en.numpy())
    print()
b'os astr\xc3\xb3nomos acreditam que cada estrela da gal\xc3\xa1xia tem um planeta , e especulam que at\xc3\xa9 um quinto deles tem um planeta do tipo da terra que poder\xc3\xa1 ter vida , mas ainda n\xc3\xa3o vimos nenhum deles .'
b"astronomers now believe that every star in the galaxy has a planet , and they speculate that up to one fifth of them have an earth-like planet that might be able to harbor life , but we have n't seen any of them ."

b'o problema \xc3\xa9 que nunca vivi l\xc3\xa1 um \xc3\xbanico dia .'
b"except , i 've never lived one day of my life there ."

b'agora aqui temos imagens sendo extra\xc3\xaddas em tempo real diretamente do feed ,'
b'now here are live images being pulled straight from the feed .'

b'agora : um , dois , tr\xc3\xaas , vai .'
b'so : one , two , three , go .'

b'eventualmente , vamos ver se teremos todos os sentidos humanos empregues , e se vamos ter meios para viver a hist\xc3\xb3ria qualquer que seja a via escolhida .'
b'eventually , we can see if we will have all of our human senses employed , and we will have agency to live the story in any path we choose .'

将数据转化为subwords格式

tokenizer_en = tfds.features.text.SubwordTextEncoder.build_from_corpus(
    (en.numpy() for pt,en in train_examples),target_vocab_size=2**13)
tokenizer_pt = tfds.features.text.SubwordTextEncoder.build_from_corpus(
    (pt.numpy() for pt, en in train_examples), target_vocab_size=2**13)
en_tokenizer = tokenizer_en
pt_tokenizer = tokenizer_pt
sample_string = 'hello world, tensorflow 2'
tokenizer_string  = en_tokenizer.encode(sample_string)
tokenizer_string
[3222, 439, 150, 7345, 1378, 2824, 2370, 7881]
orgin_string = en_tokenizer.decode(tokenizer_string)
orgin_string
'hello world, tensorflow 2'
assert orgin_string == sample_string
for token in tokenizer_string:
    print('{}-->"{}"'.format(token,en_tokenizer.decode([token])))
3222-->"hell"
439-->"o "
150-->"world"
7345-->", "
1378-->"ten"
2824-->"sor"
2370-->"flow "
7881-->"2"

添加start、end的token表示

buffer_size = 2000
batch_size = 64
max_lenth = 40

def encode_to_subword(pt_sentence,en_sentence): #把句子转换为subword之后的句子
    pt_sequence = [pt_tokenizer.vocab_size] \
    + pt_tokenizer.encode(pt_sentence.numpy()) \
    + [pt_tokenizer.vocab_size + 1]
    en_sentence = [en_tokenizer.vocab_size] \
    + en_tokenizer.encode(en_sentence.numpy()) \
    + [en_tokenizer.vocab_size + 1]
    return pt_sequence,en_sentence

过滤 长度低于40(max_lenth)的数据

def filter_by_max_lenth(pt,en):
    return tf.logical_and(tf.size(pt) <= max_lenth,
                          tf.size(en) <= max_lenth)

将python运算,转换为tensorflow运算节点

def tf_encode_to_subword(pt_sentence,en_sentence):
    return tf.py_function(encode_to_subword, #定义过的函数
                         [pt_sentence,en_sentence],
                         [tf.int64,tf.int64])

构造训练集

# 使用.map()运行相关图操作
train_dataset = train_examples.map(tf_encode_to_subword)
# 过滤过长的数据
train_dataset = train_dataset.filter(filter_by_max_lenth)
# 使用缓存数据加速读入
train_dataset = train_dataset.cache()
# 打乱并获取批数据
train_dataset = train_dataset.shuffle(
    buffer_size).padded_batch(
    batch_size, padded_shapes=([-1], [-1])) #padded_shapes有两个维度,每个维度都扩展到当前维度最大值
# 设置预取数据
train_dataset = train_dataset.prefetch(tf.data.experimental.AUTOTUNE)

构造测试集

valid_dataset = val_examples.map(tf_encode_to_subword)
valid_dataset = valid_dataset.filter(
    filter_by_max_lenth).padded_batch(
    batch_size, padded_shapes=([-1], [-1]))
for pt_batch,en_batch in valid_dataset.take(5):
    print(pt_batch.shape,en_batch.shape)
(64, 40) (64, 40)
(64, 38) (64, 40)
(64, 40) (64, 40)
(64, 39) (64, 39)
(64, 37) (64, 38)
de_batch, en_batch = next(iter(valid_dataset))
de_batch, en_batch
(<tf.Tensor: id=209188, shape=(64, 40), dtype=int64, numpy=
 array([[8214, 1259,    5, ...,    0,    0,    0],
        [8214,  299,   13, ...,    0,    0,    0],
        [8214,   59,    8, ...,    0,    0,    0],
        ...,
        [8214,   95,    3, ...,    0,    0,    0],
        [8214, 5157,    1, ...,    0,    0,    0],
        [8214, 4479, 7990, ...,    0,    0,    0]], dtype=int64)>,
 <tf.Tensor: id=209189, shape=(64, 40), dtype=int64, numpy=
 array([[8087,   18,   12, ...,    0,    0,    0],
        [8087,  634,   30, ...,    0,    0,    0],
        [8087,   16,   13, ...,    0,    0,    0],
        ...,
        [8087,   12,   20, ...,    0,    0,    0],
        [8087,   17, 4981, ...,    0,    0,    0],
        [8087,   12, 5453, ...,    0,    0,    0]], dtype=int64)>)

2.位置嵌入

将位置编码矢量添加得到词嵌入,相同位置的词嵌入将会更接近,但并不能直接编码相对位置

基于角度的位置编码方法如下:

PE(pos,2i)=sin(pos/100002i/dmodel)\Large{PE_{(pos, 2i)} = sin(pos / 10000^{2i / d_{model}})} PE(pos,2i)​=sin(pos/100002i/dmodel​)
PE(pos,2i+1)=cos(pos/100002i/dmodel)\Large{PE_{(pos, 2i+1)} = cos(pos / 10000^{2i / d_{model}})} PE(pos,2i+1)​=cos(pos/100002i/dmodel​)

# PE(pos,2i) = sin(pos/10000^(2i/d_model))
# PE(pos,2i+1) = cos(pos/10000^(2i/d_model))
# pos.shape[sentence_lenth,1]
#i.shape: [1,d_model]
# result.shape:[sentence_lenth,d_model]
# angle_rates.shape = i.shape
def get_angels(pos, i, d_model):# pos:词语在句子中的位置,i:词语在embedding 中的位置
    angle_rates = 1/np.power(10000,(2*(i//2))/np.float32(d_model))
    return pos * angle_rates
def get_position_embedding(sentence_lenth,d_model):#d_model:word_embedding的长度
    angle_rads = get_angels(np.arange(sentence_lenth)[:,np.newaxis],
                            np.arange(d_model)[np.newaxis,:],
                            d_model)
    #sines.shape:[sentence_lenth,d_model/2] 第二维只取了一半 shape减半
    #cosines.shape:[sentence_lenth,d_model/2]
    sines = np.sin(angle_rads[:, 0::2])#0:,表示1到最后 :2 每隔一个取一位
    # 第2i+1项使用cos
    cosines = np.cos(angle_rads[:, 1::2])
    # position_embedding.shape: [sentence_lenth,d_model]
    position_embedding = np.concatenate([sines, cosines], axis=-1)
    # position_embedding.shape: [1,sentence_lenth,d_model]
    position_embedding = position_embedding[np.newaxis, ...]
    
    return tf.cast(position_embedding,dtype=tf.float32)
position_embbeding = get_position_embedding(50,512)
position_embbeding.shape
TensorShape([1, 50, 512])
def plot_position_embedding(position_embedding):
    plt.pcolormesh(position_embbeding[0], cmap='RdBu')
    plt.xlabel('Depth')
    plt.xlim((0, 512))
    plt.ylabel('Position')
    plt.colorbar()
    plt.show() # 在这里左右边分别为原来2i 和 2i+1的特征

获得位置嵌入编码

plot_position_embedding(position_embbeding)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p7y44bLK-1590139711696)(output_35_0.png)]

# 1. padding mask, 2. look ahead 只能与之前的词语发生关系

#batch_data.shape :[batch_size,seq_len]
def create_padding_mask(batch_data):
    # 获取为0的padding项
    padding_mask = tf.cast(tf.math.equal(batch_data, 0), tf.float32) #比较是否相等
    #[batch_size,1,1,seq_len]
    # 扩充维度以便用于attention矩阵
    return padding_mask[:, 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: id=209203, 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)>
# mark 测试
create_padding_mask([[1,2,0,0,3],[3,4,5,0,0]])
<tf.Tensor: id=209211, shape=(2, 1, 1, 5), dtype=float32, numpy=
array([[[[0., 0., 1., 1., 0.]]],


       [[[0., 0., 0., 1., 1.]]]], dtype=float32)>

look-ahead mask 用于对未预测的token进行掩码

这意味着要预测第三个单词,只会使用第一个和第二个单词。

要预测第四个单词,仅使用第一个,第二个和第三个单词,依此类推。

#[[1,2,3], #1代表1和自己的attention,2代表1和自己后面的字的attention
# [4,5,6],
# [7,8,9]]  
# 把上三角置零即可
def create_look_ahead_mask(size):
    # 1 - 对角线和取下三角的全部对角线(-1->全部)
    # 这样就可以构造出每个时刻未预测token的掩码
    mask = 1 - tf.linalg.band_part(tf.ones((size, size)), -1, 0) # num_lower = -1时,下三角 keep,上三角置零
    return mask  # (seq_len, seq_len)
create_look_ahead_mask(3)
<tf.Tensor: id=209219, shape=(3, 3), dtype=float32, numpy=
array([[0., 1., 1.],
       [0., 0., 1.],
       [0., 0., 0.]], dtype=float32)>

4.Scaled dot product attention

进行attention计算的时候有3个输入 Q (query), K (key), V (value)。计算公式如下:
Attention(Q,K,V)=softmaxk(QKTdk)V\Large{Attention(Q, K, V) = softmax_k(\frac{QK^T}{\sqrt{d_k}}) V} Attention(Q,K,V)=softmaxk​(dk​​QKT​)V

点积注意力通过深度d_k的平方根进行缩放,因为较大的深度会使点积变大,由于使用softmax,会使梯度变小。
例如,考虑Q和K的均值为0且方差为1.它们的矩阵乘法的均值为0,方差为dk。我们使用dk的根用于缩放(而不是任何其他数字),因为Q和K的matmul应该具有0的均值和1的方差。

在这里我们将被掩码的token乘以-1e9(表示负无穷),这样softmax之后就为0,不对其他token产生影响。

q : shape == (…,seq_len_q,depth)
k : shape == (…,seq_len_k,depth)
v : shape == (…,seq_len_v,depth_v)
seq_len_k == seq_len_v
mask:shape == (…,seq_len_q,seq_len_k )

returns:

out_put:weighted sum
attention_weights : weights of attention
def scaled_dot_product_attention(q, k, v, mask):
    # query key 相乘获取匹配关系
    # matmul_qk.shape:(...,seq_len_q,seq_len_k)
    matmul_qk = tf.matmul(q, k, transpose_b=True) #第二个矩阵做转置
    
    # 使用dk进行缩放
    dk = tf.cast(tf.shape(k)[-1], tf.float32) #取出k的最后一维做为dk ,depth
    scaled_attention_logits = matmul_qk / tf.math.sqrt(dk) # logits:未经过softmax,
    #scaled_attention_logits.shape : (...,seq_len_q,seq_len_k)
    
    # 掩码
    if mask is not None:
        # 使得在softmax后趋近于0
        scaled_attention_logits += (mask * -1e9)
    
    #attention_weights.shape : (...,seq_len_q,seq_len_k)
    # 通过softmax获取attention权重
    attention_weights = tf.nn.softmax(
        scaled_attention_logits, axis=-1) #attention_weights.shape : (...,seq_len_q,seq_len_k)
    
    # attention 乘上value
    # seq_len_k == seq_len_v
    # output.shape:(...,seq_len_q,depth_v)
    output = tf.matmul(attention_weights, v) # (.., seq_len_v, depth)
    
    return output, attention_weights

调试函数

def print_scaled_dot_product_attention(q, k, v):
    temp_out, temp_att = scaled_dot_product_attention(
    q, k, v, None)
    print('attention weight:')
    print(temp_att)
    print('output:')
    print(temp_out)

q : shape == (…,seq_len_q,depth)
k : shape == (…,seq_len_k,depth)
v : shape == (…,seq_len_v,depth_v)
seq_len_k == seq_len_v
mask:shape == (…,seq_len_q,seq_len_k )

np.set_printoptions(suppress=True) # suppress是否压缩由科学计数法表示的浮点数
# precision : int, optional,float输出的精度,即小数点后维数,默认8
#threshold : int, optional,当数组数目过大时,设置显示几个数字,其余用省略号

temp_k = tf.constant([[10,0,0],
                      [0,10,0], 
                      [0,0,10],
                      [0,0,10]], dtype=tf.float32)  # (4, 3) k : shape == (...,seq_len_k,depth)

temp_v = tf.constant([[   1,0],
                      [  10,0],# 被取出
                      [ 100,5],
                      [1000,6]], dtype=tf.float32)  # (4, 2) v : shape == (...,seq_len_v,depth_v)
# 关注第2个key, 返回对应的value
temp_q1 = tf.constant([[0,10,0]], dtype=tf.float32)  #(1,3) q : shape == (...,seq_len_q,depth)
print_scaled_dot_product_attention(temp_q1, temp_k, temp_v)
# attention_weight : (...,seq_len_q,seq_len_k) 1,4
# output.shape:(...,seq_len_q,depth_v) 1,2
attention weight:
tf.Tensor([[0. 1. 0. 0.]], shape=(1, 4), dtype=float32)
output:
tf.Tensor([[10.  0.]], shape=(1, 2), dtype=float32)
# 关注重复的key(第3、4个), 返回对应的value(平均)
temp_q2 = tf.constant([[0,0,10]], dtype=tf.float32) #(1,3)
print_scaled_dot_product_attention(temp_q2, temp_k, temp_v)
attention weight:
tf.Tensor([[0.  0.  0.5 0.5]], shape=(1, 4), dtype=float32)
output:
tf.Tensor([[550.    5.5]], shape=(1, 2), dtype=float32)
# 关注第1、2个key, 返回对应的value(平均)
temp_q3 = tf.constant([[10,10,0]], dtype=tf.float32)
print_scaled_dot_product_attention(temp_q3, temp_k, temp_v)
attention weight:
tf.Tensor([[0.5 0.5 0.  0. ]], shape=(1, 4), dtype=float32)
output:
tf.Tensor([[5.5 0. ]], shape=(1, 2), dtype=float32)
# 依次放入每个query,q1,q2,q3
temp_q4 = tf.constant([ [0, 10, 0],[0, 0, 10], [10, 10, 0]], dtype=tf.float32)  # (3, 3)
print_scaled_dot_product_attention(temp_q4, temp_k, temp_v)
attention weight:
tf.Tensor(
[[0.  1.  0.  0. ]
 [0.  0.  0.5 0.5]
 [0.5 0.5 0.  0. ]], shape=(3, 4), dtype=float32)
output:
tf.Tensor(
[[ 10.    0. ]
 [550.    5.5]
 [  5.5   0. ]], shape=(3, 2), dtype=float32)

5.Mutil-Head Attention

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CWza1d3C-1590139711698)(https://www.tensorflow.org/images/tutorials/transformer/multi_head_attention.png)]

mutil-head attention包含3部分:

  • 线性层与分头
  • 缩放点积注意力
  • 头连接
  • 末尾线性层

每个多头注意块有三个输入; Q(查询),K(密钥),V(值)。 它们通过第一层线性层并分成多个头。

注意:点积注意力时需要使用mask, 多头输出需要使用tf.transpose调整各维度。

Q,K和V不是一个单独的注意头,而是分成多个头,因为它允许模型共同参与来自不同表征空间的不同信息。 在拆分之后,每个头部具有降低的维度,总计算成本与具有全维度的单个头部注意力相同。

'''
x-> Wq0-> q0
x-> Wk0-> k0
x-> Wv0-> v0

# 实战中
q-> Wq0-> q0
k-> Wk0-> k0
v-> Wv0-> v0

q -> Wq0-> Q -> split -> q0,q1,q2...
'''

'\nx-> Wq0-> q0\nx-> Wk0-> k0\nx-> Wv0-> v0\n\n# 实战中\nq-> Wq0-> q0\nk-> Wk0-> k0\nv-> Wv0-> v0\n\nq -> Wq0-> Q -> split -> q0,q1,q2...\n'
# 构造mutil head attention层
class MutilHeadAttention(tf.keras.layers.Layer):
    def __init__(self, d_model, num_heads): # d_model:model的维度, num_heads:多头的头数
        super(MutilHeadAttention, self).__init__()
        self.num_heads = num_heads #属性
        self.d_model = d_model
        
        # d_model 必须可以正确分为各个头
        assert self.d_model % self.num_heads == 0 #判断机制
        # 分头后的维度
        self.depth = self.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):
        # 分头, 将头个数的维度 放到 seq_len 前面
        #x.shape :[batch_size, seq_len, d_model]
        # d_model = num_heads * depth
        #x-> [batch_size, num_heads, seq_len, depth]
        x = tf.reshape(x, 
                       (batch_size, -1, self.num_heads, self.depth)) # -1:seq_len
        return tf.transpose(x, perm=[0, 2, 1, 3]) #维度重新排列 交换 seq_len和num_heads
    
    def call(self, q, k, v, mask): #方法
        batch_size = tf.shape(q)[0]
        
        # 分头前的前向网络,获取q、k、v语义
        q = self.WQ(q)  # (batch_size, seq_len_q, d_model)
        k = self.WK(k)  # (batch_size, seq_len_k, d_model) seq_len_k==seq_len_v
        v = self.WV(v)  # (batch_size, seq_len_v, d_model)
        
        # 分头
        # q.shape:(batch_size, num_heads,seq_len_q, depth)
        q = self.split_heads(q, batch_size) # (batch_size, num_heads, seq_len_q, depth)
        # k.shape:(batch_size, num_heads, seq_len_k, depth)
        k = self.split_heads(k, batch_size)
        # v.shape:(batch_size, num_heads, seq_len_v, depth)
        v = self.split_heads(v, batch_size)
        # 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_outputs, attention_weights = \
        scaled_dot_product_attention(q, k, v, mask)
        # 把多头维度后移
        scaled_attention_outputs = tf.transpose(
            scaled_attention_outputs, perm = [0, 2, 1, 3]) # (batch_size, seq_len_q, num_heads, depth) 切换回来

        # 合并多头
        concat_attention = tf.reshape(scaled_attention_outputs, 
                                      (batch_size, -1, self.d_model))
        
        #output.shape :(batch_size,seq_len_q,d_model)
        # 全连接重塑
        output = self.dense(concat_attention)
        
        return output, attention_weights

测试

temp_mha = MutilHeadAttention(d_model=512, num_heads=8)
y = tf.random.uniform((1, 60, 256))
output, att = temp_mha(y, y, y, mask=None) #调用方法
print(output.shape, att.shape)
(1, 60, 512) (1, 8, 60, 60)

point wise前向网络

def feed_forward_network(d_model, dff):#dff:dim of feed_forward_network
    return tf.keras.Sequential([
        tf.keras.layers.Dense(dff, activation='relu'),
        tf.keras.layers.Dense(d_model)
    ])
sample_fnn = feed_forward_network(512, 2048)
sample_fnn(tf.random.uniform((64, 50, 512))).shape
TensorShape([64, 50, 512])

6.编码器和解码器

  • 通过N个编码器层,为序列中的每个字/令牌生成输出。
  • 解码器连接编码器的输出和它自己的输入(自我注意)以预测下一个字。

编码层

每个编码层包含以下子层

  • 多头注意力(带掩码)
  • 前向网络

每个子层中都有残差连接,并最后通过一个正则化层。残差连接有助于避免深度网络中的梯度消失问题。
每个子层输出是LayerNorm(x + Sublayer(x)),规范化是在d_model维的向量上。Transformer一共有n个编码层。

class EncoderLayer(keras.layers.Layer):
    """
    x->self attention -> add&normalize & dropout
    -> feed_forward -> add& normalize & dropout
    """
    def __init__(self, d_model, num_heads, dff, rate = 0.1):
        super(EncoderLayer,self).__init__()
        self.mha = MutilHeadAttention(d_model,num_heads) #MutilHeadAttention
        self.ffn = feed_forward_network(d_model,dff)#feed forward network
        
        self.layer_norm1 = keras.layers.LayerNormalization(
            epsilon=1e-6)
        self.layer_norm2 = keras.layers.LayerNormalization(
            epsilon=1e-6)
        
        self.dropout1 = keras.layers.Dropout(rate)
        self.dropout2 = keras.layers.Dropout(rate)
    
    def call(self,x,training,encoder_padding_mask):
        # x.shape:(batch_size,seq_len,dim),dim = d_model
        # atten_output.shape:(batch_size,seq_len,d_model)
        attn_output,_ = self.mha(x,x,x,encoder_padding_mask)
        attn_output = self.dropout1(attn_output,training = training)
        out1 = self.layer_norm1(x + attn_output)
        # ffn.shape:(batch_size,seq_len,dim),dim = d_model
        # out2.shape:(batch_size,seq_len,d_model)
        ffn_output = self.ffn(out1)
        ffn_output = self.dropout2(ffn_output,training = training)
        out2 = self.layer_norm2(out1 + ffn_output)
        
        return out2
sample_encoder_layer = EncoderLayer(512,8,2048)
sample_input = tf.random.uniform((64,50,512))
sample_output = sample_encoder_layer(sample_input,False,None)
print(sample_output.shape)
(64, 50, 512)
class DecoderLayer(keras.layers.Layer):
    """
    x->self attention -> add&normalize & dropout->
    out1->encoding_outputs->attention->  add& normalize & dropout->
    out2->feed_forward ->add& normalize & dropout->out3
    """
    def __init__(self, d_model, num_heads, dff, rate = 0.1):
        super(DecoderLayer,self).__init__()
        
        self.mha1 = MutilHeadAttention(d_model,num_heads) #MutilHeadAttention
        self.mha2 = MutilHeadAttention(d_model,num_heads)
        
        self.ffn = feed_forward_network(d_model,dff)#feed forward network
        
        self.layer_norm1 = keras.layers.LayerNormalization(
            epsilon=1e-6)
        self.layer_norm2 = keras.layers.LayerNormalization(
            epsilon=1e-6)
        self.layer_norm3 = keras.layers.LayerNormalization(
            epsilon=1e-6)
        
        self.dropout1 = keras.layers.Dropout(rate)
        self.dropout2 = keras.layers.Dropout(rate)
        self.dropout3 = keras.layers.Dropout(rate)
    
    def call(self,x,encoding_outputs,training,
             decoder_mask,encoder_decoder_padding_mask):
        # decoder_mask : 由 look_ahead_mask 和decoder_padding_mask 合并而来
        # x.shape:(batch_size,seq_len,dim),dim = d_model
        # atten_output.shape:(batch_size,input_seq_len,d_model)
        
        #attn1,out1.shape: (batch_size,target_seq_len,d_model))
        attn1,attn_weights1 = self.mha1(x,x,x,decoder_mask)
        attn1 = self.dropout1(attn1,training = training)
        out1 = self.layer_norm1(attn1 + x)
        
        #attn2,out2.shape: (batch_size,target_seq_len,d_model))
        attn2,attn_weights2 = self.mha2(
            out1,encoding_outputs,encoding_outputs,
            encoder_decoder_padding_mask)
        attn2 = self.dropout2(attn2, training = training)
        out2 = self.layer_norm2(attn2 + out1)
        
        #ffn_output,out3.shape: (batch_size,target_seq_len,d_model))
        ffn_output = self.ffn(out2)
        ffn_output = self.dropout3(ffn_output,training = training)
        out3 = self.layer_norm3(ffn_output + out2)
        
        return out3, attn_weights1, attn_weights2
sample_decoder_layer = DecoderLayer(512,8,2048)
sample_decoder_input = tf.random.uniform((64,60,512))
sample_decoder_output, sample_attn_weights1, sample_attn_weights2 = sample_decoder_layer(
    sample_decoder_input,sample_output,False,None,None)
print(sample_decoder_output.shape)
print(sample_attn_weights1.shape)
print(sample_attn_weights2.shape)
(64, 60, 512)
(64, 8, 60, 60)
(64, 8, 60, 50)
class EncoderModel(keras.layers.Layer):
    def __init__(self, num_layers,input_vocab_size, max_lenth,
                 d_model,num_heads,dff,rate = 0.1):
        super(EncoderModel,self).__init__()
        self.d_model = d_model
        self.num_layers = num_layers
        self.max_lenth = max_lenth
        
        self.embedding = keras.layers.Embedding(input_vocab_size,
                                                self.d_model)
        #  position_embedding.shape : (1,max_lenth,d_model)
        self.position_embedding = get_position_embedding(max_lenth,d_model)
        
        self.dropout = keras.layers.Dropout(rate)
        self.encoder_layers =[
            EncoderLayer(d_model,num_heads,dff,rate) 
            for _ in range(self.num_layers)]
        
    def call (self, x, training, encoder_padding_mask):
        # x.shape:(batch_size,input_seq_len)
        input_seq_len = tf.shape(x)[1]
        tf.debugging.assert_less_equal(
            input_seq_len , self.max_lenth,
            "input_seq_len should be less or equal to self.max_lenth ") 
        
        # x.shape:(batch_size,input_seq_len,d_model)
        x = self.embedding(x)
        x *= tf.math.sqrt(tf.cast(self.d_model,tf.float32))
        x += self.position_embedding[:,:input_seq_len,:]
        
        x = self.dropout(x, training = training)
        
        for i in range(self.num_layers):
            x = self.encoder_layers[i](x,training,
                                       encoder_padding_mask)
            
            # x.shape:(batch_size,input_seq_len,d_model)
        return x        
sample_encoder_model = EncoderModel(2,8500,max_lenth,
                                   512,8,2048) #相当于实例化
sample_encoder_model_input = tf.random.uniform((64,37))
sample_encoder_model_output = sample_encoder_model(
    sample_encoder_model_input,False,encoder_padding_mask = None) #相当于调用方法
print(sample_encoder_model_output.shape)
(64, 37, 512)
class DecoderModel(keras.layers.Layer):
    def __init__(self, num_layers,target_vocab_size, max_lenth,
                 d_model,num_heads,dff,rate = 0.1):
        super(DecoderModel,self).__init__()
        self.num_layers = num_layers
        self.max_lenth = max_lenth
        self.d_model = d_model
        
        self.embedding = keras.layers.Embedding(target_vocab_size,
                                                d_model)
        #  position_embedding.shape : (1,max_lenth,d_model)
        self.position_embedding = get_position_embedding(max_lenth,
                                                         d_model)
        
        self.dropout = keras.layers.Dropout(rate)
        self.decoder_layers =[
            DecoderLayer(d_model, num_heads, dff, rate) 
            for _ in range(self.num_layers)]
        
    def call (self, x ,encoding_outputs,training, 
              decoder_mask, encoder_decoder_padding_mask):
        # x.shape:(batch_size,output_seq_len)
        output_seq_len = tf.shape(x)[1]
        tf.debugging.assert_less_equal(
            output_seq_len , self.max_lenth,
            "output_seq_len should be less or equal to self.max_lenth ")
        
        attention_weights = {}
        # x.shape:(batch_size,output_seq_len,d_model)
        x = self.embedding(x)
        x *= tf.math.sqrt(tf.cast(self.d_model,tf.float32))
        x += self.position_embedding[:,:output_seq_len,:]
        
        x = self.dropout(x, training = training)
        
        for i in range(self.num_layers):
            x, att1,att2 = self.decoder_layers[i](
                x,encoding_outputs,training,
                decoder_mask,encoder_decoder_padding_mask)
            attention_weights[
                'decoder_layer{}_att1'.format(i+1)] = att1
            attention_weights[
                'decoder_layer{}_att2'.format(i+1)] = att2
            # x.shape:(batch_size,output_seq_len,d_model)
        return x,attention_weights
sample_decoder_model = DecoderModel(2,8000,max_lenth,
                                   512,8,2048) #相当于实例化
sample_decoder_model_input = tf.random.uniform((64,35))
sample_decoder_model_output, sample_decoder_model_att \
= sample_decoder_model(
    sample_decoder_model_input,
    sample_encoder_model_output,
    training = False,
    decoder_mask = None,
    encoder_decoder_padding_mask = None) #相当于调用方法
print(sample_decoder_model_output.shape)

for key in sample_decoder_model_att:
    print(sample_decoder_model_att[key].shape) # 通过 key 检索字典
(64, 35, 512)
(64, 8, 35, 35)
(64, 8, 35, 37)
(64, 8, 35, 35)
(64, 8, 35, 37)
sample_decoder_model_att.keys()
dict_keys(['decoder_layer1_att1', 'decoder_layer1_att2', 'decoder_layer2_att1', 'decoder_layer2_att2'])
sample_decoder_model_att['decoder_layer1_att1'].shape
TensorShape([64, 8, 35, 35])
for i,j in sample_decoder_model_att.items():
    print(j.shape)
(64, 8, 35, 35)
(64, 8, 35, 37)
(64, 8, 35, 35)
(64, 8, 35, 37)
class Transformer(keras.Model):
    def __init__(self, num_layers,input_vocab_size, target_vocab_size,
                 max_lenth, d_model, num_heads, dff, rate = 0.1):
        super(Transformer,self).__init__()
        
        self.encoder_model = EncoderModel(
            num_layers,input_vocab_size,max_lenth,
            d_model,num_heads,dff,rate)
        
        self.decoder_model = DecoderModel(
            num_layers,target_vocab_size,max_lenth,
            d_model,num_heads,dff,rate)
        
        self.final_layer = keras.layers.Dense(target_vocab_size)
        
    def call(self,inp,tar,training,encoder_padding_mask,
            decoder_mask,encoder_decoder_padding_mask):
        #encoding_outputs.shape: (batch_size,input_seq_len,d_model)
        encoding_outputs = self.encoder_model(
            inp,training,encoder_padding_mask)
        
        #decoding_outputs.shape: (batch_size,output_seq_len,d_model)
        decoding_outputs,attention_weights = self.decoder_model(
            tar,encoding_outputs,training,
            decoder_mask,encoder_decoder_padding_mask)
        
        #predictions.shape: (batch_size,output_seq_len,target_vocab_size)
        predictions = self.final_layer(decoding_outputs)
        
        return predictions,attention_weights
sample_transformer = Transformer(2,8500,8000,max_lenth,
                                 512,8,2048,rate=0.1)
temp_input = tf.random.uniform((64,26))
temp_target = tf.random.uniform((64,31))
predictions , attention_weights = sample_transformer(
    temp_input,temp_target,training = False,
    encoder_padding_mask = None,
    decoder_mask = None,
    encoder_decoder_padding_mask = None)
print(predictions.shape)
for key in attention_weights:
    print(attention_weights[key].shape)
(64, 31, 8000)
(64, 8, 31, 31)
(64, 8, 31, 26)
(64, 8, 31, 31)
(64, 8, 31, 26)
# 1 initializes model
# 2 define loss, optimizer, learning_rate schedule
# 3 train_step
# 4 train process
num_layers = 4
d_model = 128
dff = 512
num_heads = 8

input_vocab_size = pt_tokenizer.vocab_size + 2
target_vocab_size = en_tokenizer.vocab_size + 2

drop_rate = 0.1

transformer = Transformer(num_layers,
                          input_vocab_size,
                          target_vocab_size,
                          max_lenth,d_model,
                          num_heads,dff,
                          drop_rate)
# Irate = (d_model ** -0.5)*min(setp_num**(-0.5)*min(step_num ** (-0.5),
                               #step_num*warm_up_step **(-1.5)))
    
class CustomizedSchedule(keras.optimizers.schedules.LearningRateSchedule):
    def __init__(self,d_model,warmup_steps = 4000):
        super (CustomizedSchedule,self).__init__()
        
        self.d_model = tf.cast(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))
        arg3 = tf.math.rsqrt(self.d_model)
        
        return arg3*tf.math.minimum(arg1,arg2)

learning_rate = CustomizedSchedule(d_model)
optimizer = keras.optimizers.Adam(learning_rate,
                                  beta_1=0.9,
                                  beta_2=0.98,
                                  epsilon=1e-9)
temp_learning_rate_schedule = CustomizedSchedule(d_model)


plt.plot(temp_learning_rate_schedule(
    tf.range(40000,dtype=tf.float32)))
plt.xlabel("learning rate")
plt.ylabel("Train step")
Text(0, 0.5, 'Train step')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xX4gNb9S-1590139711701)(output_84_1.png)]

loss_object = 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_mean(loss_)
    """
    Encoder :
     - encode_padding_mask :##作用在encoder layers上(self attention of EncoderLayer)
     Decoder:
     - look_ahead_mask #目标值的后半段还没有预测出来  #作用在decoder的 layers上 (self attention of DecoderLayer)
     - encoder_decoder_padding_mask  # 做 encoder decoder attention的时候,
     decoder的隐含状态与Encoder的每一个输出做attention,但Encoder上面有padding,
     不应该在Encoder上的padding花注意力,要把Encoder上的padding mask 掉
      ## look_ahead_mask 作用在Encoder和 Decoder之间的attention的layers上
     -decoder_padding_mask #也要把decoder上的padding mask掉  #作用在decoder的 layers上  (self attention of DecoderLayer)
     
     第一selfattention层上只接受一个mask的输入,但是有 look_ahead_mask ,decoder_padding_mask
     两个,所以要先合并,与操作
    """
'\nEncoder :\n - encode_padding_mask :##作用在encoder layers上(self attention of EncoderLayer)\n Decoder:\n - look_ahead_mask #目标值的后半段还没有预测出来  #作用在decoder的 layers上 (self attention of DecoderLayer)\n - encoder_decoder_padding_mask  # 做 encoder decoder attention的时候,\n decoder的隐含状态与Encoder的每一个输出做attention,但Encoder上面有padding,\n 不应该在Encoder上的padding花注意力,要把Encoder上的padding mask 掉\n  ## look_ahead_mask 作用在Encoder和 Decoder之间的attention的layers上\n -decoder_padding_mask #也要把decoder上的padding mask掉  #作用在decoder的 layers上  (self attention of DecoderLayer)\n \n 第一selfattention层上只接受一个mask的输入,但是有 look_ahead_mask ,decoder_padding_mask\n 两个,所以要先合并,与操作\n'
def create_masks(inp,tar):
    encoder_padding_mask = create_padding_mask(inp)
    encoder_decoder_padding_mask = create_padding_mask(inp)
    
    look_ahead_mask = create_look_ahead_mask(tf.shape(tar)[1])
    decoder_padding_mask = create_padding_mask(tar)
    decoder_mask = tf.maximum(decoder_padding_mask,
                              look_ahead_mask)
    #print(encoder_padding_mask.shape)
    #print(encoder_decoder_padding_mask.shape)
    #print(look_ahead_mask.shape)
    #print(decoder_padding_mask.shape)
    return encoder_padding_mask,decoder_mask,encoder_decoder_padding_mask
tem_inp ,tem_tar = iter(train_dataset.take(1)).next()
print(tem_inp.shape)
print(tem_tar.shape)
(64, 36)
(64, 37)
create_masks(tem_inp,tem_tar)
(<tf.Tensor: id=4703997, shape=(64, 1, 1, 36), dtype=float32, numpy=
 array([[[[0., 0., 0., ..., 1., 1., 1.]]],
 
 
        [[[0., 0., 0., ..., 1., 1., 1.]]],
 
 
        [[[0., 0., 0., ..., 1., 1., 1.]]],
 
 
        ...,
 
 
        [[[0., 0., 0., ..., 1., 1., 1.]]],
 
 
        [[[0., 0., 0., ..., 1., 1., 1.]]],
 
 
        [[[0., 0., 0., ..., 1., 1., 1.]]]], dtype=float32)>,
 <tf.Tensor: id=4704029, shape=(64, 1, 37, 37), dtype=float32, numpy=
 array([[[[0., 1., 1., ..., 1., 1., 1.],
          [0., 0., 1., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.],
          ...,
          [0., 0., 0., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.]]],
 
 
        [[[0., 1., 1., ..., 1., 1., 1.],
          [0., 0., 1., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.],
          ...,
          [0., 0., 0., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.]]],
 
 
        [[[0., 1., 1., ..., 1., 1., 1.],
          [0., 0., 1., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.],
          ...,
          [0., 0., 0., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.]]],
 
 
        ...,
 
 
        [[[0., 1., 1., ..., 1., 1., 1.],
          [0., 0., 1., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.],
          ...,
          [0., 0., 0., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.]]],
 
 
        [[[0., 1., 1., ..., 1., 1., 1.],
          [0., 0., 1., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.],
          ...,
          [0., 0., 0., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.]]],
 
 
        [[[0., 1., 1., ..., 1., 1., 1.],
          [0., 0., 1., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.],
          ...,
          [0., 0., 0., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.],
          [0., 0., 0., ..., 1., 1., 1.]]]], dtype=float32)>,
 <tf.Tensor: id=4704004, shape=(64, 1, 1, 36), dtype=float32, numpy=
 array([[[[0., 0., 0., ..., 1., 1., 1.]]],
 
 
        [[[0., 0., 0., ..., 1., 1., 1.]]],
 
 
        [[[0., 0., 0., ..., 1., 1., 1.]]],
 
 
        ...,
 
 
        [[[0., 0., 0., ..., 1., 1., 1.]]],
 
 
        [[[0., 0., 0., ..., 1., 1., 1.]]],
 
 
        [[[0., 0., 0., ..., 1., 1., 1.]]]], dtype=float32)>)
train_loss = keras.metrics.Mean(name = 'train_loss')
train_accuracy = keras.metrics.SparseCategoricalAccuracy(
    name = 'train_accuracy')
def train_step(inp,tar):
    tar_inp = tar[:, :-1]
    tar_real = tar[:, 1:]
    
    encoder_padding_mask, decoder_mask,encoder_decoder_padding_mask \
    = create_masks(inp,tar_inp)
    
    with tf.GradientTape() as tape:
        predictions,_ = transformer(inp,tar_inp,True,
                                   encoder_padding_mask,
                                   decoder_mask,
                                   encoder_decoder_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(tar_real,predictions)
epochs = 20
for epoch in range(epochs):
    start = time.time()
    train_loss.reset_states()
    train_accuracy.reset_states()
    
    for (batch, (inp,tar)) in enumerate(train_dataset):
        train_step(inp,tar)
        if batch % 100 == 0:
            print ('Epoch{} Batch{} Loss {:.4f} Accuracy{:.4f}'.format(
                epoch + 1,batch, train_loss.result(), 
                train_accuracy.result()))
    
    print('Epoch {} Loss{:.4f} Accuracy {:.4f}'.format(
        epoch +1 ,train_loss.result(),train_accuracy.result()))
    print('Time take for 1 epoch: {} secs\n'.format(
        time.time() - start))
Epoch1 Batch0 Loss 3.1582 Accuracy0.0612
Epoch1 Batch100 Loss 2.9546 Accuracy0.0675
Epoch1 Batch200 Loss 2.8710 Accuracy0.0769
Epoch1 Batch300 Loss 2.7864 Accuracy0.0846
Epoch1 Batch400 Loss 2.7197 Accuracy0.0910
Epoch1 Batch500 Loss 2.6597 Accuracy0.0966
Epoch1 Batch600 Loss 2.6142 Accuracy0.1014
Epoch1 Batch700 Loss 2.5711 Accuracy0.1055
Epoch 1 Loss2.5702 Accuracy 0.1056
Time take for 1 epoch: 278.3582556247711 secs

Epoch2 Batch0 Loss 2.3368 Accuracy0.1402
Epoch2 Batch100 Loss 2.2700 Accuracy0.1360
Epoch2 Batch200 Loss 2.2701 Accuracy0.1379
Epoch2 Batch300 Loss 2.2473 Accuracy0.1390
Epoch2 Batch400 Loss 2.2216 Accuracy0.1403
Epoch2 Batch500 Loss 2.2048 Accuracy0.1419
Epoch2 Batch600 Loss 2.1930 Accuracy0.1435
Epoch2 Batch700 Loss 2.1752 Accuracy0.1445
Epoch 2 Loss2.1749 Accuracy 0.1445
Time take for 1 epoch: 251.6378345489502 secs

Epoch3 Batch0 Loss 1.9136 Accuracy0.1476
Epoch3 Batch100 Loss 2.0544 Accuracy0.1580
Epoch3 Batch200 Loss 2.0410 Accuracy0.1597
Epoch3 Batch300 Loss 2.0189 Accuracy0.1614
Epoch3 Batch400 Loss 1.9965 Accuracy0.1633
Epoch3 Batch500 Loss 1.9785 Accuracy0.1658
Epoch3 Batch600 Loss 1.9642 Accuracy0.1684
Epoch3 Batch700 Loss 1.9454 Accuracy0.1704
Epoch 3 Loss1.9449 Accuracy 0.1704
Time take for 1 epoch: 249.77115440368652 secs

Epoch4 Batch0 Loss 1.8713 Accuracy0.1787
Epoch4 Batch100 Loss 1.8053 Accuracy0.1884
Epoch4 Batch200 Loss 1.7894 Accuracy0.1905
Epoch4 Batch300 Loss 1.7705 Accuracy0.1921
Epoch4 Batch400 Loss 1.7558 Accuracy0.1939



---------------------------------------------------------------------------

_FallbackException                        Traceback (most recent call last)

D:\ProgramData\Anaconda3\envs\zg5\lib\site-packages\tensorflow_core\python\ops\gen_array_ops.py in reshape(tensor, shape, name)
   8100         _ctx._context_handle, _ctx._thread_local_data.device_name, "Reshape",
-> 8101         name, _ctx._post_execution_callbacks, tensor, shape)
   8102       return _result


_FallbackException: This function does not handle the case of the path where all inputs are not already EagerTensors.


During handling of the above exception, another exception occurred:


KeyboardInterrupt                         Traceback (most recent call last)

<ipython-input-109-2bc07bd91d15> in <module>
      6 
      7     for (batch, (inp,tar)) in enumerate(train_dataset):
----> 8         train_step(inp,tar)
      9         if batch % 100 == 0:
     10             print ('Epoch{} Batch{} Loss {:.4f} Accuracy{:.4f}'.format(


<ipython-input-108-0fcc566327c5> in train_step(inp, tar)
     10                                    encoder_padding_mask,
     11                                    decoder_mask,
---> 12                                    encoder_decoder_padding_mask)
     13         loss = loss_function(tar_real,predictions)
     14     gradients = tape.gradient(loss,transformer.trainable_variables)


D:\ProgramData\Anaconda3\envs\zg5\lib\site-packages\tensorflow_core\python\keras\engine\base_layer.py in __call__(self, inputs, *args, **kwargs)
    889           with base_layer_utils.autocast_context_manager(
    890               self._compute_dtype):
--> 891             outputs = self.call(cast_inputs, *args, **kwargs)
    892           self._handle_activity_regularization(inputs, outputs)
    893           self._set_mask_metadata(inputs, outputs, input_masks)


<ipython-input-86-e2fd9de650ba> in call(self, inp, tar, training, encoder_padding_mask, decoder_mask, encoder_decoder_padding_mask)
     23         decoding_outputs,attention_weights = self.decoder_model(
     24             tar,encoding_outputs,training,
---> 25             decoder_mask,encoder_decoder_padding_mask)
     26 
     27         #predictions.shape: (batch_size,output_seq_len,target_vocab_size)


D:\ProgramData\Anaconda3\envs\zg5\lib\site-packages\tensorflow_core\python\keras\engine\base_layer.py in __call__(self, inputs, *args, **kwargs)
    889           with base_layer_utils.autocast_context_manager(
    890               self._compute_dtype):
--> 891             outputs = self.call(cast_inputs, *args, **kwargs)
    892           self._handle_activity_regularization(inputs, outputs)
    893           self._set_mask_metadata(inputs, outputs, input_masks)


<ipython-input-80-cf4aa6c8310e> in call(self, x, encoding_outputs, training, decoder_mask, encoder_decoder_padding_mask)
     37             x, att1,att2 = self.decoder_layers[i](
     38                 x,encoding_outputs,training,
---> 39                 decoder_mask,encoder_decoder_padding_mask)
     40             attention_weights[
     41                 'decoder_layer{}_att1'.format(i+1)] = att1


D:\ProgramData\Anaconda3\envs\zg5\lib\site-packages\tensorflow_core\python\keras\engine\base_layer.py in __call__(self, inputs, *args, **kwargs)
    889           with base_layer_utils.autocast_context_manager(
    890               self._compute_dtype):
--> 891             outputs = self.call(cast_inputs, *args, **kwargs)
    892           self._handle_activity_regularization(inputs, outputs)
    893           self._set_mask_metadata(inputs, outputs, input_masks)


<ipython-input-47-843aca15bbe3> in call(self, x, encoding_outputs, training, decoder_mask, encoder_decoder_padding_mask)
     31 
     32         #attn1,out1.shape: (batch_size,target_seq_len,d_model))
---> 33         attn1,attn_weights1 = self.mha1(x,x,x,decoder_mask)
     34         attn1 = self.dropout1(attn1,training = training)
     35         out1 = self.layer_norm1(attn1 + x)


D:\ProgramData\Anaconda3\envs\zg5\lib\site-packages\tensorflow_core\python\keras\engine\base_layer.py in __call__(self, inputs, *args, **kwargs)
    889           with base_layer_utils.autocast_context_manager(
    890               self._compute_dtype):
--> 891             outputs = self.call(cast_inputs, *args, **kwargs)
    892           self._handle_activity_regularization(inputs, outputs)
    893           self._set_mask_metadata(inputs, outputs, input_masks)


<ipython-input-41-4f8584226b52> in call(self, q, k, v, mask)
     33         # 分头
     34         # q.shape:(batch_size, num_heads,seq_len_q, depth)
---> 35         q = self.split_heads(q, batch_size) # (batch_size, num_heads, seq_len_q, depth)
     36         # k.shape:(batch_size, num_heads, seq_len_k, depth)
     37         k = self.split_heads(k, batch_size)


<ipython-input-41-4f8584226b52> in split_heads(self, x, batch_size)
     20         # 分头, 将头个数的维度 放到 seq_len 前面
     21         x = tf.reshape(x, 
---> 22                        (batch_size, -1, self.num_heads, self.depth)) # -1:seq_len
     23         return tf.transpose(x, perm=[0, 2, 1, 3]) #维度重新排列 交换 seq_len和num_heads
     24 


D:\ProgramData\Anaconda3\envs\zg5\lib\site-packages\tensorflow_core\python\ops\array_ops.py in reshape(tensor, shape, name)
    129     A `Tensor`. Has the same type as `tensor`.
    130   """
--> 131   result = gen_array_ops.reshape(tensor, shape, name)
    132   tensor_util.maybe_set_static_shape(result, shape)
    133   return result


D:\ProgramData\Anaconda3\envs\zg5\lib\site-packages\tensorflow_core\python\ops\gen_array_ops.py in reshape(tensor, shape, name)
   8104       try:
   8105         return reshape_eager_fallback(
-> 8106             tensor, shape, name=name, ctx=_ctx)
   8107       except _core._SymbolicException:
   8108         pass  # Add nodes to the TensorFlow graph.


D:\ProgramData\Anaconda3\envs\zg5\lib\site-packages\tensorflow_core\python\ops\gen_array_ops.py in reshape_eager_fallback(tensor, shape, name, ctx)
   8142   _attrs = ("T", _attr_T, "Tshape", _attr_Tshape)
   8143   _result = _execute.execute(b"Reshape", 1, inputs=_inputs_flat, attrs=_attrs,
-> 8144                              ctx=_ctx, name=name)
   8145   _execute.record_gradient(
   8146       "Reshape", _inputs_flat, _attrs, _result, name)


D:\ProgramData\Anaconda3\envs\zg5\lib\site-packages\tensorflow_core\python\eager\execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name)
     59     tensors = pywrap_tensorflow.TFE_Py_Execute(ctx._handle, device_name,
     60                                                op_name, inputs, attrs,
---> 61                                                num_outputs)
     62   except core._NotOkStatusException as e:
     63     if name is not None:


KeyboardInterrupt: 
def evaluate(inp_sentence):
    input_id_sentence = [pt_tokenizer.vocab_size] \
    + pt_tokenizer.encode(inp_sentence) + [pt_tokenizer.vocab_size + 1]
    
    encoder_input = tf.expand_dims(input_id_sentence,0)
    
    decoder_input = tf.expand_dims([en_tokenizer.vocab_size],0)
    
    for i in range (max_lenth):
        encoder_padding_mask, decoder_mask,encoder_decoder_padding_mask \
        = create_masks(encoder_input,decoder_input)
        
        predictions,attention_weights = transformer(
            encoder_input,
            decoder_input,
            False,
            encoder_padding_mask,
            decoder_mask,
            encoder_decoder_padding_mask)
        
        predictions = predictions[:,-1,:]
        
        predictions_id = tf.cast(tf.argmax(predictions,axis=-1),tf.int32)
        
        if tf.equal(predictions_id, en_tokenizer.vocab_size +1):
            return tf.squeeze(decoder_input,axis=0), attention_weights
        
        decoder_input = tf.concat([decoder_input,[predictions_id]],axis=-1)
    return tf.squeeze(decoder_input,axis=0), attention_weights     
def plot_encoder_decoder_attention(attention, input_sentence,
                                   result,layer_name):
    fig = plt.figure(figsize=(16,8))
    
    input_id_sentence = pt_tokenizer.encode(input_sentence)
    
    attention = tf.squeeze(attention[layer_name],axis=0)
    
    for head in range (attention.shape[0]):
        ax = fig.add_subplot(2,4,head + 1)
        
        ax.matshow(attention[head][:-1,:])
        
        fontdict = {'fontsize':10}
        
        ax.set_xticks(range(len(input_id_sentence) + 2))
        ax.set_yticks(range(len(result)))
        
        ax.set_ylim(len(result) - 1.5 ,-0.5)
        
        ax.set_xticklabels(
            ['<start>']+[pt_tokenizer.decode([i]) for i in input_id_sentence],
            fontdict = fontdict,rotation = 90)
        
        ax.set_yticklabels([en_tokenizer.decode([i]) for i in result if i <en_tokenizer.vocab_size],
                           fontdict = fontdict)
        ax.set_xlabel('Head{}'.format(head + 1))
    plt.tight_layout()
    plt.show()
def translate (input_sentence,lay_name = ''):
    result, attention_weights = evaluate(input_sentence)
    
    predicted_sentence = en_tokenizer.decode(
        [i for i in result if i < en_tokenizer.vocab_size])
    
    print("Input: {}".format(input_sentence))
    print("predicted translation: {}".format(predicted_sentence))
    
    if lay_name:
        plot_encoder_decoder_attention(attention_weights,input_sentence,result,lay_name)
translate('está Muito frio aqui.')
Input: está Muito frio aqui.
predicted translation: it 's called the j here .
translate('esta é a minha vida.')
Input: esta é a minha vida.
predicted translation: this is my life .
translate('esta é a minha vida.',lay_name='decoder_layer4_att2')
Input: esta é a minha vida.
predicted translation: this is my life .

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MOEqAyvI-1590139711702)(output_99_1.png)]

自然语言处理中的Transformer和BERT 2018年马上就要过去,回顾深度学习在今年的进展,让人印象最深刻的就是谷歌提出的应用于自然语言处理领域的BERT解决方案,BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding(https://arxiv.org/abs/1810.04805)。BERT解决方案刷新了各大NLP任务的榜单,在各... 阅读详情

相关推荐

【NLP】Transformer在pytorch 的实现+情感分析案例+生成式任务案例

定义PositionalEncoding类,用于为输入添加位置信息# 有transpose,代表默认输入数据形状为(seq_len, batch_size, d_model)# 如果输入结构为(batch_size, seq_len, d_model),则不需要transposeelse:# 如果batch_first,则需要截断的是中间的维度# 且用于中间维度截断的维度是seq_lenelse:# 如果没有batch_first,需要截断的是第一个维度return x。

weixin_51589123的博客 1152

Transformer:Attention机制、前馈神经网络、编码器与解码器

在传统的循环神经网络(RNN)和长短时记忆网络(LSTM)中,输入序列是按顺序处理的。这意味着在处理当前时间步的输入时,需要依赖之前的计算结果。这种依赖关系可能导致训练过程中梯度消失或梯度爆炸的问题,限制了模型的性能。为了解决这些问题,Transformer模型引入了自注意力机制(Self-Attention Mechanism),允许模型在处理当前输入时,直接关注到序列中的任意位置。总的来说,Transformer模型的编码器和解码器都具有各自的优势和不足。

不要给自己设限,尝试更多可能(思所向 皆可往) 2905

自然语言处理之文本生成:Transformer:多头注意力机制实现

在Transformer模型中,多头注意力机制是其核心创新之一,它允许模型从不同的表示子空间中并行地关注输入的不同部分。这一机制通过将注意力权重矩阵分解为多个较小的矩阵,然后在不同的“注意力头”中独立计算注意力,最后将这些头的结果通过线性变换合并,从而增强了模型捕捉复杂依赖关系的能力。

zhubeibei168的博客 801

【原理篇】小白入门Transformer!一文了解Transformer架构

BART、PEGASUS 模型用于生成新闻摘要。✅。

m0_60302377的博客 8697

【自然语言处理(NLP)】深度学习架构:Transformer 原理及代码实现

核心组件 - **[多头注意力机制(Multi-Head Attention)](https://blog.csdn.net/u014608435/article/details/145363310)** - **原理**:将输入的向量表示通过多个头(head)的注意力机制,并行地计算不同位置之间的依赖关系,从而捕捉到更丰富的语义信息。每个头都可以关注输入序列的不同部分,然后将这些头的结果进行拼接和线性变换,得到最终的输出。 - **公式**:$MultiHead(Q,K,V)=Concat

专注上位机开发、机器视觉、机器学习、嵌入式软硬件开发 1万+

【自然语言处理(NLP)】基于Transformer架构的预训练语言模型:BERT 原理及代码实现

模型架构 - **基于Transformer编码器**:BERT仅使用Transformer的编码器部分,其多层双向Transformer编码器允许模型在处理每个单词时,同时考虑该单词的左右上下文信息,从而生成深度的双向语言表征。 - **多层结构**:基础版本的BERT有12层Transformer编码器层,而BERT - Large有24层,层数越多,模型的表达能力越强,但计算量也越大。

专注上位机开发、机器视觉、机器学习、嵌入式软硬件开发 1万+

Transformer 动画讲解:注意力机制

当Attention模块处理包含“model”的句子时,它会查看句子中的其他单词(如“machine learning”或“fashion”),并确定这些单词与“model”之间的语义关系。以单词“model”为例,在“machine learning model”(机器学习模型)和“fashion model”(时尚模特)这两个不同的上下文中,它的含义是不同的。在自然语言处理(NLP)中,嵌入向量(Embedding Vector)是单词或文本片段的数值表示,它们捕捉了这些单词或文本片段的语义信息。

2301_78285120的博客 1462

【自然语言处理(NLP)】基于Transformer架构的预训练语言模型:BERT 训练之数据集处理、训练代码实现

【自然语言处理(NLP)】基于Transformer架构的预训练语言模型:BERT 训练之数据集处理、训练代码实现

专注上位机开发、机器视觉、机器学习、嵌入式软硬件开发 1万+

Transformer介绍及架构解析

第一章:Transformer背景介绍 1.1 Transformer的诞生 2018年10月,Google发出一篇论文《BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding》, BERT模型横空出世, 并横扫NLP领域11项任务的最佳成绩! 论文地址: https://arxiv.org/pdf/1810.04805.pdf 而在BERT中发挥重要作用的结构就是Transformer..

码python的Vinsmoke 3987

Uncertainty-Aware Mean Teacher(UA-MT)

本文提出了一种新的基于不确定性的半监督学习框架(UA-MT),通过额外利用未标记的数据从3D MR图像中分割左心房。具体地说,本文建立了一个教师模型和一个学生模型,学生模型通过最小化标注数据上的分割监督损失和所有输入数据上的与教师模型预测输出的一致性损失进行优化。如果没有未标记输入中的注释,教师模型的预测目标可能不可靠且有噪声。:在估计不确定性 U 的指导下,我们过滤掉相对不可靠**(高不确定性),整个体积** U 的不确定性**是 {u} ∈ RH×W ×D。过滤掉高不确定性的,也就是熵大于某个值的。

Alexa_的博客 1870

华为C语言笔试题(附答案)

华为C语言笔试题(附答案)     1、局部变量能否和全局变量重名?   答:能,局部会屏蔽全局。要用全局变量,需要使用 ":: "   局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内。  

峰云四起 3036

NLP自然语言处理 04 transformer架构模拟实现

导包位置编码器部分词嵌入WordEmbedding位置编码模型PositionEncoding编码器部分。

m0_54235621的博客 1029

OpenSees入门指南:从零开始的环境配置与TCL脚本实战

本文提供了一份详细的OpenSees入门指南,涵盖从零开始的环境配置到TCL脚本实战的全过程。文章重点讲解了OpenSees的安装步骤、环境变量设置,并推荐了高效的VS Code集成开发环境配置方法。通过一个简支梁分析的完整TCL脚本示例,手把手引导读者完成第一个非线性有限元分析,帮助土木工程与结构工程领域的研究者与学生快速上手这一强大的开源分析工具。

weixin_28829339的博客 336

Transformer模型:PyTorch实现的高效自然语言处理工具

Transformer模型:PyTorch实现的高效自然语言处理工具 项目介绍 Transformer模型自2017年由Vaswani等人提出以来,已成为自然语言处理(NLP)领域的标杆模型。本项目提供了一个基于PyTorch的Transformer模型实现,旨在帮助开发者快速搭建和训练Transformer模型,适用于多种NLP任务,如机器翻译、语言建模等。 项目技术分析 技术栈 PyTorc...

gitblog_00700的博客 748

鸿蒙进阶——HDI及IDL硬件接口IPC框架小结

HDI(Hardware Device Interface):OpenHarmony硬件设备接口,定义系统中跨进程通信的接口,实现服务间的跨进程通信

最美不过,心中有梦,身旁有你! 3907

手把手搭建你的第一个OCT仿真模型:用Python和光学仿真库重现A-SCAN信号

本文详细介绍了如何使用Python和光学仿真库搭建OCT仿真模型,重现A-SCAN信号。从环境配置、干涉仪建模到信号处理全流程,手把手教你实现光学相干层析成像的核心技术。通过代码示例和性能优化技巧,帮助开发者深入理解OCT原理并应用于医疗诊断等领域。

weixin_42562079的博客 241

Pytorch实现Transformer:让自然语言处理更高效的利器

Pytorch实现Transformer:让自然语言处理更高效的利器 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 在自然语言处理(NLP)领域,Transformer模型的出现无疑是革命性的。本项目是基于Python语言和Pytorch深度学习框架的Transformer模型实现,旨在帮助研究人员和开发者理解和掌握这一强大模型的构建与训练过程。通过本项目,您可以深入...

gitblog_06734的博客 316

数字IC物理验证实战 | 从Calibre LVS报告到Innovus定位的Debug全链路解析

本文详细解析了数字IC物理验证中Calibre LVS报告的Debug全流程,从INCORRECT NETS错误的初探到Innovus定位技巧,提供了实战案例和高效工具的使用方法。重点介绍了Calibre高亮功能、Innovus验证命令以及前后端工具联动的关键策略,帮助工程师快速定位和解决LVS问题,提升物理验证效率。

weixin_30919429的博客 127

【NLP】Transformer理解(Pytorch实现)

蓝斯诺特 【参考:Transformer简明教程, 从理论到代码实现到项目实战, NLP进阶必知必会._哔哩哔哩_bilibili】 举了一个实例,计算过程浅显易懂 【参考:NLP - Transformer_伊织_的博客-优快云博客】 【参考:lansinuote/Transformer_Example | github】 下面略有修改 import torch import random import numpy as np import math torch.manual_seed(100) m

myaijarvis notebook 806

杰理SDK入门教程(五):按键使用配置

摘要 杰理SDK提供IO按键和AD按键两种方案。IO按键通过GPIO电平检测实现,配置时需要设置板级宏定义和硬件连接,默认使用PB1引脚。AD按键基于ADC电压采样,通过电阻分压区分按键,需配置功能使能、硬件通道和键值适配。按键功能通过修改SDK中的key_table文件实现。两种方案适用于不同硬件场景,开发者可根据需求选择。

qq_42014563的博客 777

YOLO11 Backbone改进:二值化、三值化权重实战(一)

本文介绍了二值化/三值化神经网络的基本概念、优势挑战及应用场景。二值化网络将权重限制为±1,三值化则增加0值,显著减少模型存储需求和计算复杂度。虽然存在精度下降等挑战,但通过技术改进已能在移动设备、自动驾驶等领域应用。文章分析了YOLO11中适合量化的层,并详细阐述了二值化权重原理及Straight-Through Estimator等关键技术。二值化/三值化神经网络为资源受限设备提供了高效的深度学习解决方案。

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 299

自然语言处理——05 Transformer架构和手写实现

Transformer背景介绍、Transformer架构(输入、输出、编码器、解码器)、输入模块(文本嵌入层、位置编码器)、编码器模块(多头注意力机制、前馈全连接层、规范化层、子层连接结构、编码器层、编码器)、解码器模块(解码器层、解码器)、模型构建

念头通达 1759

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

【NLP自然语言处理】9.基础-Transformer介绍,架构,以及输入部分实现

Transformer模型是2017年由谷歌提出的革命性神经网络架构,其核心创新在于自注意力机制。相比传统RNN/LSTM模型,Transformer具有并行计算能力强、长距离依赖捕捉效果好等优势,迅速成为NLP领域的主流架构。BERT、GPT等知名模型均基于Transformer构建。该模型采用编码器-解码器结构,包含文本嵌入层、位置编码、多头注意力机制等关键组件。位置编码通过正弦/余弦函数为输入序列添加位置信息,解决了传统架构无法处理词序的问题。Transformer在机器翻译、文本生成等任务上表现优异

资深系统架构,深耕高并发研发与 AI 大模型工程化落地。技术栈以 Python (AI/NLP/RAG/Agent) 与 Golang (高并发架构) 为双核心,兼具 PHP 大型应用经验。专注算法落地、复杂系统设计及团队技术赋能 332

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Go语言实现的NLP Transformer项目安装与配置指南

Go语言实现的NLP Transformer项目安装与配置指南 1. 项目基础介绍 本项目是一个纯Go语言编写的自然语言处理(NLP)Transformer模型库,旨在为Go语言开发者提供方便的模型训练、测试和推理功能。该库目前处于积极开发阶段,可能会有很多更新和变化。当版本达到1.0时,才会被认为是稳定的。本项目受到了Python中的HuggingFace Transformers库和Rust语...

gitblog_00492的博客 414

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

NLP学习—22.Transformer的代码实现

文章目录引言一、准备工作二、背景介绍三、模型结构1.Encoder-Decoder结构2.Encoder and Decoder Stacks2.1 Encoder2.2 decoder3.Attention3.1self-attention3.2 Multi-Head Attention3.3 Attention在模型中的应用4.Feed-Forward5.Embeddings5.1 Positional Encoding6.完整模型四、模型训练五、Example 引言   Transformer是如今几

柳杰的博客 7030

自然语言处理Transformer模型在Go语言中的实现

自然语言处理Transformer模型在Go语言中的实现 1. 项目介绍 本项目是一个纯Go语言编写的自然语言处理(NLP)Transformer模型库,旨在为Go开发者提供一个方便的工具,以训练和测试NLP模型,并进行推理。这个包目前处于积极开发阶段,可能会有很多变化。请在自行承担风险的情况下使用它。当版本达到1.0时,将被视为稳定版。 本项目受到了Python中流行的HuggingFace T...

gitblog_00493的博客 454
上一篇: Seq2Seq_Attention
下一篇: CNN-RNN结构用于图像处理
潘诺西亚的火山
博客等级 码龄10年 7415粉丝 283原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

潘诺西亚的火山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值