写在前面
Memory Networks经典论文阅读笔记,会包括Vanilla Memory Networks及其各种变形以及在NLP领域的应用。主要涉及一下论文:
- Memory Networks (Facebook AI Research/2015)
- End-To-End Memory Networks(2015)
- Key-Value Memory Networks for Directly Reading Documents(2016)
- Ask Me Anything: Dynamic Memory Networks for Natural Language Processing (2016)
- Dynamic Memory Networks for Visual and Textual Question Answering (2016)
1、Memory Networks
对应论文Memory Networks (Facebook AI Research/2015)
Memory Networks提出的最大卖点就是具备长期记忆(long-term memory),虽然当时RNN在文本处理领域十分有效,但是其对信息的长期记忆能力并不理想。Memory Networks的长期记忆思路其实也非常简单暴力,直接采用额外的记忆模块来保存之前的信息,而不是通过cell之间的hidden state传递。
框架
Memory Networks主要由一个记忆模块 m m m和四个组件 I , G , O , R I, G, O, R I,G,O,R构成
- I: (input feature map)
- 用于将输入转化为网络里内在向量表示。(可以利用标准预处理,例如,文本输入的解析,共参考和实体解析。 还可以将输入编码为内部特征表示,例如,从文本转换为稀疏或密集特征向量)
- G: (generalization)
- 用于更新记忆。简单的可以直接插入记忆数组中,复杂的可以将当前的记忆用于更新先前的记忆
- O: (output feature map)
- 从记忆里结合输入,把合适的记忆抽取出来,返回一个向量。每次获得一个向量,代表了一次推理过程。
- R: (response)
- 将上述向量转化回所需的格式,比如文字或者answer。
流程
考虑问答任务,Memory network的工作流程为:
- 给定一段输入x,通过组件I将x映射到向量空间
- 通过组件G更新记忆。论文中只是简单地将输入的向量插入到记忆槽中去。 m i = G ( m i , I ( x ) , m ) , ∀ i m_{i}=G\left(m_{i}, I(x), m\right), \forall i mi=G(mi,I(x),m),∀i
- 利用组件O计算output feature。
o
=
O
(
I
(
x
)
,
m
)
\mathrm{o}=\mathrm{O}(\mathrm{I}(\mathrm{x}), \mathrm{m})
o=O(I(x),m)
– 计算所求问题与记忆槽中的元素的相似度,可以返回一条或多条最相似的记忆
o 1 = O 1 ( x , m ) = arg max i = 1 , … , N s O ( x , m i ) o_{1}=O_{1}(x, \mathbf{m})=\underset{i=1, \ldots, N}{\arg \max } s_{O}\left(x, \mathbf{m}_{i}\right) o1=O1(x,m)=i=1,…,NargmaxsO(x,mi) o 2 = O 2 ( x , m ) = arg max i = 1 , … , N s O ( [ x , m o 1 ] , m i ) o_{2}=O_{2}(x, \mathbf{m})=\underset{i=1, \ldots, N}{\arg \max } s_{O}\left(\left[x, \mathbf{m}_{o_{1}}\right], \mathbf{m}_{i}\right) o2=O2(x,m)=i=1,…,NargmaxsO([x,mo1],mi) - 对output feature进行解码,返回输出。
r
=
argmax
w
∈
W
s
R
(
[
q
,
o
1
,
o
2
]
,
w
)
r=\operatorname{argmax}_{w \in W} s_{R}\left(\left[q, o_{1}, o_{2}\right], w\right)
r=argmaxw∈WsR([q,o1,o2],w)
s
R
(
x
,
y
)
=
x
U
U
T
y
s_{R}(x, y)=x U U^{T} y
sR(x,y)=xUUTy
损失函数
采用margin ranking loss,这个与支持向量机的损失函数类似。 ∑ f ‾ ≠ m o 1 max ( 0 , γ − s O ( x , m o 1 ) + s O ( x , f ‾ ) ) + \sum_{\overline{f} \neq \mathbf{m}_{o_{1}}} \max \left(0, \gamma-s_{O}\left(x, \mathbf{m}_{o_{1}}\right)+s_{O}(x, \overline{f})\right)+ f=mo1∑max(0,γ−sO(x,mo1)+sO(x,f))+ ∑ f ‾ ′ ≠ m o 2 max ( 0 , γ − s O ( [ x , m o 1 ] , m o 2 ] ) + s O ( [ x , m o 1 ] , f ‾ ′ ] ) ) + \sum_{\overline{f}^{\prime} \neq \mathbf{m}_{o_{2}}} \max \left(0, \gamma-s_{O}\left(\left[x, \mathbf{m}_{o_{1}}\right], \mathbf{m}_{o_{2}}\right]\right)+s_{O}\left(\left[x, \mathbf{m}_{o_{1}}\right], \overline{f}^{\prime}\right] ) )+ f′=mo2∑max(0,γ−sO([x,mo1],mo2])+sO([x,mo1],f′]))+ ∑ f ‾ ′ ≠ m o 2 max ( 0 , γ − s O ( [ x , m o 1 ] , m o 2 ] ) + s O ( [ x , m o 1 ] , f ‾ ′ ] ) ) + \sum_{\overline{f}^{\prime} \neq \mathbf{m}_{o_{2}}} \max \left(0, \gamma-s_{O}\left(\left[x, \mathbf{m}_{o_{1}}\right], \mathbf{m}_{o_{2}}\right]\right)+s_{O}\left(\left[x, \mathbf{m}_{o_{1}}\right], \overline{f}^{\prime}\right] ) )+ f′=mo2∑max(0,γ−sO([x,mo1],mo2])+sO([x,mo1],f′]))+
一些扩展
使用word-level的输入
如果输入不是句子级别的而是词语级别的,我们需要另外增加一个分词组件。 seg ( c ) = W seg ⊤ U S Φ seg ( c ) \operatorname{seg}(c)=W_{\operatorname{seg}}^{\top} U_{S} \Phi_{\operatorname{seg}}(c) seg(c)=Wseg⊤USΦseg(c)该分词函数是可以在训练过程中学习得到的
Huge Memory处理
如果需要处理的memory太大:
- 可以按 entity 或者 topic 来存储 memory,这样 G 就不用在整个 memories 上操作了
- 如果 memory 满了,可以引入 forgetting 机制,替换掉没那么有用的 memory,H 函数可以计算每个 memory 的分数,然后重写
- 还可以对单词进行 hashing,或者对 word embedding 进行聚类,总之是把输入 I(x) 放到一个或多个 bucket 里面,然后只对相同 bucket 里的 memory 计算分数
处理未登录词
使用语言模型,通过上下文词语来预测未登录词位置的词,然后就可以认为未登陆词与预测出的词的意思相近
小结
- 记忆网络是一个组件形式的模型,每个模型相互对立又相互影响。每个组件没有固定的模型,可以是传统的模型,也可以是神经网络
- Loss2 无法 backpropagate 到模型的左边部分,BP 过程到 m 就停了,并不能 end-to-end 进行训练
2、End-To-End Memory Networks
对应论文End-To-End Memory Networks(2015)
上一节提到原始记忆网络受限于反向传播不能实现端到端的训练,因此在本文中改进提出了一种端到端的记忆网络。其主要思想跟attention mechanism很像。论文中提出了单层和多层两种架构,多层其实就是将单层网络进行stack。我们先来看一下单层模型的架构
Single Layer
模型的输入为:
- Sentence { x i } \left\{x_{i}\right\} {xi}
- Question q q q
- Answer a a a
一图流如下
- 映射到向量空间: K e y : { x i } ⟶ A { m i } Key: \left\{x_{i}\right\} \stackrel{A}{\longrightarrow}\left\{m_{i}\right\} Key:{xi}⟶A{mi} Q u e r y : q ⟶ B u Query: q \stackrel{B}{\longrightarrow} u Query:q⟶Bu V a l u e : { x i } ⟶ C { c i } Value: \left\{x_{i}\right\} \stackrel{C}{\longrightarrow}\left\{c_{i}\right\} Value:{xi}⟶C{ci}
- 计算attention distribution p i = S o f tmax ( u T m i ) p_{i}=S o f \operatorname{tmax}\left(u^{T} m_{i}\right) pi=Softmax(uTmi)
- 计算context vector o = ∑ i p i c i o=\sum_{i} p_{i} c_{i} o=i∑pici
- 预测答案 a ^ = Softmax ( W ( o + u ) ) \hat{a}=\operatorname{Softmax}(W(o+u)) a^=Softmax(W(o+u))
- 计算损失以及更新参数直到收敛
Multiple Layer
理解了上述单层框架之后,多层结构也很简单,相当于做多次attention操作,不过注意上层的query向量是由下层的输出向量和query向量得到的(可以简单地拼接,求和,也可以用MLP、RNN)。
网络参数设置细节
对于多层网络参数设置问题,文章中提出两种思路:
- Adjacent: 这种方法让相邻层之间的A=C。也就是说Ak+1=Ck,此外W等于顶层的C,B等于底层的A,这样就减少了一半的参数量。
- Layer-wise(RNN-like): 与RNN相似,采用完全共享参数的方法,即各层之间参数均相等。Ak=…=A2=A1,Ck=…=C2=C1。由于这样会大大的减少参数量导致模型效果变差,所以提出一种改进方法,即令uk+1=Huk+ok,也就是在每一层之间加一个线性映射矩阵H。
3、Key-Value Memory Networks
对应论文 Key-Value Memory Networks for Directly Reading Documents(2016)
用于QA任务。作者首先是比较了基于知识库KB和基于document的问答系统的优劣,接着提出了本文的模型:Key-Value MemNN
Key hashing
根据问题 x x x从知识源(知识图谱,维基百科等)中预先选择出N个key-value对存储在memory中, ( k h 1 , v h 1 ) , … , ( k h N , v h N ) \left(k_{h_{1}}, v_{h_{1}}\right), \ldots,\left(k_{h_{N}}, v_{h_{N}}\right) (kh1,vh1),…,(khN,vhN)。并且要求选中的key中至少有一个词和问题中的相同(利用倒排索引的方法检索)。
Key addressing
计算问题和每个key之间的相似度来判断memory中key-value对和问题之间的相关可能性。 p h i = Softmax ( A Φ X ( x ) ⋅ A Φ K ( k h i ) ) p_{h_{i}}=\operatorname{Softmax}\left(A \Phi_{X}(x) \cdot A \Phi_{K}\left(k_{h_{i}}\right)\right) phi=Softmax(AΦX(x)⋅AΦK(khi))
Value reading
使用加权求和读取value,得到输出向量 o o o o = ∑ i p h i A Φ V ( v h i ) o=\sum_{i} p_{h_{i}} A \Phi_{V}\left(v_{h_{i}}\right) o=i∑phiAΦV(vhi)
Hops iteration
如上图,根据输出
o
o
o更新
q
2
=
R
1
(
q
+
o
)
q_{2}=R_{1}(q+o)
q2=R1(q+o),迭代Key Addressing
与Value Reading
过程实现memory access process,最后第 H hop后得到
q
h
q_{h}
qh+1, 计算所有可能答案的分数
a
^
=
argmax
i
=
1
,
…
,
C
Softmax
(
q
H
+
1
⊤
B
Φ
Y
(
y
i
)
)
\hat{a}=\operatorname{argmax}_{i=1, \ldots, C} \operatorname{Softmax}\left(q_{H+1}^{\top} B \Phi_{Y}\left(y_{i}\right)\right)
a^=argmaxi=1,…,CSoftmax(qH+1⊤BΦY(yi))
Key-Value 实现
- KB Triple
- KB,针对 triples (subject, relation, object),key 是 subject 和 relation,value 是 object。然后需要将 subject 和 object 交换,relation 取反再存一次(KB 大小翻倍)
- Sentence Level
- document,每个 memory slot 编码一个句子的情况,key 和 value 都是用 bag-of-words 的形式编码的整个句子(和标准 MemNN 里一样)
- Window Level
- document,分割成 W 个词的窗口(中心词是实体),key 是用 bag-of-words 编码后的整个窗口,value 是中心词
- Window + Center Encoding
- document,和 Window Level 的区别就是使用不同 feature 对中心词和窗口中除了中心词以外的词进行编码
- Window + Title
- document,key 还是上面两条提到的窗口,value 是 document 的 title,另外也保留 Window Level 里的所有 memory 对
MovieQA数据集
pass
4、Dynamic Memory Networks
对应论文Ask Me Anything: Dynamic Memory Networks for Natural Language Processing (2016)
论文认为大多数NLP任务都可以转化为QA任务,并给出了具体例子。于是提出一种用于解决QA任务的模型Dynamic Memory Networks,框架如下图所示。
Input Module
输入可以是一个/多个句子,一篇/几篇文章,包含语境信息和知识库等,将这些原始语料输入经过一个GRU编码后得到隐状态表示。
h
t
=
R
N
N
(
L
[
w
t
]
,
h
t
−
1
)
h_{t}=R N N\left(L\left[w_{t}\right], h_{t-1}\right)
ht=RNN(L[wt],ht−1)
如果是单个句子,就输出每个词的 hidden state;如果是多个句子,就输出每个句子 EOS 标记对应的 hidden state。
Question Module
与Input Module类似,也是将输入的问句进行编码,使用的也是GRU编码器
q
t
=
G
R
U
(
[
L
[
w
t
Q
]
,
q
t
−
1
)
q_{t}=G R U\left(\left[L\left[w_{t}^{Q}\right], q_{t-1}\right)\right.
qt=GRU([L[wtQ],qt−1)
输出是 final hidden state
Input Module和Question Module共享参数矩阵
Episodic Memory Module
输入为Input Module和Question Module两个模块的输出,这个模块主要有三个组件:internal memory, attention mechanism, memory update mechanism。
Attention mechanism
输入是本时刻的输入c,前一时刻的记忆m和问题q。首先计算相互之间的相似度作为特征向量传入一个两层的神经网络,最终计算出来的值就是门控函数的值,也就是该输入与问题之间的相似度。
g
t
i
=
G
(
c
t
,
m
i
−
1
,
q
)
g_{t}^{i}=G\left(c_{t}, m^{i-1}, q\right)
gti=G(ct,mi−1,q)
其中G是一个两层dense网络
G
(
c
,
m
,
q
)
=
σ
(
W
(
2
)
tanh
(
W
(
1
)
z
(
c
,
m
,
q
)
+
b
(
1
)
)
+
b
(
2
)
)
\begin{array}{l}{G(c, m, q)=} {\sigma\left(W^{(2)} \tanh \left(W^{(1)} z(c, m, q)+b^{(1)}\right)+b^{(2)}\right)}\end{array}
G(c,m,q)=σ(W(2)tanh(W(1)z(c,m,q)+b(1))+b(2))
Memory Update Mechanism:记忆更新
计算出门控函数的值之后,根据其大小对记忆进行更新。更新方法就是GRU算出的记忆乘以门控值,再加上原始记忆乘以1-门控值。 h t i = g t i G R U ( c t , h t − 1 i ) + ( 1 − g t i ) h t − 1 i h_{t}^{i}=g_{t}^{i} G R U\left(c_{t}, h_{t-1}^{i}\right)+\left(1-g_{t}^{i}\right) h_{t-1}^{i} hti=gtiGRU(ct,ht−1i)+(1−gti)ht−1i e i = h T C i e^{i}=h_{T_{C}}^{i} ei=hTCi m i = G R U ( e i , m i − 1 ) m^{i}=G R U\left(e^{i}, m^{i-1}\right) mi=GRU(ei,mi−1)
Answer Module
使用GRU最为本模块的模型,根据memory模块最后的输出向量(将其作为初始隐层状态),然后输入使用的是问题和上一时刻的输出值连接起来(每个时刻都是用q向量)。并使用交叉熵损失函数作为loss进行反向传播训练。
y
t
=
S
o
f
t
max
(
W
(
a
)
a
t
)
y_{t}=S o f t \max \left(W^{(a)} a_{t}\right)
yt=Softmax(W(a)at)
a
t
=
G
R
U
(
[
y
t
−
1
,
q
]
,
a
t
−
1
)
a_{t}=G R U\left(\left[y_{t-1}, q\right], a_{t-1}\right)
at=GRU([yt−1,q],at−1)
**
5、DMN+
对应论文:Dynamic Memory Networks for Visual and Textual Question Answering (2016)
本文是对DMN的改进,提出原始DMN存在几个问题:
- 输入模块只考虑了过去信息,没考虑到将来信息
- 只用 word level 的 GRU,很难记忆远距离句子之间的信息
- 只考虑了文本输入,无法扩展到其他类型输入(如图片)
基于以上,DMN+对DMN的两个部分进行了改进:input module以及attention机制与memory更新。
Input Module for Text QA
把DMN中的单向GRU换成了两个组分:sentence reader和Bi-GRU(也叫input fusion layer)。sentence reader 得到每个句子的 embedding,input infusion layer 把每个句子的 embedding 放入另一个 GRU 中,得到 context 信息,来解决句子远距离依赖的问题。
其中,sentence reader 使用的是 positional encoding,即对句子中每个单词进行位置编码,然后加权求和。使用位置编码的原因是 GRU/LSTM 编码句子计算量大并且容易过拟合。
Input Module for VQA
对于visual question answering,作者提出了另一种input module,由三个部分组成:
- Local region feature extraction
- Visual feature embedding
- Input fusion layer
The Episodic Memory Module
Attention Mechanism
仍然是人工构造特征向量来计算 attention,但与之前版本的 DMN 相比更为简化,省去了两项含有参数的部分,减少了计算量。另外与 DMN 不同的是,gate 值不是简单的二层前馈网络的结果,而是接着计算了一个 sofmax 评分向量。 z i t = [ f i ↔ ∘ q ; f i ↔ ∘ m t − 1 ; ∣ f i → − q ∣ ; ∣ f i → − m t − 1 ∣ ] z_{i}^{t}=\left[\stackrel{\leftrightarrow}{f_{i}} \circ q ; \stackrel{\leftrightarrow}{f_{i}} \circ m^{t-1} ;\left|\overrightarrow{f_{i}}-q\right| ;\left|\overrightarrow{f_{i}}-m^{t-1}\right|\right] zit=[fi↔∘q;fi↔∘mt−1;∣∣∣fi−q∣∣∣;∣∣∣fi−mt−1∣∣∣] Z i t = W ( 2 ) tanh ( W ( 1 ) z i t + b ( 1 ) ) + b ( 2 ) Z_{i}^{t}=W^{(2)} \tanh \left(W^{(1)} z_{i}^{t}+b^{(1)}\right)+b^{(2)} Zit=W(2)tanh(W(1)zit+b(1))+b(2) g i t = exp ( Z i t ) ∑ k = 1 M i exp ( Z k t ) g_{i}^{t}=\frac{\exp \left(Z_{i}^{t}\right)}{\sum_{k=1}^{M_{i}} \exp \left(Z_{k}^{t}\right)} git=∑k=1Miexp(Zkt)exp(Zit)
接下去计算context vector,两种方案,一种是 soft attention,简单的加权求和,另一种是 attention based GRU。
AttGRU 考虑了输入 facts 的位置和顺序信息(position and ordering),或者说是时序信息。在得到 attention 后,把 attention 作为 gate,如上图,把传统 GRU 中的 update gate
u
i
u_{i}
ui 替换成了 attention 的输出
g
i
g_{i}
gi,这样 gate 就包含了 question 和前一个 episode memory 的知识,更好的决定了把多少 state 信息传递给下一个 RNN cell。同时这也大大简化了 DMN 版本的 context 计算。
h
i
=
g
i
t
∘
h
~
i
+
(
1
−
g
i
t
)
∘
h
i
−
1
h_{i}=g_{i}^{t} \circ \tilde{h}_{i}+\left(1-g_{i}^{t}\right) \circ h_{i-1}
hi=git∘h~i+(1−git)∘hi−1
h
^
\hat{h}
h^ 是更新的 state,
h
i
−
1
h_{i−1}
hi−1 是传入的上一时刻的 state,
g
i
g_{i}
gi 是 attention value,是一个由 softmax 产生的标量(scalar)而不是 sigmoid 激活产生的 vector
u
i
u_{i}
ui,context vector 是 GRU 的 final hidden state。
Memory Update Mechanism
DMN 中 memory 更新采用以 q 向量为初始隐层状态的 GRU 进行更新,用同一套权重,这里替换成了一层 ReLU 层,实际上简化了模型。 m t = Re L U ( W t [ m t − 1 ; c t ; q ] + b ) m^{t}=\operatorname{Re} L U\left(W^{t}\left[m^{t-1} ; c^{t} ; q\right]+b\right) mt=ReLU(Wt[mt−1;ct;q]+b)