NLP-NER进展-1

2021-06-12

NER难点

  1. NER序列标注的方式对噪声(漏标)十分敏感,但是这种情况比较常见。
  2. 实体边界,长度,跨度对NER任务来说非常重要
  3. 顺序结构对于NER任务来说至关重要,通常需要RNN作为底层编码器来捕捉顺序性

NER的4种标注框架

  1. 序列标注

    每个序列位置都被标注一个标签,比如按照BILOU标注,然后用CRF解码。序列标注的方式对噪声(漏标)十分敏感,但是这种情况比较常见。一个解决方案就是采用下面说的片段排列,转化为一个span分类问题,这样更适合对负样本实体的采样;这样模型建模不会像对序列标注中的漏标过于敏感,也更好控制。此外,序列标注没办法解决嵌套问题,一个改进方法是采取token-level 的多label分类,将SoftMax替换为Sigmoid,但是这样没办法用CRF解码(因为CRF输入的是所有标签的概率分布,而不是每个标签是否入选的概率)。所以这种方式可能会导致label之间依赖关系的缺失,可采取后处理规则进行约束。

  2. 指针标注

    利用指针网络给每个位置给一个start None或者end None的二分类标签,用以标注一个实体的起始位置。如果是多类别实体,那么就转化为层叠式指针标注:C类实体,C个指针网络。但是Pointer Network一般是用两个模块分别识别实体的首和尾,这会带来训练和预测时的不一致。指针网络对实体的长度和跨度都不会特别敏感,很容易会把意两个实体的首尾组合都当成目标预测出来。MRC就是指针网络的一个典型例子。此外,假设序列长度为n,那么每个指针网络就要做n个二分类,这样会导致样本Tag空间稀疏,同时收敛速度会较慢,特别是对于n比较大的情况。
  3. 多头标注

    对每个token pair进行标记,构建一个\(N \times N \times C\)的分类矩阵,可以用于实体或者关系抽取。这个相比较与指针网络,综合考虑了实体首尾的一致性。事实上,多头标注成为了众多实体和关系抽取SOTA的首选利器

  4. 片段排列

    枚举所有可能的span进行分类,与序列长度进行解耦,可以更加灵活地处理复杂抽取和低资源问题。事实上,片段排列的思想已经被Google推崇[3]并统一了信息抽取各个子任务。对于含T个token的文本,理论上共有\(N = T(T+1)/2\)​种片段排列。如果文本过长,会产生大量的负样本,在实际中需要限制span长度并合理削减负样本。需要注意的是:

    • 实体span的编码表示:在span范围内采取注意力机制与基于原始输入的LSTM编码进行交互。然后所有的实体span表示并行的喂入SoftMax进行实体分类。
    • 这种片段排列的方式对于长文本复杂度是较高的。

Named Entity Recognition as Dependency Parsing (ACL)

image-20210615163201120

总的来说,这个文章的思路比较简单,但是我们仍然可以通过这个文章来窥探一下biaffine和dependency parsing。首先讲讲文章的思路:

  1. 底层的输入应该还是一个完整的句子。然后基于bert + fastTest 获取每个token的context dependent word embeddings。

  2. 用CNN对每个token的characters进行encode,但是characters的初始embedding怎么来不知道。1,2两个embedding做拼接。

  3. 在过一个双向LSTM后,用2个FFNN系数矩阵分别算出每个token的头指针和尾指针向量。$i$表示第$i$个头尾指针组合。 \(\begin{aligned} h_{s}(i) &=\mathrm{FFNN}_{s}\left(x_{s_{i}}\right) \\ h_{e}(i) &=\mathrm{FFNN}_{e}\left(x_{e_{i}}\right) \end{aligned}\)

  4. 最后用一个biaffine仿射模型的方式拼接每套头尾指针(假设句子长度为$l$,所有头尾指针的组合个数为$l \times l$),结果向量是c维的,其中c是总实体类别数+1,1表示是non-entity。也就是说,biaffine模型会产生一个$l \times l \times c$的scoring tensor。$i$表示第$i$个头尾指针组合。 \(\begin{aligned} r_{m}(i)=& h_{s}(i)^{\top} \mathrm{U}_{m} h_{e}(i) \\ &+W_{m}\left(h_{s}(i) \oplus h_{e}(i)\right)+b_{m} \end{aligned}\)

  5. 当然,头指针在尾指针之后的这种组合是要去掉的。

  6. 然后对每个头尾指针组合过softmax \(y^{\prime}(i)=\arg \max r_{m}(i)\)

  7. 然后规则后处理,先去除non-entity,具体的规则是论文里面分别定义了flat和nested ner应该遵循的一些规则。

