购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.3 深度学习在分词中的应用

深度学习在分词任务中的探索其实并不热门,原因有两个:一是在BERT提出之后,一部分任务可以直接基于字向量去解决,二是在分词任务上深度模型的指标相比工程方法没有大幅提升,但响应速度却大幅下降。不热门不代表没有价值,下面按时间顺序及相对热门的领域介绍分词任务里的深度模型。

1.3.1 Bi-LSTM模型

Google公司的Ji Ma、Kuzman Ganchev和David Weiss于2018年在论文State-of-the-art Chinese Word Segmentation with Bi-LSTMs中提出了一个用于分词的模型,该模型非常简单,就是一个稍微变形的Bi-LSTM。

对于中文分词,不同的语料库标准不统一,例如“宝马公司”,有的语料库认为这是一个词,有的语料库会将其分为“宝马”+“公司”。有的语料库的训练集和测试集不统一,如上面的论文中就给出了一个错误分析——“抽象概念”,在训练集里这个词从来没有出现过,只存在“抽象”和“概念”两个独立的子词,而在测试集里就出现了“抽象概念”这个词。这种实例确实难以通过算法来克服。所以之后的一些尝试和发表的论文就开始进行跨语料的联合学习。

Bi-LSTM可以算是深度学习在分词领域应用最早的模型了,虽然前面也有不少使用神经网络进行中文分词的模型,但是其指标都没有全方位地超越最好的传统算法,如HMM、CRF和最短路径等。

1.模型结构

先看一下Bi-LSTM模型的结构,如图1.8所示。

图1.8 stacked Bi-LSTM模型结构

Bi-LSTM模型结构是标准的序列标注结构,就是将一句话输入后,每个字都会对应一个标签输出,对于分词的标签一般为B、M、E、S。B就是Begin,是词的开始部分;M就是Middle,是词的中间部分;E就是End,是词的结束部分;S就是Single,是单字词,如“我”“是”等。

每个字都有了对应的标签后,就可以根据标签来分词,S就是单独的一个词,BE就是一个双字词,BME就是一个三字词,BMME就一个是四字词,以此类推。

如图1.8所示,中间词标识使用的是I,与M的意思是一样的。图1.8(a)是正常的Bi-LSTM,就是输入正向的LSTM,同时也输入反向的LSTM,然后把两边的输出合并,作为下一层的输入。而这里的模型使用的是变形的Bi-LSTM,如图1.8(b)所示为Stack-LSTM,就是先输入反向的LSTM,然后这个反向LSTM的输出不是等待与正向的输出合并,而是直接输入正向的LSTM,然后以正向的LSTM的输出作为下一层的输入。这其实类似正常的双层LSTM,只不过第一层是反向传播的。

序列标注模型最后经常会跟一层CRF,作为寻找最佳序列的组合,这个逻辑其实与最短路径分词类似,就是找出概率最高的那条路线,而不是用贪婪算法,每步都直接取最大值。虽然取最大值的方法计算简单,但是其值往往都不是最优解。而这里的模型没有使用CRF。

序列标注任务中的最后一层常用的有3种方法。

第一种就是使用贪心算法,其计算简单,但其值往往不是最优解。

第二种是使用Beam Search,它也是一种贪心算法,不同的是每次不是取最大值,而是取几个值,如5个值,然后就用这5个值依次作为下一步的输入,分别计算出下一步的结果,再取两步中最优的5个结果,以此类推,到最后一步还是只保留5个最优值。这种方法的计算量会增加,而且不保证可以取到最优解,但最终的结果基本可以非常接近最优值。

第三种是使用CRF。CRF简单理解就是一个打分层外加一个动态规划求最优解的方法。求最优解就是前面简单提过的Viterbi算法。打分层在传统的CRF里其实是特征工程,也就是基于当前任务如分词,将计算法专家们总结的很多先验经验整合成为多个打分函数,然后基于当前的句子选择适合的打分函数,给每个字的每个标签打一个分数,然后基于这个分数找出整个序列总得分最高的那个序列组合。而现在的CRF一般都用神经网络的自动学习特征去拟合特征工程的特征函数,详细介绍的话可以占用一章的篇幅,但CRF不是我们的重点,因此这里可以简单将CRF理解为一个全连接层,对每个字都输出4个值,也就是4个标签BMES的得分。

