原文https://www.hankcs.com/nlp/parsing/deep-biaffine-attention-for-neural-dependency-parsing.html
这是斯坦福专攻Dependency Parsing的博士生Dozat在ICLR 2017上的论文,拿到了graph-based方法中的最高分,改进版还拿到了CoNLL 2017 Shared Task的第一。
基于图的依存句法分析需要解决两个问题:1、哪两个节点连依存弧;2、弧的标签是什么。NN方法使用分类器来解决这两个问题,记feature detector得到的特征向量为riri。
arc得分
这是一个不定类别的多分类问题。若句子中有nn个单词,包含虚根ROOT在内一共d=n+1d=n+1个token。对每个token来讲,都需要得到一个分数向量si∈Rd×1si∈Rd×1。所有token构成Rd×dRd×d的分数矩阵,最后根据arc-factored原理找MST。
而一般MLP是个固定类别的分类器:
si=Wri+b(1)(1)si=Wri+b
无法处理不定类别分类,所以作者提出先将riri重新encode为Rk×1Rk×1,也就是过一遍MLP:
h(arc−dep)ih(arc−head)j=MLP(arc−dep)(ri)=MLP(arc−head)(rj)(2)(3)(2)hi(arc−dep)=MLP(arc−dep)(ri)(3)hj(arc−head)=MLP(arc−head)(rj)
这里两个MLP分别是dep专用和head专用。kk的量级通常更小,压缩encode的另一个好处是去除多余的信息。因为原始riri中含有预测依存弧标签的信息,这对预测head来讲是赘余的。
特征降维了之后,权值矩阵和偏置也必须做出调整。作者提出用两个矩阵连乘(两次仿射变换biaffine)输入向量:
s(arc)i=H(arc−head)U(1)h(arc−dep)i+H(arc−head)u(2)si(arc)=H(arc−head)U(1)hi(arc−dep)+H(arc−head)u(2)
其中,矩阵HH是dd个token的特征经过MLP二次encode出来的特征向量hh的stack形式,上式维度变化是:
(d×k)(k×k)(k×1)+(d×k)(k×1)=(d×1)(d×k)(k×k)(k×1)+(d×k)(k×1)=(d×1)
结果是拿到了dd个token的分数Rd×1Rd×1,同时分类器又不需要维护多个不同大小的权值矩阵(只需一个Rk×kRk×k的矩阵和两个MLP),漂亮地实现了可变类别分类。
如果把偏置放到U(1)U(1)里面去,同时进行d个token的运算,则上式的维度变化是:
(d×(k+1))((k+1)×k)(k×d)=(d×d)(d×(k+1))((k+1)×k)(k×d)=(d×d)
作者称这3个式子为deep bilinear attention mechanism,因为不同于直接用RNN输出的feature (shallow),这里通过MLP二次encode了一下。叫attention的原因是,输入是所有时刻的RNN feature,输出是一个在各个时刻上归一化的向量。
整个网络的架构如作者的Figure所示:
从下往上看,输入是word以及pos的embedding拼接,BiLSTM提取到特征riri,经过两个不同的MLP分别得到 h(arc−dep)ihi(arc−dep) 和 h(arc−head)jhj(arc−head) ,dd个这样的hh stack起来分别构成了H(arc−dep)H(arc−dep)和H(arc−head)H(arc−head)。其中由于bias的原因,H(arc−dep)H(arc−dep)额外拼接了一个单位向量。经过一个中间矩阵U(arc)U(arc)仿射变换后,每个token以dep的身份与以head的身份的每个token进行一次点积,得到arc成立的分数矩阵S(arc)S(arc)。
arc标签
这是个固定类别的分类问题,作者认为必须同时考虑依存关系的先验概率,已知词语作为head或dep接受某种依存关系的后验概率。也就是下式:
s(label)i=r⊤yiU(1)ri+(ryi⊕ri)⊤U(2)+b(4)(4)si(label)=ryi⊤U(1)ri+(ryi⊕ri)⊤U(2)+b
第一项是同时已知ii作为dep、yiyi作为head情况下的后验概率,第二项是已知ii或yiyi是arc两端的后验概率,第三项偏置是什么都不知道时label的先验概率。
为什么第二项的⊕⊕可以这么解读呢?拼接的话向量有先后顺序的呀?难道不应该用没有顺序的求和吗?
来看看两个向量(书写简便,就用仅含有一个元素的“向量”做例子)x1x1和x2x2的拼接乘上一个矩阵会发生什么:
⎛⎝⎜abcdef⎞⎠⎟(x1x2)=⎛⎝⎜ax1+dx2bx1+ex2cx1+fx2⎞⎠⎟(abcdef)(x1x2)=(ax1+dx2bx1+ex2cx1+fx2)
结果正好是求和形式,也就是说拼接的时候虽然有先后顺序,但做完乘法就变成了无序的求和形式。
第一项中含有一个高阶tensor,假设一共有mm种label,上式第一项的维度变化为:
(1×k)(m×k×k)(k×1)=(m×1×1)(1×k)(m×k×k)(k×1)=(m×1×1)
结果
重新整理了一下作者的分数表格:
考虑到Kuncoro et al. (2016)的RNNG其实是用separately trained Generative Model去rerank另一个Discriminative Model sample到的100棵phrase structure树,占了ensemble的便宜,所以作者是过谦了。
代码
代码开源在:https://github.com/tdozat/Parser-v1
需要TensorFlow-0.10才能运行,比较古老: