基于BERT+BiLSTM+CRF做中文分词

本文介绍了基于BERT+BiLSTM+CRF的中文分词流程,BERT提供语境化词向量,BiLSTM处理序列信息,CRF考虑标签间的依赖关系,解决分词中的歧义问题。该模型在中文信息处理如搜索引擎、机器翻译等领域有广泛应用。
摘要由CSDN通过智能技术生成

        本文是一次基于BERT+BiLSTM+CRF做中文分词的具体流程,方便自己查看,如有错误的地方,还请各位不吝赐教!

1.汉语分词:

        事先声明,本节汉语分词任务的介绍都可以百度出来,只是整合搬运了一下!

(1)分词的概念

        一般分词是NLP(自然语言处理)的第一项核心技术。英文中每个句子都将词用空格或标点符号分隔开来,而在中文中很难对词的边界进行界定,难以将词划分出来。在汉语中,虽然是以字为最小单位,但是一篇文章的语义表达却仍然是以词来划分的。因此处理中文文本时,需要进行分词处理,将句子转为词的表示。

(2)汉语分词的意义和作用

        对于中文分词的意义和作用,就要提到智能计算技术。智能计算技术涉及的学科包括数学、计算机科学、电子机械、通讯、生理学、进化理论和心理学等等。简单来说,智能计算就是让机器“能看会想,能听会讲”。要想实现这样的一个目标,首先就要让机器理解人类的语言,只有机器理解了人类的语言文字,才使得人与机器的交流成为可能。

        对于人类语言而言,“词是最小的能够独立活动的有意义的语言成分”,所以对于中文来讲,将词确定下来是理解自然语言的第一步,只有跨越了这一步,中文才能像英文那样过渡到短语划分、概念抽取以及主题分析,以至自然语言理解,最终达到智能计算的最高境界。

        从现阶段的实际情况来看,英文已经跨越了分词这一步,并且已经展现了良好的应用前景,无论是信息检索还是主题分析的研究都要强于中文,究其根本原因就是中文要通过分词这道难关,只有攻破了这道难关,我们才有希望赶上并超过英文在信息领域的发展,所以中文分词对我们来说意义重大,可以说直接影响到使用中文的每一个人的方方面面。

        以搜索引擎为例,对于搜索引擎来说,最重要的并不是找到所有结果,因为在上百亿的网页中找到所有结果没有太多的意义,最重要的是把最相关的结果排在最前面,这也称为相关度排序。中文分词的准确与否,常常直接影响到对搜索结果的相关度排序。         

        Google的中文分词技术采用的是美国Basis Technology公司提供的中文分词技术,百度使用的是自己公司开发的分词技术,中搜使用的是国内海量科技提供的分词技术。由此可见,中文分词的准确度,对搜索引擎结果相关性和准确性有相当大的关系。

(3)“汉语分词”的典型应用

        中文分词是其他中文信息处理的基础,搜索引擎只是中文分词的一个应用。此外,在机器翻译(MT)、语音合成、自动分类、自动摘要、自动校对等等,都需要用到汉语分词。

(4)“汉语分词”的技术难点

A.歧义识别

        歧义是指同样的一句话,可能有两种或者更多的切分方法。歧义又分为组合型歧义、交集型歧义和真歧义三种类型。

(a) 组合型歧义:分词是有不同的粒度的,指某个词条中的一部分也可以切分为一个独立的词条。比如“中华人民共和国”,粗粒度的分词就是“中华人民共和国”,细粒度的分词可能是“中华/人民/共和国”

(b)交集型歧义:在“郑州天和服装厂”中,“天和”是厂名,是一个专有词,“和服”也是一个词,它们共用了“和”字。

(c)真歧义:本身的语法和语义都没有问题, 即便采用人工切分也会产生同样的歧义,只有通过上下文的语义环境才能给出正确的切分结果。例如:对于句子“美国会通过对台售武法案”,既可以切分成“美国/会/通过对台售武法案”,又可以切分成“美/国会/通过对台售武法案”。

B.分词标准

        比如人名,在哈工大的标准中姓和名是分开的,但在Hanlp中是合在一起的。这需要根据不同的需求制定不同的分词标准。

C.新词

        新词也称未被词典收录的词,该问题的解决依赖于人们对分词技术和汉语语言结构的进一步认识。