如果想深入学习CRF,可以参考李航的《机器学习方法》一书的CRF章节。该书是一本典型的教科书,里面有很多公式可以作为参考标准。同时,读者还可以参阅网上的一些文章,如《通俗易懂理解——条件随机场CRF》,对于理解CRF也非常有帮助。

2.bi-gram输入

这里的输入使用uni-gram与bi-gram两个Embedding层的合并。这个想法是受Hao Zhou、Zhenting Yu、Yue Zhang等人发表的论文Word-Context Character Embeddings for Chinese Word Segmentation的启发,如图1.9所示。

图1.9 uni-gram和bi-gram特征输入

这里,uni-gram其实就是字向量,而bi-gram就是双字向量,这个双字可能是词也可能不是词,获取方式是使用Word2vec训练方式进行预训练,分别训练uni-gram向量和bi-gram向量。

当然,模型实验也尝试了不进行预训练而只是把uni-gram和bi-gram进行随机初始化的效果。

bi-gram双字向量这个特征后面还会被很多模型使用,实验结果表明其效果还是不错的,对很多NLP任务都起到了提升作用。

各语料库的实验结果如图1.10所示。

图1.10 各语料库的实验结果

这个实验结果在当时确实是最好的,除了PKU数据集,其他性能都超越了以往的模型。比较有意思的是,在对比预训练词向量的使用方式的结果中,预训练之后不进行微调的方法在大部分数据集上的效果反而更好,而根据分词任务进行微调的效果除了MSR数据集之外全部低于fix组。当然,原因也可能是模型微调过度而导致过拟合。按笔者的经验微调有一定的提升效果,但其值不能调得太大,一般需要提前结束作为正则来限制微调值。也有可能是数据集本身的问题,前面说过,训练集和测试集经常会出现一些不匹配的标注,因此需要更深层次地研究数据集。

3.其他优化手段

Bi-LSTM模型虽然简单,但是为了达到当时SOTA的效果,使用了一些调优方法,如RNN Dropout、超参数的网格搜索(见图1.11)和优化器使用基于动量的平均SGD过程等。

图1.11 网格搜索的范围

值得一提的是网格搜索,这也是优化指标的一个手段。所谓优化,就是在高维空间里寻找一个最优解,也就是最大值或最小值,两者可以增加一个负号和互换,所以等价,后面统一使用最小值。如果是二维平面,那么最小值很容易找,就是一阶导数为0,二阶导数大于0。如果是高维,那么就是一阶梯度为0,二阶梯度矩阵全部大于0。但问题是:如果有10维,10个方向全部大于0的概率高吗?假设大于0的概率为50%,那么0.5的10次方(就是10个方向都大于0的概率)等于1/1024,概率非常低。

因为超平面不是由数学公式推导出来的,不是凸平面,所以可能是任意形状的。这样的平面其实就是一阶梯度为0,而二阶梯度各方向大于0和小于0都有的概率才是最高的。这样的点其实就是鞍点,连局部最小值都算不上。

所以理论上,在一个高维空间中寻找一个任意平面的最小值是非常困难的。即使使用了最先进的优化器,其值也非常容易停在一个鞍点上。解决这个问题的最佳方式就是使这个鞍点的二阶梯度小于0的维度少一些,这样就不容易被优化器的动量之类的因素扰动跳出这个区域。

怎样才能寻找到最优解呢?其实并没有一个最优的方法,可以使用上面提到的网格搜索来增加找到最优解的概率。其原理也很简单,就是从高维空间不同出发点去寻找。例如,现在我们都不知道珠穆朗玛峰是最高的,要寻找世界上最高的山峰,应该怎么找?我们可以从不同的地区向着当地最高的位置去寻找。

具体到模型,就是以不同的超参数组合优化模型。如图1.11所示,例如组1使用bi-gram双字向量的长度为16,学习率为0.03,输入的dropout率为0.2,LSTM内部流转的dropout率为0.3,组2就使用其他参数,然后看两个组最终的指标结果,使用最优的那个指标,如图1.12所示。

图1.12 网格搜索的结果

