GLMP 代码 详细注释

这篇博客详细解析了GLMP(GLOBAL-TO-LOCAL MEMORY POINTER NETWORKS)的实现,主要涵盖ContextRNN、ExternalKnowledge和LocalMemoryDecoder等模型组件,以及GLMP的Encoder&Decoder、评估和性能计算等方面,内容包括已验证的代码注释。
摘要由CSDN通过智能技术生成

GLMP 缩写来自论文 GLOBAL-TO-LOCAL MEMORY POINTER NETWORKS
FOR TASK-ORIENTED DIALOGUE

下面是它代码的详细注释(已跑通)

3.1 模型

3.1.1 ContextRNN
class ContextRNN(nn.Module):
    def __init__(self, input_size, hidden_size, dropout, n_layers=1):
        #初始化设置参数
		super(ContextRNN, self).__init__()      
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.n_layers = n_layers     
        self.dropout = dropout
        #nn.Dropout:参数为float类型,将元素置0的概率
        self.dropout_layer = nn.Dropout(dropout)
        #nn.Embedding:参数分别为(单词个数 词向量维度 遇到PAD_token输出0)
        #此处可看出embedding词向量的维度和hidden的维度相同
        self.embedding = nn.Embedding(input_size, hidden_size, padding_idx=PAD_token)
		#调用pytorch中的GRU模块,设置网络为双向GRU
        self.gru = nn.GRU(hidden_size, hidden_size,
                          n_layers, dropout=dropout, bidirectional=True)
        self.W = nn.Linear(2*hidden_size, hidden_size)

    def get_state(self, bsz):
        """Get cell states and hidden states."""
        return _cuda(torch.zeros(2, bsz, self.hidden_size))

    def forward(self, input_seqs, input_lengths, hidden=None):
        # Note: we run this all at once (over multiple batches of multiple sequences)
        #contiguous函数返回一个内存连续的tensor
        #view函数返回一个tensor,必须有与原tensor相同的数据和相同数目的元素,但可以有不同的大小。
        #一个tensor必须是连续的contiguous()才能被查看。
        #两个函数联合作用将embedding的维度调整成一句一行
        embedded = self.embedding(input_seqs.contiguous().view(input_seqs.size(0),
                                                               -1).long()) 
        embedded = embedded.view(input_seqs.size()+(embedded.size(-1),))
        embedded = torch.sum(embedded, 2).squeeze(2) 
        embedded = self.dropout_layer(embedded)
        #初始化hidden
        hidden = self.get_state(input_seqs.size(1))
        if input_lengths:
            embedded = nn.utils.rnn.pack_padded_sequence(embedded, input_lengths, batch_first=False)
        outputs, hidden = self.gru(embedded, hidden)
        if input_lengths:
           outputs, _ = nn.utils.rnn.pad_packed_sequence(outputs, batch_first=False)   
        hidden = self.W(torch.cat((hidden[0], hidden[1]), dim=1)).unsqueeze(0)
        outputs = self.W(outputs)
        return outputs.transpose(0,1), hidden
3.1.2 ExternalKnowledge
class ExternalKnowledge(nn.Module):
    def __init__(self, vocab, embedding_dim, hop, dropout):
        #ExternalKnowledge的工作原理类似于MemoryNetwork
        super(ExternalKnowledge, self).__init__()
        self.max_hops = hop#跳数
        self.embedding_dim = embedding_dim
        self.dropout = dropout
        self.dropout_layer = nn.Dropout(dropout) 
        for hop in range(self.max_hops+1):#针对每一跳都初始化
            #nn.Embedding:单词个数 词向量维度 遇到PAD_token输出0
            C = nn.Embedding(vocab, embedding_dim, padding_idx=PAD_token)
            #将值用均值为0,方差为0.1的正态分布填充
            C.weight.data.normal_(0, 0.1)
            ##将一个child module添加到当前model,被添加的module可以通过name属性来获取。
            self.add_module("C_{}".format(hop), C)
        #定义查询C的方法?通过C_{i}来查询
        self.C = AttrProxy(self, "C_")
        #定义softmax为单维度的softmax
        self.softmax = nn.Softmax(dim=1)
        self.sigmoid = nn.Sigmoid()
        #一维卷积函数Conv1d:参数分别为(进 出通道 卷积核的大小 输入的每一条边补充0的层数)
        self.conv_layer = nn.Conv1d(embedding_dim, embedding_dim, 5, padding=2)

    def add_lm_embedding(self, full_memory, kb_len, conv_len, hiddens):
        #将hiddens按照kb_len的顺序加入full_memory矩阵
        for bi in range(full_memory.size(0)):
            start, end = kb_len[bi], kb_len[bi]+conv_len[bi]
            full_memory[bi, start:end, :] = full_memory[bi, start:end, :] + hiddens[bi, :conv_len[bi], :]
        return full_memory

    def load_memory(self, story, kb_len, conv_len, hidden, dh_outputs):
        # Forward multiple hop mechanism
        #squeeze函数:把第一个维度(维度为1)挤掉
        u = [hidden.squeeze(0)]
        story_size = story.size()
        self.m_story = []
        for hop in range(self.max_hops):#循环K跳来计算Attention权重
            #求c^k_i
            #把外部知识的三元组挤成一个向量
			embed_A = self.C[hop](story.contiguous().view(story_size[0], -1))#.long()) # b * (m * s) * e
            embed_A = embed_A.view(story_size+(embed_A.size(
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值