python-pytorch seq2seq+attention笔记1.0.0
记录
- 2024年5月14日09:27:39----0.5.10
- 2024年5月14日11:32:47----0.5.12
- 2024年5月14日11:51:03----1.0.0
- 2024年5月15日13:57:25----1.0.3
- 2024年5月19日16:21:17----1.0.10
1. LSTM模型的数据size
一定是按这个来:维度(batch_size, seq_length, embedding_dim) 是一个三维的tensor;其中,batch_size指每次输入的文本数量;seq_length指每个文本的词语数或者单字数;embedding_dim指每个词语或者每个字的向量长度。
2. 关于LSTM的输入数据包含hn和cn时,hn和cn的size
LSTM的输入数据是上个时间窗的hn和cn时,hn和cn的size要求一定是和LSTM模型参数吻合。公式是(laynum,batchsize,hidden or embeding size)或者(batchsize,hidden or embeding size)。
3. LSTM参数中默认batch_first
其实改变的是模型的hn和cn的size,不改变output的size。因为,cn和hn的size是和batch_size有关系的,是layernum、batch_size、hidden_size
4. Attention机制的三种算法
这里使用的是luong的attention,计算权重的方法有dot 、general、concat三种,常见使用general算法。
general大概思路是:
计算分数:decoder中LSTM的output和encoder的output做bmm计算
计算权重:将计算出来的分数做softmax,得到行上的概率分布或者权重
计算新向量:将权重和encoder的outpu再做bmm计算
拼接decoder的output和新向量
对新的拼接结果做tanh计算
最后全连接到vocab_size
5. decoder中使用注意力的步骤
- 计算分数score
- 计算权重at
- 计算新的context向量ct
- 拼接ct和decoder_ht
- 做tanh计算
- 使用tanh结果做全连接预测
6. 模型的编码器
思路很简单,就是将word2index后,通过embedding,将数据给LSTM模型就可以了,返回的是 LSTM的output、hn、cn。
当前你可以根据自己的习惯,在使用LSTM时候增加参数batch_fist或者bidirectional。
此时inputx的是word2index后的数据。
class encoder(nn.Module):
def __init__(self):
super(encoder, self).__init__()
self.embedding=nn.Embedding(vocab_size,n_hidden)
self.lstm=nn.LSTM(n_hidden,n_hidden*2,batch_first=False)
def forward(self, inputx):
embeded=self.embedding(inputx.long())
output,(encoder_h_n, encoder_c_n)=self.lstm(embeded.permute(1,0,2))
return output,(encoder_h_n,encoder_c_n)
7. 模型的解码器
将解码器的输入embedding后,加上编码器的outout、hn、cn,给LSTM模型输出ouput、hn、cn,做general的attention,最终返回新的LSTM的output、hn、cn。
class lstm_decoder(nn.Module):
def __init__(self):
super(lstm_decoder, self).__init__()
self.embedding=nn.Embedding(vocab_size,embedding_size)
self.decoder = nn.LSTM(embedding_size, n_hidden * 2, 1,batch_first=False)
self.fc = nn.Linear(n_hidden * 2, num_classes)
def forward(self, input_x, encoder_output, hn, cn):
embeded=self.embedding(input_x)
decoder_output, (decoder_h_n, decoder_c_n) = self.decoder(embeded.float().permute(1,0,2), (hn, cn))
decoder_output = decoder_output.permute(1, 0, 2)
encoder_output = encoder_output.permute(1, 0, 2)
# 下面是实现attention编码
# 计算分数score
decoder_output_score = decoder_output.bmm(encoder_output.permute(0,2,1))
# 计算权重at
at = nn.functional.softmax(decoder_output_score, dim=2)
# 计算新的context向量ct
ct = at.bmm(encoder_output)
# 拼接ct和decoder_ht
ht_joint = torch.cat((ct, decoder_output), dim=2)
# 做tanh计算
fc_joint = torch.tanh(self.att_joint(ht_joint))
# 全连接做预测
fc_out = self.fc(fc_joint)
# 实现attention编码结束
return fc_out, decoder_h_n, decoder_c_n
8. 最终模型
在训练时候,encoder的output、hn、cn作为decoder的的输入一部分。最终模型的输出和target数据(view(-1))计算loss。
pred = model(encoder_input, decoder_input, 1)
loss = criterion(pred.reshape(-1, vocab_size), decoder_t