其中,第一列就是指标最优的那一组,第二列就是平均值。从经验上讲,虽然网格搜索会极大地增加训练时间,有几组参数就训练几次,但是指标提升的效果没有理论上预测的那么好,如图1.13所示。

图1.13 消融实验对比

Ji Ma、Kuzman Ganchev和David Weiss几人对几个关键模块进行了实验对比,发现预训练还是有较大影响的,至于stacked Bi-LSTM和LSTM Dropout,其实将它们去掉后对模型的整体性能影响并不大,说明这两个设计是有正贡献的,如图1.14所示。

图1.14 OOV的召回率

Ji Ma几人最后还做了一些错误的案例分析,其中值得一提的是OOV(超出词典范围)问题,就是前面提过的在训练集里根本没出现过的词,但在测试集里出现了,结果如图1.14所示,其实效果笔者认为还可以,随机初始化的嵌入向量就能达到65%以上的召回率。为什么训练时没出现过的词也能识别出来呢?应该是一些常见的上下文组合信息造成的。例如,“我要去吃××。”,这个××一般都是一个词,即使训练集里没出现,也有概率能分出来。而使用预训练的嵌入向量后,整体OOV的召回率指标又提升了10%左右,这说明额外的预训练信息还是有价值的。

1.3.2 基于词向量的分词

上一节我们讲了使用预训练的字向量和bi-gram双字向量来分词,那么能不能使用词向量分词呢?

这个问题是不是听着很奇怪,如果知道词向量,那么肯定就分好词了,否则怎么知道词向量呢?还真可以,当然我们预先分好的词只是作为后面分词的参考,而不是最终结果。阿里巴巴的Yuxiao Ye、Weikang Li和Yue Zhang等人在2018年发表的一篇论文Improving Cross-Domain Chinese Word Segmentation with WordEmbeddings中就是这么做的,这里大概了解一下逻辑增加的一些思路即可。

首先,使用任意一种分词器把语料分成词,这里的分词有点像jieba的全部模式,就是把所有可能的词全部分出来。例如,在前面的最短路径里把“中国人民生活”和“中国、人民、生活、中国人、国人、民生”等都分出来,基于这样的假设,就是因为词向量是基于语言模型训练的,所以正确分词的一句话中的所有词的词向量距离是比较接近的。这一点很容易理解,因为如Word2vec之类的词向量训练时的损失函数就是让上下文词的输出与目标词接近,这样上下文距离目标词就肯定是接近的。

有了这个假设,就可以寻找一个全句词向量距离总值最小的一种分词路线。其实这个逻辑跟最短路径分词没有本质的区别,只是最短路径使用bi-gram作为图的边的权值,而这里是使用边上的两个词向量的距离作为权值。

当然,也可以不使用基本分词器把所有可能的词分出来,只是这样就需要进行一定程度的遍历,尝试所有字符可能组合的词,如果在预训练词向量词典里没有这个词,则跳过。这个逻辑跟前面差不多,只是不需要预先分词。

1.3.3 简易融合语料分词

因为汉语分词只能使用汉语语料,所以其存在的问题是语料库缺乏。现在多个分词语料库也存在一个问题,就是分词标准不统一,如表1.1所示。

表1.1 分词语料库的标准

因此如何充分利用这些标准不统一的语料库成了一个较热门的问题。

直接的方法就是把标准统一化,例如,先把所有的繁体字转换为简体字,然后基于一个映射表把一些翻译的差异统一进行转换。例如,将表1.1中Benz对应的大陆版“奔驰”、台湾版“宾士”和香港版“平治”,统统转换为“奔驰”。接着把不同的标准统一起来,需要做很多的人工规则识别操作,最后使用一个合并的大语料进行训练。这种方法最大的问题就是需要大量的人工介入,因此可能会引入一些不易感知的新的不统一或错误。

有人在基于Google多语言翻译模型对不同语言语料的处理时,想到了直接联合语料进行训练,只是在不同语料的每句话前面增加一个相应语料的特有标识,如表1.2所示。

表1.2 不同语料库的处理

其中,在PKU语料的每句话前后都增加一对特有标识<pku></pku>。其他语料也一样。

对于序列标注问题,所有的损失都可以使用最大似然估计MLE,其实MLE在底层是与交叉熵等价的。

