首先输入是64 * 10的矩阵,代表64个句子,每个句子10个词。
X = self.positionalEncoding(self.embedding(X)*math.sqrt(self.num_hiddens))
在经过embeddeding之后,变为64 * 10 *32 矩阵,每个词使用32维向量表示。然后将数据放入 X = encoder_block(X,valid_lens)
,这里我们将block设为1,就是encoderBlock只有一层。valid_lens
是一个64 * 1的向量,表示每句话的有用的向量。
随后就进入Y = self.addnorm1(X,self.multihead_attention(X,X,X,valid_lens))
,先进入多头注意力机制。
queries = transpose_qkv(self.W_q(queries),self.num_heads)
keys = transpose_qkv(self.W_k(keys),self.num_heads)
values = transpose_qkv(self.W_v(values),self.num_heads)
self.W_q、self.W_k、self.W_v
均为全连接层,将输入的X,进行不同的变换。这里的num_heads为4,transpose_qkv函数会将query进行切分。
def transpose_qkv(X,num_heads):# 输入为64*10*32 X = X.reshape(X.shape[0],X.shape[1],num_heads,-1)#torch.Size([64, 10, 4, 8])X = X.permute(0, 2, 1, 3)#torch.Size([64, 4, 10, 8])return X.reshape(-1, X.shape[2], X.shape[3])#输入为torch.Size([256, 10, 8])
一共有64句话,此次的head为4,也就是每行句子需要4次不同的self-attention,一共需要256次,
其中每次self-attention中query与单词个数相同均为10,query的由一个长度为8的向量表示。这也就是256*10*8的由来。