pytorch教程 聊天机器人(详细注释&attention&rnn输入输出shape等知识点...

最近可能要用到seq2seq模型去解决一些轨迹预测的问题,拿pytorch教程的聊天机器人练了练手。

原文中教程已经写的比较详尽了,在此对原文教程进行一些补充说明,可能更加方便向我这样的小白入门学习。

本文是对教程的补充说明,并没有照搬所有教程中的代码,中文教程写的很不错啦,链接在下面。

 

pytorch中文教程http://www.pytorch123.com/FifthSection/Chatbot/

我的git地址:https://github.com/jamjar102/pytorch_chatbot_2  这里面代码写了一些注释方便像我这样的小白follow作者的思想,并且带有数据集

数据集:我给一个网盘吧,不方便科学学习的小伙伴可以快速下载:

链接:https://pan.baidu.com/s/1XWESTyoPYv_0j-gk21Skpg 
提取码:f8r6 

(觉得百度云更慢的可以按照教程提供的地址下载

 


一)在教程->2.2 加载和清洗数据中

这块调用了normalizeString()函数,这个函数其实并不是库函数,但是原文中并没有提供

需要自己实现一下,代码如下:

import re
def normalizeString(string):
    string=re.sub("([?,;.!<>])",repl=r" \1",string=string)
    string=re.sub("[^a-zA-Z.?!]+",repl=" ",string=string)
    string=re.sub("\s+",repl=' ',string=string)
    return string.strip()

这个函数主要是进行大小写转换,去除非法字符的,就是normalize一下

 

二) 在教程->3.为模型准备数据中

在outputVar()函数中,声明的mask变量应该转成bool型,教程中写的是mask=torch.ByteTensor(mask),如果这么写会报warning,(在pycharm中运行训练时间大幅增长):

received a mask with dtype torch.uint8, this behavior is now deprecated,please use a mask with dtype torch.bool instead. 

代码修改成如下即可:

def outputVar(l, voc):
    indexes_batch = [indexesFromSentence(voc, sentence) for sentence in l]
    max_target_len = max([len(indexes) for indexes in indexes_batch])
    padList = zeroPadding(indexes_batch)
    mask = binaryMatrix(padList)
    mask = torch.BoolTensor(mask)
    padVar = torch.LongTensor(padList)
    return padVar, mask, max_target_len

 

三)GRU 组件输入输出shape

在CNN中,batch的position=0,RNN中position=1

输入数据input的shape为(sentence_max_length,batch_size,1)其中1的含义是:由于每个词都是做了word2index,所以在准备数据的时候这块的维度就是1

在model encoderRNN定义中,forward前向函数中,进行了如下操作

 embedded = self.embedding(input_seq)

此时shape变成了,(sentence_max_length,batch_size,hidden_size), 因为原文中作者设定了embedding后的维度为hidden_size

 

RNN的输出OUT的shape =(max_length,batch_size,hidden_size * num_directions) 这块原文写错了,最后一项的维度应该是hidden_size * num_directions

由于在encoder中,定义的RNN是bidirectional的,所以第三维由两个GRU的隐层输出拼接而成。[:hidden_size]为正向的隐层输出,[hidden_size:]为反向的隐层输出

 

 def forward(self, input_seq, input_lengths, hidden=None):
        # 将单词索引转换为词向量
        embedded = self.embedding(input_seq)  #embedding
        # 为RNN模块打包填充batch序列
        packed = nn.utils.rnn.pack_padded_sequence(embedded, input_lengths)  # todo batch 需要进行pack_padded_sequence 和  nn.utils.rnn.pad_packed_sequence
        # 正向通过GRU
        outputs, hidden = self.gru(packed, hidden)
        # 打开填充
        outputs, _ = nn.utils.rnn.pad_packed_sequence(outputs)
        # 总和双向GRU输出
        outputs = outputs[:, :, :self.hidden_size] + outputs[:, : ,self.hidden_size:]  # todo 双向RNN,output 维度为[seq_len,  batch,  hidden_size*bidirectional]
        # 返回输出和最终隐藏状态  todo 对位相加(把双向的同一个位置的两个GRU单元hidden输出 相加)
        return outputs, hidden

RNN的隐层输出的shape=(n_layers x num_directions,batch_size,hidden_size)

隐层输出就是最后GRU单元的hidden输出,所以只和RNN模型的层数、方向 ,batch_size,以及一个hidden的位数有关

 

四)Luong attention机制

 

快速了解attention机制看这个视频可以,https://blog.csdn.net/qq_43409114/article/details/105889114 ,随手b站上找了一个视频,看了看可以讲清楚

简而言之就是如果不使用attention 机制,decoder的 input会吃encoder最后的hidden输出,如果只用这一个输出表示前面所有信息,想想就很不靠谱

所以采用了attention机制,decoder的一个GRU单元的hidden输出会和前面encoder的每一个hidden输出进行运算,得到权重,从而找到“更应该关注的那个词”

利用这个attention权重和docoder这个GRU单元的hidden输出共同作用得到target词汇

 

关于BahdanauAttention和Luong attention机制可以看这篇 https://blog.csdn.net/qq_43409114/article/details/105889114 

对论文的解读还是写的十分清楚的

 

五)train函数中有个小bug,decoder前面+self.即可

 


 

虽然我跟我机器人对话过程十分尴尬

但是最起码可以跑了嘛

能跑就行 能跑就行,哈哈哈哈哈哈

如果有什么问题困扰你,请留言,让那个问题来困扰我们所有人

如果本文中有什么写错的地方,欢迎各位指正

 

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值