这里的 m 就是有 m 个句子, n 就是每个句子有 n 个字, Y 就是正确的标签序列。

本章后面不特别指出的情况下,损失函数是通用的。

融合分词的训练结果如图1.15所示。其中,使用的网络是普通的Bi-LSTM+CRF。前面讲过,CRF的最大作用就是Viterbi算法可以找到最优解,所以理论上在序列标注问题中,任意模型在添加上一层CRF层后指标都会提升一些,至于提升多少则不一定。有兴趣的读者可以对比一下前面介绍的Bi-LSTM分词的结果,虽然前面那个Bi-LSTM最后没有添加CRF,但是指标依然比较高,也就是说这里的Bi-LSTM实际上只是一个没有任何调优的模型,没有stacked,没有bi-gram向量等。继续看这里的实验结果,baseline就是对语料分别进行训练的结果,+naive就是语料联合训练但前后没有特殊标识。由此可见,如果对多语料不进行处理,反而令指标大幅下降,+multi就是在不同语料库的句子前后加上了特殊标识。

图1.15 融合分词的训练结果

本节的重点不是介绍模型有哪些创新,所以模型未达到最好并没有明显影响,关键是加入了特殊标识的联合语料训练确实让最终的指标上升了,虽然幅度不太大,但是有明显的提升,证明这样简单的融合方法是有效的,后面会介绍一些其他的融合方法。

1.3.4 分词的多标准集成学习

分词的多标准集成学习依然是对多个分词语料的联合训练,与1.3.3节的区别在于1.3.3节使用了共享全部权重的统一模型,且使用一个额外标识来区分每种语料,而本节模型的方案是为每个语料库设计一个专有的网络层。

其实现在分词因为语料数量的限制,许多论文都在研究如何充分利用现有的多个分词语料库,而就因为这些语料库的标准经常不同,所以如何协同这些不同的标准也就成了问题。

至于单纯的网络更新,到目前为止,几乎所有相关论文的指标都没有超过SOTA,表现最好的是对transformer进行的一些改造,最终指标才能接近SOTA模型。因此现在看到的提升SOTA指标的论文基本上都是向联合语料这个技术方向努力的。这并非语料融合技术本身有多么重要,而是由于标签语料太稀少,不足以支撑深度网络的学习,只有把语料库合并起来才勉强够用。

还有一个方向是使用现有的语料库。例如,在进行一些领域分词时使用一些领域词典,再加上无标注的大量语料库来协同提升分词的质量。因为无标注的语料数量永远大于有标注的语料数量,所以这也是所有NLP任务的方向。这种训练方式被称为半监督学习。不过目前在分词领域看到的结果还不能令人满意,所以这里就不介绍了。

本节讲解的是蚂蚁金服的W Huang、X Cheng和K Chen等人发表的一篇论文Toward Fast and Accurate Neural Chinese Word Segmentation with Multi-Criteria Learning其分词模型如图1.16所示。

整体上,这个模型还是把分词作为一个序列标注问题来解决的,就是在网络中输入一串文字 C 1 C 2 C n ,然后每个字符输出一个取值为{B,M,E,S}的标签 y 1 y 2 y n

第一层是嵌入层,就是把one-hot的高维字向量转换为相对低维的字向量,这里可以使用预训练的字向量,也可以从随机初始化开始训练。

第二层是一个Transformer模块,准确说是一个BERT模型,不过原来的BERT是12层,这里为了使速度和效果达到平衡,使用了原来BERT的最下面的几层,具体使用多少层其实是一个超参数,后面实验有测试。对于Transformer,在后面的章节中会具体讲解。BERT的网络结构就是Transformer的编码器(Encoder)部分。

这里的BERT保留了原来的权重,因为这些权重是基于大量语料训练的,拥有语言的很多先验知识,理论上对分词是有正向贡献的。

图1.16中虽然把嵌入层与BERT层(图中显示为Transformer Blocks)分开了,但是理论上这个嵌入层是BERT内置的嵌入层,否则初始化为与BERT不同的emb向量后再经过BERT可能会出现与预测完全不符的结果。所以最初的两层其实可以简单理解为一个BERT动态词向量层。

图1.16 分词模型结构

