项目地址
链接:https://github.com/ganguagua/priori-lstm
解决问题
- 模型不能充分运用词典的先验信息
- 自己从头训练模型所需的数据量大,且所需时间长
- 对于不能识别的新词,模型需要重新训练,流程冗长,效率低
- 准确率达到95%以上,同时在词典更新时能很好的识别新词
核心思路
- 运用预训练模型,bert是字模型的,可以用bert的embedding矩阵,加速模型收敛,保证模型泛化
- 模型结构采用双向LSTM,结合上下文信息,更准确
- 把最大匹配的结果和字的embedding concat在一起作为LSTM输入,充分利用先验信息
- 模型结构图
- 标签设计
每个字对应两种标签,是一个词的末尾和不是,end/not-end
相关知识
1. 最大前向匹配
规则:首先需要一个词典,然后从前往后去匹配,优先匹配长度更长的词汇。
详细说明:以“人们常说生活是一部教科书,而血与火的战争更是不可多得的教科书”这句话为例,词典中只要有{“人们”,“生活”, “教科书”, “战争”, “不可多得”}, 用最大前向匹配即可正确切分成“人们 常 说 生活 是 一 部 教科书 , 而 血 与 火 的 战争 更 是 不可多得 的 教科书”。为什么要最大匹配,是因为词汇之间有包含关系,有最大匹配的准确率更高。例如“北京大学” 可以是“北京”、“大学”两个词汇,但是“北京大学”作为一个词更符合我们的语言习惯。至于前向匹配和后向匹配是差不多的,结合起来看会更好。
2. LSTM模型
由来:早期的词袋模型不能解决语序的问题,ngram也只能解决短依赖,且没出现过的组合就很难识别。NLP中长依赖很多,特别是英语中,常见的就是各种代词、从句。例如 “我的孩子天资还不错,但学习成绩一般,小动作较多,老师不是特别喜欢他” 这句话中的“他”指的是“我的孩子”,传统的ngram或者cnn都没办法解决。RNN就应运而生了。将一个序列分一个个时间布,依次输入一个网络结构,后输入就可以根据先输入的做调整关联。而这种比较好的网络结构就是LSTM,之后又有GRU,两者效果相当,GRU计算更快。
详细介绍可以去网上搜一下,相关资料非常多,应用也非常广泛
3. bert预训练模型
模型结构:文字 通过字典映射转成 id序列 ,再通过embedding矩阵转成向量矩阵;再通过transformer结构得到上下文语义信息;id转向量其实就是个查表,对应到tensorflow中就是tf.gather。
注意力机制:和rnn相比,注意力机制可以并行计算,实现工业级应用。核心就是计算权重矩阵,即每个位置对其他位置的权重贡献。bert的transformer 通过Q K V三个矩阵实现,Q·K得到权重矩阵,再乘上V得到上下文语义。
预训练:类似word2vec的完形填空,用海量的无监督数据先去训练好底层参数,例如上面说的embedding矩阵,实际应用时再用高质量的标注数据做微调。项目用的就是bert的embedding矩阵,因为bert在各个NLP任务中都取得了state of art。
使用说明
- 训练数据:项目用的是微软的公开数据集,读者可以按照格式自行增加,在lstm.conf中可以配置文件路径
- 环境:需要在python3 tensorflow2.0中使用
- 训练:python controller.py train
- 预测:python controller.py predict