七、序列标注

所谓序列标注(Sequence Tagging)就是,给定一些预定义的 tag,然后要给每个词都打上 tag。比如说:

  • 词性标注(POS Tagging)给每个词标注词性,比如名词、动词、冠词等;
  • 命名实体辨别(NER),比如地名、机构名、人名等;
  • 短语分块(Chunking),就是识别出连在一起的短语。

不管是什么任务,反正都得先有标签再说。一种经典的标签叫 BIO,其中有三个标签,分别是 Begin,Inside 以及 Outside。对于每个连续片段,第一个词是 B,后面的词都是 I,不属于连续片段的是 O。这个标签在命名实体辨别任务中很常用,比如下面这个句子:

China Mobile is a company.

如果识别 China Mobile 是实体,那么:

China/B Mobile/I is/O a/O company/O

更进一步,有带类型的 BIO,比如地名就包括 B-LOC 和 I-LOC,组织机构就包括 B-ORG 和 I-ORG,等等。类型反正是自定义的,想怎么定义就怎么定义。因此,假如有 $n$ 个类型,那么每个类型都包括 B 和 I,然后再单独加上一个 O,因此总共会有 $2n+1$ 个标签,很好理解吧。

序列标注的问题就在于歧义,断句不知道怎么断。

下面我们以词性标注为例子介绍两条路径,分别是统计方法的 HMM 以及神经网络方法。

1. 问题定义

词性大家都知道,本质是描述词在句子中的语法角色。有两类,一类是封闭类,成员基本固定,数量少,并且主要起语法作用,比如冠词、代词、介词等;另一类是开放类,可以不断新增,且语义丰富,比如名词、动词、形容词等。当然情态动词 can 和过去完成时的 had 这些也是封闭类的,所以这个定义其实是有点模糊的。实际上定义这玩意对词义标注有用吗,我感觉是没有的,但是万一考试问个这种题呢,你又不能说没讲,就很恶心。而标签集合(Tagset)包含了一套标准化的标签编码,这个有不同的标准,我们常见的是 UD Tagset,还有更精细的 PennTree Bank Tagset 等,知道就好。

OK,我们抽象一下,给定了词序列 $x_1,\cdots,x_n$,需要求出 POS tag 序列 $y_1,\cdots,y_n$。目标就是使得 $P(y_1\cdots y_n\vert x_1\cdots x_n)$ 越大越好。

2. 隐马尔科夫模型(HMM)

简单变形:

\[\begin{align*} &P(y_1\cdots y_n|x_1\cdots x_n)\\ =&\boxed{P(y_1\cdots y_n)}\cdot\boxed{P(x_1\cdots x_n|y_1\cdots y_n)}\\ =&\boxed{P(y_1)P(y_2|y_1)P(y_3|y_2)\cdots}\cdot\boxed{\prod_i P(x_i|y_i)} \end{align*}\]

注意这里的变形有两个假设,前面这个链式拆开是一阶马尔科夫假设,你也可以改成二阶的;后面这个是做了独立性假设,认为每个词只由它对应的词性影响。这两个假设合称 Hidden Markov Models(HMM,隐马尔科夫模型)。还定义了两个名词,$P(y_i\vert y_{i-1})$ 叫转移概率,$P(x_i\vert y_i)$ 叫发射概率,好优雅的名字!

这些概率就可以用统计学的方法求了:

\[\begin{split} P(y_i|y_{i-1})=\frac{Count(y_{i-1},y_i)}{Count(y_{i-1})}\\ P(x_i|y_i)=\frac{Count(y_i,x_i)}{Count(y_i)} \end{split}\]

提到统计学,当然也是可以加上拉普拉斯平滑的,这里不细讲了。

2. HMM 的使用

现在我们已经训练好了一个 HMM 模型,也就是获取了所有的发射概率和转移概率,如何确定 $y_i$ 呢?目标肯定是使得 $P(y_1\cdots y_n\vert x_1\cdots x_n)$ 的值最大,但是呢不能用贪心算法,因为后面的词会受前面词影响。因此我们需要动态规划,这个算法叫 The Viterbi Algorithm

我们以 Trigram 为例吧,也就是把上面的式子中的 $P(y_3\vert y_2)$ 改成 $P(y_3\vert y_2y_1)$,这样会难一点。然后我们需要定义数组 $\pi(k,u,v)$,表示在第 $k$ 个词,前两个词性为 $u$,前一个词性为 $v$ 时的最大概率。最后定义递推关系,可以发现只需要遍历前第三个词的所有可能就好了,也就是:

\[\pi(k,u,v)=\max_w\{\pi(k-1,w,u)\cdot p(v|w,u)\cdot p(x_k|v)\}\]

初始值很显然就是 $\pi(0,START,START)=1$,因此整个递推方程是能运行起来的。但是仅求出 $\pi$ 还不够呀,我们需要求的是最大概率对应的标签。因此还需要单独记录 path 表,在每个位置记录取到最大概率的 $w$,最后回溯一遍就好了。这个算法的时间复杂度是,首先需要遍历 $k,u,v$,其次需要遍历 $w$,因此时间复杂度为 $O(n\cdot\vert S\vert^3)$,其中 $n$ 是句子长度,$\vert S\vert$ 是标签集大小。