经过BERT层之后,每个字符都会输出一个向量,这个向量再分别经过两个网络层,一个是与语料库相关的网络,另一个是所有语料库通用的共享网络。这两个网络结构比较简单,就是一个线性映射:

是共享层的输出, 是专属层的输出。图1.16中的多个箭头其实对应的是不同的语料库输入,具体到某个语料库,那么其只会进入对应的专业网络层和共享网络层两个方向。

共享网络层用来提取所有语料(以及其对应的分词标准)通用的特征,而专有网络则用来在通用特征之外提取专属特征。

对两个网络层的输出做一个按位相加:

最后一层就是常见的CRF层。论文里给出的推导是:

对于分词来说, y 的取值为{B,M,E,S}。 是关于 X 对标签 i y 的打分函数,最简单的 s 就是 s =sum(WX), , ,WX的乘积还是个矩阵,再对 n 维度求和,这样 s 的结果就是一个4维向量,对应的就是BMES各自的得分,而上面公式中(,) s X i 的下标 i y 就是取这4维中的某一个值的意思。

s 后面的 b 并不是一个普通的偏置,看看它的下标,有两个 y ,实际上这个 b 不只是一个偏置,它还是一个打分函数,不过因为它的参数只有前一时刻的 和当前时刻的 ,所以最简单的yy打分函数可以直接使用一个参数矩阵,类似一个权重矩阵, b 的下标有两个,都是 y ,一个取行方向,一个取列方向,最后得到一个scalar的标量值,这样就可以跟前面的 s 相加成为最终的得分。

这里要注意,这并不是一个普通的softmax取极值,exp前面有一个连乘号∏,这个连乘就是CRF的关键。其实也不难理解,正常的arg max+softmax只分一次类,就是在4个值中取最大的那一个,而现在是要分 n 次类,每次都有4个值的可能性。这就是前面说的序列标注逻辑。这里的连乘号∏的意思就是求一个最优路径的最优解,而不是使用贪婪算法在每个节点上取极值。

这里只是CRF的初始公式,基于这个公式只能使用穷举法,也就是把每个字所在的位置的每种标签都计算一遍,然后找出最大的那一个。这样的计算量是非常大的,所以正常的CRF都会基于这个公式往下推导,最终推导出的就是Viterbi算法,以节省计算量。

如想要进一步理解CRF,可以参考笔者前面的建议。因为序列标注经常会使用CRF作为最后一层,所以涉及序列标注的章节都有可能会涉及CRF。

模型介绍完了,然而对于一个分词任务来说,性能其实也是非常重要的,在工业行业,分词经常是其他NLP任务的上游,尤其是对于一些在线处理的任务,如查询分析之类,用户本身对一个请求全程时间的耐受极限大概是200ms,而一个分词就占100ms甚至几百毫秒是不能忍受的。这也是直到现在为止工业行业里的分词模型大多还是使用最短路径+HMM/CRF实现的原因。

W Huang等人发表的论文则正视了这个问题,他们对模型进行了一些加速,虽然最终的结果笔者认为依然不可能应用于请求量较大的线上环境,但是可以大致介绍一下。

第一,BERT的12层自注意力对一些相对抽象的NLP任务会有较大帮助,而对于分词这个抽象层级其实非常低的任务,实际上就是不需要理解全局的语义,对远距离的依赖也不大,甚至词意都不需要理解。这种场景下12层的注意力有些过多了,如图1.17所示。

图1.17 BERT层数的影响

我们可以看一下关于BERT不同层数对最终分词准确率的实验关系,层数的增加确实还是可以增加性能指标的,但与付出的代价并不成正比,大致是一个类似log曲线的衰减曲线。为了平衡速度与效果,这里选择了3层。

第二,为了提升推理速度,使用了降低存储精度的方法,就是用float16代替原来的float32。这种方法属于量子化(Quantization)方法里最基础的一种。Quantization最极端的是把图像识别模型全部进行二值化,也就是用0/1代替原来float32的权重值。当然推理精度也下降了不少,但速度确实提升了几十倍甚至上百倍。

第三,这里使用XLA的一种加速技术,这种技术属于硬件底层,这里略过,如图1.18所示。

图1.18 速度提升方法的效果