2.数据集及预处理:

        数据集来源于SIGHAN 2005第二届中文分词任务中的Peking University数据集。数据集共19814条句子,总共4699个字(不重复)。

        首先,对于汉语分词任务而言,汉字分词无非有两种情况,一种是一个字,其余则是多字组合。每个字在构造一个特定词语时都占据着一个特定的位置即词位,一般采用四结构词位:B(词首),M(词中),E(词尾)和S(单独成词),即每个字有对应的四种可能状态,相当于为每一个汉字做四分类的任务。

        在该数据集中以空格分开词,即相当于有标注的文本,因为该文本比较干净,所以无需过多的预处理,只是按照空格划分来标注汉字,按照词的长度对每一个汉字打标签,对于超出最大长度的文本(最大长度为500),则以最大长度作为限制将一段文本拆分成多段。

        预处理过后的数据与标签如下图所示:

 数据与对应标签(前五个)

        之后是将标签映射成0-3,分别对应着BMES的标签,对于单独的汉字,则是统计总共的汉字个数,从        

预处理之后,是将得到的数据划分成一个个token,本次使用的模型是bert-base-chinese,

3.模型架构介绍:

(1)整体架构:

        目前对于NLP任务,较为通用的框架是使用预训练模型+针对下游任务的微调这种处理范式。对于汉语分词的上游任务语言预处理而言, 一直是研究的热点问题。而BERT作为先进的语言预处理模型, 可以获取高质量的词向量(相较于传统模型的Word2Vec), 从而更有利于下游任务进行特征提取和分类。BERT-BiLSTM-CRF模型整体结构如图所示, 这个模型主要分3个模块。首先标注语料经过BERT预训练语言模型获得相应的词向量, 之后再把词向量输入到BiLSTM模块中做进一步处理, 最终利用CRF模块对BiLSTM模块的输出结果进行解码, 得到一个预测标注序列, 然后对序列中的各个实体进行提取分类, 从而完成中文实体识别的整个流程。

 模型架构

(2)Bert:

        Bert作为该模型中的预处理模块,主要作用是提取出序列中丰富的词级特征、语法结构特征和语义特征,经过BERT处理过后能够获得语境化的词向量, 对处理长距离依赖信息的语句有很好的效果。

        BERT的本质上是通过在海量的语料的基础上运行自监督学习方法为单词学习一个好的特征表示,所谓自监督学习是指在没有人工标注的数据上运行的监督学习。在以后特定的NLP任务中,我们可以直接使用BERT的特征表示作为该任务的词嵌入特征。所以BERT提供的是一个供其它任务迁移学习的模型,该模型可以根据任务微调或者固定之后作为特征提取器。

        随着研究的不断深入,对于语言模型的研究先后经历了one-hot、Word2Vec、ELMO(2014)、GPT(2018)到BERT(2018),前几个语言模型均存在一些缺陷,,如Word2Vec模型训练出来的词向量是属于静态Word Embedding,无法表示一词多义; GPT使用的Transformer的Decoder,属于属于生成式模型,是单向语言模型, 无法获取一个字词的上下文。而对BERT模型而言, 它是综合ELMO和GPT这两者的优势而构造出来的模型,它使用的是TRansformer的Encoder,在训练时通过MLM(Masked Language Model)和NSP(Next Sequence Prediction)来计算损失,未来更多的证据证明,MLM是一种十分有效的方式。由于BERT具有很强的语义表征优势, 可以利用BERT获取语境化的词向量来提高实体识别的性能。

        Bert架构如下图所示。对于任意序列, 首先通过分词处理得到分词文本序列; 然后对分词序列的部分词进行全词Mask, 再为序列的开头添加一个特殊标记[CLS], 句子间用标记[SEP]分隔。此时序列的每个词的输出Embedding由3部分组成: Token Embedding、Segment Embedding和Position Embedding。将序列向量输入到双向Transformer进行特征提取, 最后得到含有丰富语义特征的序列向量。当然,输入形式一般要根据下游任务具体而定,比如在分词中不需要NSP损失,也自然不需要同时输入两个句子来判断是不是相邻句子,也不需要[SEP]分隔符;而[CLS]则置于文本序列之前,用以表征全局信息。

Bert架构

        Bert使用的Transformer的Encoder结构,如图所示。Transformer使用的编码层只有Positional Embedding,并且是不可训练的,采用正余弦编码,因为Transformer无法得到序列中每个token的前后位置关系,所以采用位置编码来记录每个token在序列中的位置,与Transformer不一样的是,Bert不仅使用了Positional Embedding,而且加入了Patch Embedding和Token Embedding,Token Embedding就是将词划分成一个合适的个体或组合,比如playing可以划分成play和ing,在中文中自然就代表一个字。Patch Embedding采用0-1编码,0代表第一个句子,1代表第二个句子,用于区分不同的句子。Bert的Positional Embedding与Transformer不同,Bert的PE是直接从0向后递增得到的,没有采用Transformer的正余弦编码,因为发现简单的递增位置嵌入效果就已经很好了,且在Bert中PE是可训练的。

 

