记忆网络模型系列之End to End Memory Network
2018-01-19 21:55
453 查看
上文记忆网络介绍模型并非端到端的QA训练,该论文End-To-End Memory Networks就在上文的基础上进行端到端的模型构建,减少生成答案时需要事实依据的监督项,在实际应用中应用意义更大。
本文分为三个部分,分别是数据集处理、论文模型讲解及模型构造、模型训练。主要参考代码为MemN2N。
论文中使用了babi数据集,关于本数据集在文章Ask Me Anything: Dynamic Memory Networks for Natural Language Processing 阅读笔记及tensorflow实现中有详细介绍并有处理流程,因此在这里也不再赘述。
使用输入集合S={x1,x2,...xi,...,xn}表示上下文知识,使用输入向量q表示问题,使用输出向量aˆ表示预测答案。记忆网络模型通过对上下文集合S和问题向量q的数学变换,得到对应于问题的答案。
首先,上下文集合S通过隐含层矩阵Embedding A∈Rd∗v 得到记忆向量的编码向量 。同样的,问题向量q通过隐含层矩阵Embedding B∈Rd∗v 得到问题向量的编码向量u,然后计算两者的内积:
pi=Softmax(uTmi)
其中,Softmax(zi=ezi/∑j),那么 pi 就为输入向量的概率。
然后,每个输入xi 都有一个输出向量 ci,ci 和 mi得到的方式是类似的,ci 是通过隐含层矩阵Embedding C∈Rd∗v 得到的。将 pi与ci 相乘求和,得到答案向量的编码向量o。
o=∑ipici
答案向量的编码向量o以后,需要解码生成预测的答案,通过一个待训练矩阵W∈Rd∗v ,得到预测答案aˆ 。
aˆ=Softmax(W(o+u))
1、将uk与ok相加作为下一层的问题编码,即:
uk+1=uk+ok
2、每一层都有嵌入矩阵Ak,Ck来将x映射到记忆单元和编码单元。但是这样参数数量就会随模型层数的增加呈倍数增长,为了减少参数数量,使训练能够方便进行,论文中提出了两种减少参数的方法:
2.1相邻的嵌入矩阵相同,这样比着之前减少了一般参数,即
Ak+1=Ck+1
WT=CK
B=A1
2.2层间共享参数,即
A1=A2=...=AK
C1=C2=...=CK
论文中也提到2.1的方式比2.2的方式训练效果要好很多。
story:[None,10,7] –Sentences最多有10句话,每句话最多有7个单词。
query:[None,7] –q问题最多有7个单词。
m_emb_A:[None,10,7,20] –story通过一个[vocab_size, embedding_size]的嵌入矩阵。
q_emb:[None,7,20] –query通过一个[vocab_size,embedding_size]的嵌入矩阵。
u_0:[None,20] –q_emb通过位置编码,具体细节详见4.1章,得到u_0代表问题的向量表示。
u_temp:[None,1,20] –u_0拓展维度变为[None,20,1],并且将第一维和第二维进行transpose得到[None,1,20]。
m_A:[None,10,20] –得到10句话的向量表示。
dotted:[None,10] –将u_temp与m_A点乘,并求和,得到记忆单元中10句话的权重。
probs:[None,10] –得到softmax概率。
probs_temp:[None,1,10]
m_emb_C:[None,10,7,20] –同m_emb_A
m_C:[None,10,20] –同m_A
c_temp:[None,20,10]
o_k:[None,20] –得到输出编码向量
总体来说,端到端的记忆网络的提出,使记忆网络变得更加实用,不再需要对支持事实这一监督项,因此可用的数据集就变得更多。本篇代码使用的babi数据集,训练集和测试集各1000个,词表总共才30个,因此是一个极度简单的模型。因此在接下来的几篇文章中,将会采用较大的数据集对记忆网络以后发展的模型进行说明。
本文分为三个部分,分别是数据集处理、论文模型讲解及模型构造、模型训练。主要参考代码为MemN2N。
数据集处理
==论文中使用了babi数据集,关于本数据集在文章Ask Me Anything: Dynamic Memory Networks for Natural Language Processing 阅读笔记及tensorflow实现中有详细介绍并有处理流程,因此在这里也不再赘述。
模型讲解及构建
模型的结构如下图所示。图(a)是单层的模型,图(b)是多层模型(三层)。单层记忆网络
以图(a)为例,输入有两个部分,使用输入集合S={x1,x2,...xi,...,xn}表示上下文知识,使用输入向量q表示问题,使用输出向量aˆ表示预测答案。记忆网络模型通过对上下文集合S和问题向量q的数学变换,得到对应于问题的答案。
首先,上下文集合S通过隐含层矩阵Embedding A∈Rd∗v 得到记忆向量的编码向量 。同样的,问题向量q通过隐含层矩阵Embedding B∈Rd∗v 得到问题向量的编码向量u,然后计算两者的内积:
pi=Softmax(uTmi)
其中,Softmax(zi=ezi/∑j),那么 pi 就为输入向量的概率。
然后,每个输入xi 都有一个输出向量 ci,ci 和 mi得到的方式是类似的,ci 是通过隐含层矩阵Embedding C∈Rd∗v 得到的。将 pi与ci 相乘求和,得到答案向量的编码向量o。
o=∑ipici
答案向量的编码向量o以后,需要解码生成预测的答案,通过一个待训练矩阵W∈Rd∗v ,得到预测答案aˆ 。
aˆ=Softmax(W(o+u))
多层记忆网络
如图(b)所示,多层记忆网络和单层的基本结构是类似的,有一些小的细节需要改变,以将几个单层网络连接起来。1、将uk与ok相加作为下一层的问题编码,即:
uk+1=uk+ok
2、每一层都有嵌入矩阵Ak,Ck来将x映射到记忆单元和编码单元。但是这样参数数量就会随模型层数的增加呈倍数增长,为了减少参数数量,使训练能够方便进行,论文中提出了两种减少参数的方法:
2.1相邻的嵌入矩阵相同,这样比着之前减少了一般参数,即
Ak+1=Ck+1
WT=CK
B=A1
2.2层间共享参数,即
A1=A2=...=AK
C1=C2=...=CK
论文中也提到2.1的方式比2.2的方式训练效果要好很多。
模型构建代码
按照代码的逻辑捋一下训练时需要注意的重要参数:story:[None,10,7] –Sentences最多有10句话,每句话最多有7个单词。
query:[None,7] –q问题最多有7个单词。
m_emb_A:[None,10,7,20] –story通过一个[vocab_size, embedding_size]的嵌入矩阵。
q_emb:[None,7,20] –query通过一个[vocab_size,embedding_size]的嵌入矩阵。
u_0:[None,20] –q_emb通过位置编码,具体细节详见4.1章,得到u_0代表问题的向量表示。
u_temp:[None,1,20] –u_0拓展维度变为[None,20,1],并且将第一维和第二维进行transpose得到[None,1,20]。
m_A:[None,10,20] –得到10句话的向量表示。
dotted:[None,10] –将u_temp与m_A点乘,并求和,得到记忆单元中10句话的权重。
probs:[None,10] –得到softmax概率。
probs_temp:[None,1,10]
m_emb_C:[None,10,7,20] –同m_emb_A
m_C:[None,10,20] –同m_A
c_temp:[None,20,10]
o_k:[None,20] –得到输出编码向量
with tf.variable_scope(self._name): # Use A_1 for thee question embedding as per Adjacent Weight Sharing # 将问题变量queries通过嵌入矩阵A_1得到问题向量q_emb # 然后将q_emb与其位置编码变量_encoding加权求和得到u_0 # self._encoding是位置编码向量,就是对词出现的顺序进行编码,具体细节详见4.1章 q_emb = tf.nn.embedding_lookup(self.A_1, queries) u_0 = tf.reduce_sum(q_emb * self._encoding, 1) u = [u_0] # 总共三层,待训练的参数有四个矩阵,分别是A_1,C_1,C_2,C_3 for hopn in range(self._hops): # 对于第一层,记忆单元的嵌入矩阵为A_1 if hopn == 0: m_emb_A = tf.nn.embedding_lookup(self.A_1, stories) m_A = tf.reduce_sum(m_emb_A * self._encoding, 2) # 对于第二层和第三层,记忆单元的嵌入矩阵分别为C_1和C_2 else: with tf.variable_scope('hop_{}'.format(hopn - 1)): m_emb_A = tf.nn.embedding_lookup(self.C[hopn - 1], stories) m_A = tf.reduce_sum(m_emb_A * self._encoding, 2) # hack to get around no reduce_dot u_temp = tf.transpose(tf.expand_dims(u[-1], -1), [0, 2, 1]) dotted = tf.reduce_sum(m_A * u_temp, 2) # Calculate probabilities probs = tf.nn.softmax(dotted) probs_temp = tf.transpose(tf.expand_dims(probs, -1), [0, 2, 1]) with tf.variable_scope('hop_{}'.format(hopn)): m_emb_C = tf.nn.embedding_lookup(self.C[hopn], stories) m_C = tf.reduce_sum(m_emb_C * self._encoding, 2) c_temp = tf.transpose(m_C, [0, 2, 1]) o_k = tf.reduce_sum(c_temp * probs_temp, 2) # Dont use projection layer for adj weight sharing # u_k = tf.matmul(u[-1], self.H) + o_k u_k = u[-1] + o_k # nonlinearity if self._nonlin: u_k = nonlin(u_k) u.append(u_k) # Use last C for output (transposed) with tf.variable_scope('hop_{}'.format(self._hops)): return tf.matmul(u_k, tf.transpose(self.C[-1], [1,0]))
模型训练
模型训练部分就是一些熟悉的代码,这里不再赘述,大概经过100个epochs的训练,训练效果如下:总体来说,端到端的记忆网络的提出,使记忆网络变得更加实用,不再需要对支持事实这一监督项,因此可用的数据集就变得更多。本篇代码使用的babi数据集,训练集和测试集各1000个,词表总共才30个,因此是一个极度简单的模型。因此在接下来的几篇文章中,将会采用较大的数据集对记忆网络以后发展的模型进行说明。
相关文章推荐
- 记忆网络之End-To-End Memory Networks
- 论文:记忆网络之Gated End-to-End Memory Networks
- 记忆网络之Gated End-To-End Memory Networks
- 记忆网络系列之Key Value Memory Network
- Long-Short Memory Network(LSTM长短期记忆网络)
- End to End Memory network
- 记忆网络系列之Recurrent Entity Network
- End-to-End Memory Network
- 技术系列之 网络模型(一)基础篇
- 技术系列之 网络模型(二)
- An End-to-End Trainable Neural Network...笔记
- End-To-End Memory Networks
- CRT detected that the application wrote to memory after end of heap buffer
- [行为识别]RPAN:An end-to-end recurrent pose-attention network for action recognition
- 理解长短期记忆(Long Short Term Memory, LSTM)模型(colah 原文翻译)
- Beej’s Guide Network to Programming 系列连载01
- Alamofire源码解读系列(七)之网络监控(NetworkReachabilityManager)
- CRT detected that the application wrote to memory after end of heap buffer 问题(转)
- 技术系列之 网络模型(二)
- 技术系列之 网络模型(三)多路复用模型