图1.18下面的数字表示batch,即同时推理的样本数,这里就是分词的句子数。可见其实使用了这么多方法,相对Bi-LSTM而言速度也没有提升太多,最大的是2.6倍,LSTM众所周知的问题之一就是速度慢。

这里有个有意思的地方,就是随着batch数量的增大,BERT相对LSTM的速度也在慢慢变小,甚至batch为256时原装BERT的速度只相当于LSTM的一半。当然,原始的BERT是12层自注意力,直接与一层LSTM对比不太公平,但我们只看相对值,不看绝对值,就是BERT相比LSTM的速度变低了。

这个现象其实是符合预期的,笔者的理解是,Transformer最开始抛弃RNN结构的原因是RNN是循环结构,无法充分并行化,从而导致速度慢。但这个并行是对推断某一条样本而言的,现实中经常是多个任务一起执行,这里的batch只要大于1,就是多个推断任务一起执行。也就是说,虽然RNN在单条任务中无法充分使用GPU,但是只要把batch调大,让任务数多一些,就可以充分使用GPU了。对于BERT(Transformer)而言,因为在一个任务中就有大量并行,GPU资源可能已经饱和,所以在执行多任务时就没有更多的GPU资源并行执行了,只能等前面的任务结束再开始。这样就看到了图1.18所示的结果,当batch少的时候,虽然BERT有12层大计算量的自注意力,但是速度依然跟LSTM差不多,随着batch增大,其开始慢慢显示出不支。至于能支持多少batch的并发,则跟GPU参数相关。实验结果如图1.19所示。

图1.19 实验结果

这个结果比较难得,在10个数据集上全部都达到了最优,一般这种多数据集的模型创新,能在多数数据集上达到最好就可以发表论文了。图1.19中也标出了达到这个效果的是用了3层的BERT自注意层。而降低精度使用float16之后,其实各项指标下降得并不多,虽然推断速度没提升多少,但存储模型参数的空间却肯定下降了一半。对于某些对容易有限制的场景也是有一些意义的。

由此可见,融合多数据集一起训练的方法是有效的。直观的理解其实是增加训练的语料,但1倍语料显然不如10倍语料的训练效果好。但笔者认为,融合训练的效果提升不仅是因为语料的增加。分词领域的语料不仅标准不同,而且使用的环境也不同,因此语法习惯也不完全相同,这样使交叉学习起到了互补的作用。更多的语料其实也隐含增加样本多样性的意思,但样本的多样性与语料多少不是一个强相关关系,而分词的多个语料的多样性与语料数的相关性显然更强。

对于分词领域,占比较多的错误前面也分析过,就是OOV问题(即在训练集里并未出现过的词,在测试集里出现了)。这里对单语料库训练和融合语料库训练的OOV召回率进行了对比,如图1.20所示。

图1.20 OOV召回实验

实验证明,多个语料库之间确实存在互补性。

至此,我们已经学习了关于多个不同标准的分词语料库的融合方法,到这里就结束了吗?还没有。我们已经使用过特殊标签及共享部分网络两种方法,还有什么探索方向呢?其实还有针对不同语料库的私有网络值得研究。

1.3.5 分词的多标准融合学习1

1.3.4节提到的论文创新点比较少,就是在每个语料库使用同样的共享层基础上增加了一个专用层,来建模不同语料的不同之处。接下来我们要介绍的这个模型是多语料库多标准融合学习的最后一种尝试,如图1.21所示。

图1.21 分词模型的三种结构

单语料分词模型可以简单地视为一个专有编码层(Private Encoder)和一个专有的解码层,如图1.21(a)所示。而对于多语料融合学习则可以分为两种,一种就是前面说过的共享层加上专有层,如图1.21(b)所示,另一种就是全共享,共享的编码层(Shared Encoder)和共享的解码层,如图1.21(c)所示。

其实前面章节介绍的简易融合学习版本也是一种全共享方案,用以区分不同语料的方法是在每个句子前后加上独有的标识,而模型使用的则是常见的Bi-LSTM+CRF。很巧合,本节介绍的模型也使用了这个方案,如图1.22所示。

图1.22 网络结构

本节模型与前面介绍的模型的区别就是底层模型由LSTM换成Transformer的编码器,其实就是BERT的结构,然后附加一些手工特征,从而最终让指标达到近似于SOTA的水准。

1.嵌入层