(3)BiLSTM

        LSTM (Long-Short Term Memory, 长短期记忆网络), 是循环神经网络(RNN)的一种变体。它解决了RNN训练时所产生的梯度爆炸或梯度消失。LSTM巧妙地运用门控概念实现长期记忆, 同时它也能够捕捉序列信息。 

        LSTM的核心主要是以下结构: 遗忘门、输入门、输出门以及记忆单元。输入门与遗忘门两者的共同作用就是舍弃无用的信息, 把有用的信息传入到下一时刻。 对于整个结构的输出, 主要是记忆单元的输出和输出门的输出相乘所得到的。

        相较于单向的LSTM,双向LSTM可以看到上下文信息,能给出更贴近语境的输出。在模型中,BiLSTM接受来自BERT的输出,作为双向LSTM各个时间步的输入,再将正向LSTM输出的隐状态序列与反向LSTM的在各个位置输出的隐状态进行按位置拼接,得到完整的隐状态序列。为了防止过拟合,设置dropout。之后接入一个全连接层,得到对每个词预测的标签。

(4)CRF

        在汉语分词识别任务中, BiLSTM善于处理长距离的文本信息, 但无法处理相邻标签之间的依赖关系。BiLSTM只能利用到序列的上下文信息给出最有可能的预测,但是无法利用其预测出的信息来帮助预测,具体来说,中文分词的标签共有“BMES”四种,如果一个字被预测为M,则他的前一个字一定是B或者M,不可能是E或S,这就是标签之间的约束关系,而BiLSTM无法利用这层关系,而CRF能通过邻近标签的关系获得一个最优的预测序列, 可以弥补BiLSTM的缺点。CRF层,进行句子级的序列标注。

        CRF层的参数表示的是从第i个标签到第j个标签的转移得分,进而在为一个位置进行标注的时候可以利用此前已经标注过的标签,之所以要加2是因为要为句子首部添加一个起始状态以及为句子尾部添加一个终止状态。如果记一个长度等于句子长度的标签序列,那么模型对于句子的标签等于的打分为。下图得分中包含发射得分和状态转移得分两部分。发射得分指的是BiLSTM输出的标签的得分,状态转移得分是CRF由i状态转移到j状态的概率,公式中的A是加权系数(可以使用自使用损失函数加权计算出),状态转移得分相当于对BiLSTM的输出加入了约束,规范其输出,降低出现预测为E的字前面是E或S的可能性。

        如何去评估当前状态的得分呢?通过预测出的最优路径的得分与所有路径得分的比值来衡量。比值越大,说明越合理。损失函数为-logP(y|x),即负对数似然,P(y|x)越大,loss越小。

 

BERT-BiLSTM-CRF是一种基于深度学习中文分词方法,它结合了BERT预训练模型、双向长短时记忆网络(BiLSTM)和条件随机场(CRF)模型。具体流程如下: 1. 预处理:将中文文本转换为字符序列,并将每个字符转换为对应的向量表示。 2. BERT编码:使用BERT模型对字符序列进行编码,得到每个字符的上下文表示。 3. BiLSTM编码:将BERT编码后的字符向量输入到双向LSTM中,得到每个字符的上下文表示。 4. CRF解码:使用CRF模型对BiLSTM编码后的结果进行解码,得到最终的分词结果。 以下是BERT-BiLSTM-CRF中文分词Python代码示例: ```python import torch import torch.nn as nn from transformers import BertModel class BertBiLSTMCRF(nn.Module): def __init__(self, bert_path, num_tags): super(BertBiLSTMCRF, self).__init__() self.bert = BertModel.from_pretrained(bert_path) self.lstm = nn.LSTM(input_size=self.bert.config.hidden_size, hidden_size=self.bert.config.hidden_size // 2, num_layers=1, bidirectional=True, batch_first=True) self.dropout = nn.Dropout(p=0.5) self.fc = nn.Linear(self.bert.config.hidden_size, num_tags) self.crf = CRF(num_tags) def forward(self, input_ids, attention_mask): bert_output = self.bert(input_ids=input_ids, attention_mask=attention_mask)[0] lstm_output, _ = self.lstm(bert_output) lstm_output = self.dropout(lstm_output) emissions = self.fc(lstm_output) return emissions def loss(self, input_ids, attention_mask, tags): emissions = self.forward(input_ids, attention_mask) loss = self.crf(emissions, tags, mask=attention_mask.byte(), reduction='mean') return -loss def decode(self, input_ids, attention_mask): emissions = self.forward(input_ids, attention_mask) return self.crf.decode(emissions, attention_mask.byte()) ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值