那这个文章和dependency parsing有啥关系呢?首先了解下什么是dependency parsing(依存分析)。依存是指词与词之间支配与被支配的关系,这种关系不是对等的,这种关系具有方向指向。确切的说,处于支配地位的成分称之为支配者(governor,regent,head),而处于被支配地位的成分称之为从属者(modifier,subordinate,dependency)。依存关系连接的两个词分别是核心词(head)依存词(dependent)。依存关系可以细分为不同的类型,表示两个词之间的具体句法关系, 依存关系用一个有向弧表示,叫做依存弧。依存弧的方向为由从属词指向支配词。

基于图的依存句法分析从左向右解析句子,针对句中的每个词,找该词的head词(该词到head词之间的arc)以及从该词到head词之间的依存关系类型,即需要解决两个问题:哪两个节点连依存弧以及弧的标签是什么。目前的深度学习的方法使用分类器来解决这两个问题。咋眼一看,这。。不就是一个NER的问题吗?Biaffine模型其实就是为了解决依存分析多提出的依存标签分类器。简单来说,这个文章和dependency parsing没关系,它只是用了dependency parsing的解决方案。

那啥是双仿射呢:

线性(linear)模型:$\boldsymbol{W} \boldsymbol{x}^{\top}\left(\boldsymbol{x} \in \mathbb{R}^{1 \times d_{1}}, \boldsymbol{W} \in \mathbb{R}^{d \times d_{1}}\right)$

双线性(blinear)模型: $\boldsymbol{x} \boldsymbol{W} \boldsymbol{y}^{\top}\left(\boldsymbol{x} \in \mathbb{R}^{1 \times d_{1}}, \boldsymbol{y} \in \mathbb{R}^{1 \times d_{2}}, \boldsymbol{W} \in \mathbb{R}^{d_{1} \times d_{2}}\right)$

仿射(affine)模型:$\boldsymbol{W} \boldsymbol{x}^{\top}+\boldsymbol{b}\left(\boldsymbol{x} \in \mathbb{R}^{1 \times d_{1}}, \boldsymbol{W} \in \mathbb{R}^{d \times d_{1}}, \boldsymbol{b} \in \mathbb{R}^{d \times 1}\right)$ 或者可写作:$\boldsymbol{W}[\boldsymbol{x} ; 1]^{\top}\left(\boldsymbol{x} \in \mathbb{R}^{1 \times d_{1}}, \boldsymbol{W} \in \mathbb{R}^{d \times\left(d_{1}+1\right)}\right)$ 也就是把b写进$W$里面。

双仿射(biaffine)模型:$[\boldsymbol{x} ; 1] \boldsymbol{W}[\boldsymbol{y} ; 1]^{\top}\left(\boldsymbol{x} \in \mathbb{R}^{1 \times d_{1}}, \boldsymbol{y} \in \mathbb{R}^{1 \times d_{2}}, \boldsymbol{W} \in \mathbb{R}^{\left(d_{1}+1\right) \times\left(d_{2}+1\right)}\right)$

TENER: Adapting Transformer Encoder for Named Entity Recognition

  1. 这个文章的一个最主要的贡献就是,解释了为什么transformer在NER任务上的性能不如BiLSTM.
  2. 这个文章指出了:对于NER任务来说,位置和方向信息是十分重要的。
  3. 为了让transformer更好的适应NER任务,本文提出了2个优化方向:
    • 第一个是给transformer适配上了sinusoidal position embedding,就是三角函数编码。
    • 第二个,指出了The attention distribution of the vanilla Transformer is scaled and smooth. But for NER, a sparse attention is suitable since not all words are necessary to be attended.
  4. 本文也用了character-level information。说啥前文已经证明了用character-level information 可以很好地捕捉到out-of-vocabulary 不在词表里面的生词的feature。但是这明显只对英语有用吧。文章说了,别人都喜欢用CNN来做character-level encoder,但是他认为CNN无法捕捉discontinuous characters 如“un..ily” in “unhappily” and “unnecessarily” 。所以他们还是用transformer来做character-level encoder。

Named Entity Recognition for Social Media Texts with Semantic Augmentation