给定一个句子 X = x 1 ,…, x T ,先把每个字符映射到一个向量上,这个字向量可以是预先训练好的,如Word2vec或BERT里的Embedding层,也可以从随机初始化开始训练。除此之外,还加上了3个手工特征。

(1)语料库标识 m ,加在每个句子的开头,如图1.21所示。例如,对于PKU语料库来说,就在开头加一个 m ,如果总共有10个语料库,字符词典的长度为 k ,那么字符的one-hot向量维度就是 k +10。与1.3.3节的简易融合不同的是,这里没有在末尾也加上同样的标识,这个末尾的同功能标识确实感觉有些冗余。

(2)bi-gram信息,其在前面介绍过,不少分词模型也尝试过加入bi-gram信息,并且证明了确实对最终结果有正贡献。具体来说就是使用Word2vec单独训练一遍双字向量,注意这里不是分词,只是两个连续的字。最后拼接起来作为这里用于分词的字向量的补充:

(3)位置编码,跟Transformer的位置基本一样。

i 对应于字向量的第 i 维, d 就是字向量的维度, t 就是时间步。最终序列 X 的嵌入向量就可以表达如下:

2.编码层

这里的编码层其实就是一个Transformer的编码器部分,也就是多层多头自注意力。其公式如下:

公式中的 W 是可训练的权重, i 是指第 i 个头的参数计算。

这是一个头的自注意力,可通过多种随机初始化,训练出多个头,最后把多头自注意力的结果拼接到一起:

LN是layer-norm的缩写,就是归一化。resnet就是一层残差网络,其实跟LSTM里面的一个门的逻辑类似,就是计算一个门控阀门,然后控制两路输入哪一部分占比更多:

H '就是第一个完整的自注意力层的输出,作为下一个自注意力层的输入。

3.解码层

解码层就是常见的CRF。实验结果如图1.23所示。

图1.23 实验结果对比

虽然这里的对比模型都不是最好的模型,单纯看本模型使用的Transformer,将1.3.4节的单数据集训练结果与多标注融合训练结果对比可以看到,除了OOV指标提升幅度较大之外,准确率、召回率和F1指标的提升幅度非常小。与1.3.4节介绍的拥有专享网络层的结果对比来看,此处的结果略高一点,而OOV指标却比1.3.4节降低了不少。

可以得出结论,对于分词的多标准融合训练,使用共享网络+专有网络的效果更好一些。如果在1.3.4节的模型中也加入bi-gram的特征,结果会反超现在的模型,如图1.24所示。

这里进行了模块去除的消融实验,也证明了上面得出的结论。把bi-gram去掉之后,整体指标下降了一些,比1.3.4节模型的最终指标数据降低了。同时,这个实验也表明,对于Transformer这种模型来说,使用CRF带来的指标提升效果可以忽略不计,而且CRF的训练和推断速度都比MLP慢很多,因此在很多场景下完全可以不使用CRF。

图1.24 模块消融实验

1.3.6 分词的多标准融合学习2

为什么还是学习多标准融合?因为其效果比较好,查看最近中文分词领域的论文可知,单数据集的训练结果与多数据集的结果普遍相差1%~2%。这其中的原因我们前面已经分析过,如果现在有一个非常巨量的单一标准中文分词语料库,最终的结果是否还是比多标准数据集差,笔者不敢肯定,但至少现在没有这样的巨量数据集,所以充分利用已有的数据集就是现今关键的一个探索方向。

Zhen Ke、Liang Shi和Erli Meng等人发表的论文Unified Multi-Criteria Chinese Word Segmentation with BERT中的模型是由复旦大学与小米公司联合研究的。前面讲述了各种区分不同标准数据集的方法,如增加专有网络层,在句子的前后增加独有标识等。这里做了一个创新尝试,就是在输入独有标识的同时在输出端也增加一个任务,用来预测这个句子属于哪个数据集,其实就是预测这个独有的标识。

其实这并非什么创新,某种信息 K 如果想让其对某个机器学习任务 T 有贡献,本来就有两种方法。一种就是把 K 作为输入信息 X 的一部分输入网络,然后利用这些输入信息进行训练,如果输入的信息 K 与任务推断 T 有相关性,模型就必然可以学习到一些逻辑。另一种就是反着操作,即在输入的时候不附带这个信息 K ,而是在输出的时候需要通过这些原有的信息 X 额外预测出这个 K 。因为在训练阶段 K 是已知的,相当于另外一种输入的信息,所以模型也能学习到相关逻辑。