HMM 的优点在于:

  • 数学公式非常简洁,并且实际意义也很清晰;
  • 统计学依旧不担心参数;

但是:

  • 需要高质量的训练数据
  • 不能设计特征,也不能学习特征

3. 神经序列标注

利用我们前面说到过的双向 RNN,LSTM 和 GRU 等,可以构建一些好用的神经网络模型,这里我们就不细讲了,感兴趣的可以搜 BLSTM,CRF,FLERT 等自行了解。

4. Seq2Seq

这里我们把序列的定义拓宽:假如输入序列与输出序列的长度不一样,那么不管是 HMM 还是 RNN 都报废了,最经典的问题就是机器翻译。解决这个问题的方法是 Encoder-Decoder 架构。见下图:

诶?图片怎么不见了?

这个思路很简单,就是用两个 LSTM 拼接起来,前一个 LSTM 在中间不做任何输出,只进行输入,然后把输入的整个序列编码成一个向量,叫做 Encoder。然后进入下一个 LSTM,每次我们把前一个输出当做新的输入,将其插入到记忆中,影响下一个输出,这个部分叫 Decoder,本质上就是已知前面的词去预测下一个词。用数学公式表示,就是:

\[p(y_1,\cdots,y_{T'})=\prod_{t=1}^{T'}p(y_t|v,y_1,\cdots,y_{t-1})\]

其中 $T’$ 是输出长度,每个输出的值受到输入编码后的向量 $v$ 与该输出前的所有输出影响。反正这个框架很简单啦。

这个架构提出以后,作者还发现了一些现象:

  • 一层 LSTM 不好用,得两层 LSTM(这不废话嘛);
  • 深度越大越好(这不也是废话嘛);
  • 倒着输入比原始输入更好。

好家伙,合着就最后一个发现最重要,前两个都是为了醋包饺子呗。这其实也合理,让句子开头最后输入,这样输出的时候第一个词就会比较准。这也说明了,其实输出的序列和输入的序列压根没建立联系,这是我们不希望看到的。因此我们期望在输出的时候,能够让对应的输入影响最大,这怎么办呢?

5. Attention

一个自然的想法产生了:那每当我要输出的时候,拿着我此时的隐状态,和之前所有输入的隐状态去碰面,然后计算出我与每个输入间的关系。依据我们关系的远近,来判断我的输出更需要参考哪些输入。话不多说,上图!

诶?图片怎么不见了?

如图所示,在 Encoder 中,我们把每个词输入进去,得到了每个隐状态 $h_1^e,\cdots,h_n^e$。这时还没到输出呢,我们还是正常进行,把这些输入压缩成向量 $v$,输入给 Decoder。现在假如我们要输出 $y_i$,并且获得了上一时刻的隐状态 $h_{i-1}^d$。那么我们这么做:

第一步,评价一下每个输入与当前隐状态的相关性:

\[e_{ij}=a(h_{i-1}^d,h_j^e)\]

这里衡量的是第 $j$ 个输入与当前输出的相关性,这个衡量的方式也是经历了长久的发展,最后得到了一个公认的比较好的方式:

\[a(q,k)=\frac{q^Tk}{\sqrt{d_k}}\]

其中 $d_k$ 就是 $k$ 向量的维度。不管怎样,反正就是用一个函数衡量了它们的相关性。

第二步,把所有的分数过一遍 softmax,以变成概率 $\alpha_{ij}$。

第三步,根据概率加权,得到上下文向量:

\[c_i=\sum_{j=1}^n \alpha_{ij}h_j^e\]

到这里我们就获得了一个既糅合了所有输入,又对输入进行了加权的,更适合当前输出体质的向量。然后,本来咱们的 LSTM 需要输入长期记忆、前一个输出和输入,现在就改成了前一个隐状态、$c_i$ 和前一个输出了。

实际上 Attention 机制可以处理任意的向量之间的关系,不一定要用在 Seq2Seq 任务中。在 Attention 机制中,我们有三种向量,第一个叫 Query,就是拿它来与各个向量求关系;第二个叫 Key,它们是被求关系的那些向量;最后一个叫 Value,它们是最终被用于加权的那些向量。

6. Self-Attention

在 Seq2Seq 的 encoder-decoder attention 里,K 和 V 是同源的,都是 encoder 的隐状态,而 Q 是 decoder 前一个输出中的隐状态。而自注意力机制不一样,所有的 K,Q,V 都来自于词本身:

\[q=wW^Q,k=wW^K,v=wW^V\]

其中的三个矩阵都是可以学习的参数。随后就像之前的 Attention 一样,我们有计算公式:

\[z=softmax(\frac{qk^T}{\sqrt{d_k}})\cdot v\]

再进一步,什么是多头注意力(Multi-Head Attention)呢,就是把 $Q,K,V$ 切成 $h$ 份,每份独立做 attention,最后再拼接到一起,再过一个线性层。

自注意力是 Transformer 中很重要的组成部分,但是我觉得应该不会考 Transformer 吧,毕竟 PPT 上也不算详细。

Leave a comment