image-20210615165948298

  1. 输入的是整个句子。主要解决社交媒体的短文,不连续,语法不连贯的这个问题。
  2. 先说语义增强模块,准备2套词向量,对于句子的每个词,利用其中一套词向量找出最相近的n个词,然后,用另外一套词向量隐射这些词成e向量。
  3. 然后,h向量和e做内积,然后softmax算比重。算完比重再吧e向量按比例加权和得到v向量。h向量看下面。
  4. 再看左边,对输入的词进行embedding之后,利用一个带位置的transformer的encoder层来获取h向量。这个带位置向量的embedding,其实就是改了attention的方式。
  5. 好了,有了h向量和v向量,用一个门结构,去融合这两个向量。$\mathbf{g}=\sigma\left(\mathbf{W}{1} \cdot \mathbf{h}{i}+\mathbf{W}{2} \cdot \mathbf{v}{i}+\mathbf{b}_{g}\right)$
  6. 然后再来一个u向量来平衡g向量和v向量。
  7. 最后u经过一个线性变化,再经过一个仿射,得到bios的tag,再加上CRF修正。。

GlobalPointer by 苏神

关于位置编码的浅显理解

对于Transformer模型来说,位置编码的加入是必不可少的,因为纯粹的Attention模块是无法捕捉输入顺序的,即无法区分不同位置的Token。加入位置编码的方式总体来说就是两种:

  1. 绝对位置编码:想办法把位置信息融入到输入中

  2. 相对位置编码:想办法微调attention的结构,使它有能力分辨不同位置的token

绝对位置编码