不过上述论文中的相关方法,笔者有一些不同的意见,一个信息既被用于输入,又被用于预测输出,这样模型完全可以基于输入的信息不通过任何运算直接输出。例如,要识别图像里面的对象是狗还是猫,如果在有监督训练的同时把对应的猫和狗的标签也作为 X 输入网络,那么网络完全可以不去学习图像本身的特征,直接可以基于输入的猫和狗信息得出高准确率的结果,只是这样的网络模型是学不到任何东西的。

具体结果怎么样,先看模型的整体结构,如图1.25所示。

这个模型也是使用了全共享式的结构,也就是不同的数据集都使用同样的模型网络。为了区分不同的数据集,输入的时候在句子前面必须加上唯一标识,这与前面介绍的几个模型的做法是相同的。

这里的第一层没有直接使用Embedding,而是经过了一个BERT。可以理解为把BERT作为预训练的词向量使用了,因为BERT是动态的词向量,所以只能通过模型计算,而不能直接取出结果向量:

这里的 T 就是句子的长度,+1就是加上数据集标识, d h 就是输出的字向量维度。

图1.25 模型整体结构

然后同样保持中文多标准分词的传统,输入了bi-gram的特征,但不同的是,这里并没有直接与字向量进行拼接,而是经过了一层混淆层的融合:

这里的 E 就是bi-gram的双字向量。

融合公式如下:

公式的前两行很简单,就是一个线性映射加一个tanh变换。后面的式子是一个类门控,类似GRU基于这个门控决定字向量和双字向量哪路的输入占比更高,然后相加进行融合输出。

从本质上看这种方法类似残差网络,或者可以理解为LSTM的门控输出。这样做的目的是只保留更有用的信息,把没用的信息过滤掉,避免浪费计算量。

后面接上多头自注意力层、残差网络和归一层,其实还是Transformer的编码器部分的一个完整多头自注意力层:

这里没明确标出来残差网络,中间的加号就是残差的意思。

解码分为两部分,一部分就是分词常用的序列标注解码组件,这里用的是MLP,也就是一层全连接,直接用贪婪算法求每一步的极值或用Beam Search求序列最大值:

最后的下标表示选择输出向量中标签 y t 对应的那个位置的值。

解码的另一部分就是前面说过的预测数据集的标识。

这里的 h 0 是第一层BERT输出的第一个单元, C 是数据集的数量。

损失函数是:

N 是训练集的句子数量。

下面再来看看实验结果对比,如图1.26所示。

图1.26 实验结果对比

这个结果同时进行了模块的消融实验。先看全模块的数据,基本上达到了SOTA水准,比前面两个模型的指标稍高一些。模型结构其实并没有太大的改变,笔者认为其主要贡献应该是使用预训练的BERT作为字向量信息。而所谓的数据集预测任务,图1.26中的-CLS部分也可以见到,其实并没有什么效果,甚至整体指标去掉CLS模型与加上CLS模型在各个数据集上的指标对比结果几乎相同。这个结果其实我们在前面已经预料到了,把信息同时作为输入和目标,网络是很容易记住这个规则的,难以从中真正学习到有用的特征。

再看一下OOV实验的对比,如图1.27所示。这里主要对比的是SOTA模型Multi-Task BERT,该模型我们并没介绍过,但大致的方法与本节所讲的模型类似,其也是因为增加了BERT作为字向量而在效果上得到了一些提升。

图1.27 OOV实验结果对比

介绍到这里,分词模型基本就告一段落了。如果分词模型不用BERT作为字向量的来源,而是使用百度的ERNIE或XLNET之类的优化型BERT,那么或许可以再提升一些指标,但提升的贡献来自上游的预训练模型而不是分词模型本身,所以也不会有什么创新。 fzO0d4eRxjElFSRL5Sc1LDTQ8q2rKALovUD6bcve/PDt83mw0EtbtAiqeOvk2KQS

点击中间区域
呼出菜单
上一章
目录
下一章
×