绝对位置编码的主要形式为在输入序列的第k个向量$x_k$中加入位置向量$p_k$变为$x_k+p_k$,其中$p_k$只依赖于位置编号k。具体操作上,它其实会有各种变种:

  1. 可训练的位置编码

    这是最朴素方案,不需要特意去设计什么,而是直接将位置编码当作可训练参数,比如输入序列的最大长度为512,每个token的词向量编码维度为768,那么我们就初始化一个512×768的矩阵作为位置向量与词向量相加,让它随着训练过程更新。现在的BERT,GPT等模型就是用的是这种位置编码。

  2. 用三角函数表达的位置编码

    是google论文《Attention is All You Need》里面提出的,如下: \(\left\{\begin{array}{l} \boldsymbol{p}_{k, 2 i}=\sin \left(k / 10000^{2 i / d}\right) \\ \boldsymbol{p}_{k, 2 i+1}=\cos \left(k / 10000^{2 i / d}\right) \end{array}\right.\) 其中2i和2i+1就简单理解为某个token(第k个比如说)的位置向量里面的第偶数和奇数个分量值,d是位置向量的维度,比如768。很显然,基于三角函数的位置编码一个最重要的好处是向量的规律性,可以很容易向外推倒到其他位置的位置向量形式。此外,另外一个使用它的理由是,三角函数的性质,为表达相对位置的信息提供了可能性。比如说: \(\sin (\alpha+\beta)=\sin \alpha \cos \beta+\cos \alpha \sin \beta \mid\)

    \[\cos (\alpha+\beta)=\cos \alpha \cos \beta-\sin \alpha \sin \beta\]

    这表明位置α+β的向量可以表示成位置α和位置β的向量组合。但是具体怎么去利用这些性质,其实还需要进一步去探索。

  3. 递归式

    原则上来说,RNN模型不需要位置编码,它在结构上就自带了学习到位置信息的可能性。因此,如果在输入后面先接一层RNN,然后再接Transformer,那么理论上就不需要加位置编码了。同理,我们也可以用RNN模型来学习一种递归形式的绝对位置编码,比如从一个向量p0出发,通过递归格式pk+1=f(pk)来得到各个位置的编码向量。理论上来说,基于递归模型的位置编码也具有比较好的外推性,但是很明显,递归形式的位置编码牺牲了一定的并行性,可能会带速度瓶颈。

关于绝对位置编码,我其实还有2个问题搞不太清楚:

  • 关于外推性:为啥外推性很重要,是不是外推性其实间接的或者说某程度上让距离感知更明显呢?我觉得是。
  • 关于位置编码的相加性:刚才有说到,输入$x_k$与绝对位置编码$p_k$的组合方式一般是$x_k+p_k$,为什么不能相乘呢?其实没有从理论上有证明说相加一定是正确的,只不过相加在深度学习领域更像是经验科学,相加证明了是有效的而已。

相对位置编码

一般认为,相对位置编码是由绝对位置编码启发而来。下面我们具体来看看是如何启发。

首先,我们考虑一般的带绝对位置编码的Attention的形式: \(\left\{\begin{array}{c} \boldsymbol{q}_{i}=\left(\boldsymbol{x}_{i}+\boldsymbol{p}_{i}\right) \boldsymbol{W}_{Q} \\ \boldsymbol{k}_{j}=\left(\boldsymbol{x}_{j}+\boldsymbol{p}_{j}\right) \boldsymbol{W}_{K} \\ \boldsymbol{v}_{j}=\left(\boldsymbol{x}_{j}+\boldsymbol{p}_{j}\right) \boldsymbol{W}_{V} \\ a_{i, j}=\operatorname{softmax}\left(\boldsymbol{q}_{i} \boldsymbol{k}_{j}^{\top}\right) \\ \boldsymbol{o}_{i}=\sum_{j} a_{i, j} \boldsymbol{v}_{j} \end{array}\right.\) attention这里还是简单回归一下,就是输入序列的每个词向量,经过3个不同的系数矩阵,然后生成3个向量:query,key和value。然后每个词的query向量分别和自己与其他词的所有key向量算内积,然后softmax,算出每个词向量应该为当前词的最终词向量贡献多少比例的向量内容。然后每个词的value向量按刚才算好的这些比例的权重相加。

OK,现在背景有了,我们具体看看各种相对编码是如何被启发出来的。

  1. 最经典的相对编码,来源于google的《Self-Attention with Relative Position Representations》

    首先展开第i个query和第j个key向量的内积我们可以得到: \(\boldsymbol{q}_{i} \boldsymbol{k}_{j}^{\top}=\left(\boldsymbol{x}_{i}+\boldsymbol{p}_{i}\right) \boldsymbol{W}_{Q} \boldsymbol{W}_{K}^{\top}\left(\boldsymbol{x}_{j}+\boldsymbol{p}_{j}\right)^{\top}=\left(\boldsymbol{x}_{i} \boldsymbol{W}_{Q}+\boldsymbol{p}_{i} \boldsymbol{W}_{Q}\right)\left(\boldsymbol{W}_{K}^{\top} \boldsymbol{x}_{j}^{\top}+\boldsymbol{W}_{K}^{\top} \boldsymbol{p}_{j}^{\top}\right)\) google把第一项位置去掉,把第二项位置$\boldsymbol{W}{K}^{\top} \boldsymbol{p}{j}^{\top}$改为一个和位置i和位置j都有关系的可学习的向量$\boldsymbol{R}{i, j}^{K}$。$\boldsymbol{R}{i, j}^{K}$具体是啥呢,我的理解是它可以是位置i和j的标量再乘以一个可学习的系数矩阵。所以这就是为什么被称作为相对位置了。然后,经过softmax之后,我们现在可以达到的简化的$a_{i,j}$结果。 \(a_{i, j}=\operatorname{softmax}\left(\boldsymbol{x}_{i} \boldsymbol{W}_{Q}\left(\boldsymbol{x}_{j} \boldsymbol{W}_{K}+\boldsymbol{R}_{i, j}^{K}\right)^{\top}\right)\) 相类似地,在计算$o_i$的时候,把$p_jW_v$也改为相对位置向量$\boldsymbol{R}_{i, j}^{V}$。所以得到: \(\boldsymbol{o}_{i}=\sum a_{i, j}\left(\boldsymbol{x}_{j} \boldsymbol{W}_{V}+\boldsymbol{R}_{i, j}^{V}\right)\)

    相对位置通常来说会进行截断,以适应任意距离。这样一来,只需要有限个位置编码就可以表达出任意长度的相对位置了: \(\begin{aligned} \boldsymbol{R}_{i, j}^{K} &=\boldsymbol{p}_{K}\left[\operatorname{clip}\left(i-j, p_{\min }, p_{\max }\right)\right] \\ \boldsymbol{R}_{i, j}^{V} &=\boldsymbol{p}_{V}\left[\operatorname{clip}\left(i-j, p_{\min }, p_{\max }\right)\right] \end{aligned}\) 其中$p_K$和$p_V$用来表达两套不同的位置系数矩阵。

  2. XLNET所用的位置编码

    XLNET式位置编码源于对上述的$\boldsymbol{q}{i} \boldsymbol{k}{j}^{\top}$完全展开: \(\boldsymbol{q}_{i} \boldsymbol{k}_{j}^{\top}=\boldsymbol{x}_{i} \boldsymbol{W}_{Q} \boldsymbol{W}_{K}^{\top} \boldsymbol{x}_{j}^{\top}+\boldsymbol{x}_{i} \boldsymbol{W}_{Q} \boldsymbol{W}_{K}^{\top} \boldsymbol{p}_{j}^{\top}+\boldsymbol{p}_{i} \boldsymbol{W}_{Q} \boldsymbol{W}_{K}^{\top} \boldsymbol{x}_{j}^{\top}+\boldsymbol{p}_{i} \boldsymbol{W}_{Q} \boldsymbol{W}_{K}^{\top} \boldsymbol{p}_{j}^{\top}\) 做法很简单,直接把$p_j$替换成相对位置向量$R_{i-j}$,至于两个$p_i$,则替换成2个可训练的向量$u$和$v$(我的理解是任意i都用这两个$u$和$v$)。这边的位置向量$p_i$,其实采用的是三角函数形式的,和上面的有点不同。所以$R_{i-j}$就是三角函数数学操作而已。

    值得注意的是,value向量在这个工作里面其实是没有加到位置信息的。关于value向量上需不需要加位置编码这个事呢,其实是有争议的,这也很好理解,比如说有些人认为词的意思和所处的位置有很大的关系,有些人认为词的意思是和位置无关的。但是不管是那种,和词义是和上下文有关这个核心理念是不冲突的。

    似乎从这个工作开始,后面的相对位置编码都只加到Attention矩阵上去,而不加到value向量上去了。

  3. T5所用的位置编码

    这玩意其实和上面差不多,还是源于对上述的$\boldsymbol{q}{i} \boldsymbol{k}{j}^{\top}$完全展开。如果给每一个展开项加上一点含义,那这个展开式就是“输入-输入”、“输入-位置”、“位置-输入”、“位置-位置”四项注意力的组合。接下来,就看你认为哪个组合不重要了。

    比如说,如果你认为输入信息与位置信息应该是独立(解耦)的,那么它们就不应该有过多的交互,所以“输入-位置”、“位置-输入”两项Attention可以删掉。辣么$\boldsymbol{p}{i} \boldsymbol{W}{Q} \boldsymbol{W}{K}^{\top} \boldsymbol{p}{j}^{\top}$就可以作为一个直依赖位置的量。但是呢,在T5中,这个量有点神奇,和上面的向量形式($R_{i-j}$)有点不一样,变得更简单了,它用一个标量$\beta_{i,j}$来表示: \(\boldsymbol{q}_{i} \boldsymbol{k}_{j}^{\top}=\boldsymbol{x}_{i} \boldsymbol{W}_{Q} \boldsymbol{W}_{K}^{\top} \boldsymbol{x}_{j}^{\top}+\boldsymbol{\beta}_{i, j}\) 说白了,这仅仅是在Attention矩阵的基础上加一个可训练的偏置项而已。我的理解是呢,这个标量肯定也是底层的i-j(直接位置相减)然后映射到$f(i-j)$(如下所示,就是比较邻近的位置(0~7),我们需要比较得精细一些,所以给它们都分配一个独立的位置编码,至于稍远的位置(比如8~11),我们不用区分得太清楚,所以它们可以共用一个位置编码,距离越远,共用的范围就可以越大,直到达到指定范围再clip。) 再乘以可训练的参数变换。

    image-20210612143045823

  4. DeBERTa所用的位置编码

    DeBERTa则和上面刚刚相反,它扔掉了第4项,保留第2、3项并且替换为相对位置编码(果然,科研就是枚举所有的排列组合看哪个最优): \(\boldsymbol{q}_{i} \boldsymbol{k}_{j}^{\top}=\boldsymbol{x}_{i} \boldsymbol{W}_{Q} \boldsymbol{W}_{K}^{\top} \boldsymbol{x}_{j}^{\top}+\boldsymbol{x}_{i} \boldsymbol{W}_{Q} \boldsymbol{W}_{K}^{\top} \boldsymbol{R}_{i, j}^{\top}+\boldsymbol{R}_{j, i} \boldsymbol{W}_{Q} \boldsymbol{W}_{K}^{\top} \boldsymbol{x}_{j}^{\top}\) 这里的$R_{i-j}$,和上面的$\boldsymbol{R}{i, j}^{K}$和$\boldsymbol{R}{i, j}^{V}$一样的设计。没有特别的地方。

    不过,DeBERTa比较有意思的地方,是提供了使用相对位置和绝对位置编码的一个新视角,它指出NLP的大多数任务可能都只需要相对位置信息,但确实有些场景下绝对位置信息更有帮助,于是它将整个模型分为两部分来理解。以Base版的MLM预训练模型为例,它一共有13层,前11层只是用相对位置编码,这部分称为Encoder,后面2层加入绝对位置信息,这部分它称之为Decoder,还弄了个简称EMD(Enhanced Mask Decoder);至于下游任务的微调截断,则是使用前11层的Encoder加上1层的Decoder来进行。

Reference

  1. GlobalPointer-苏神:https://www.kexue.fm/archives/8373
  2. 让研究人员绞尽脑汁的Transformer位置编码