开源项目kcws代码分析--基于深度学习的分词技术
来源:互联网 发布:上海哪里有mac专柜 编辑:程序博客网 时间:2024/06/10 06:28
转自http://blog.csdn.net/pirage/article/details/53424544
分词原理
本小节内容参考待字闺中的两篇博文:
- 97.5%准确率的深度学习中文分词(字嵌入+Bi-LSTM+CRF)
- 如何深度理解Koth的深度分词?
简单的说,kcws的分词原理就是:
- 对语料进行处理,使用word2vec对语料的字进行嵌入,每个字特征为50维。
- 得到字嵌入后,用字嵌入特征喂给双向LSTM, 对输出的隐层加一个线性层,然后加一个CRF就得到本文实现的模型。
- 于最优化方法,文本语言模型类的貌似Adam效果更好, 对于分类之类的,貌似AdaDelta效果更好。
另外,字符嵌入的表示可以是纯预训练的,但也可以在训练模型的时候再fine-tune,一般而言后者效果更好。对于fine-tune的情形,可以在字符嵌入后,输入双向LSTM之前加入dropout进一步提升模型效果。
具体的解决方案,基于双向LSTM与CRF的神经网络结构:
如上图所示,单层圆圈代表的word embedding输入层,菱形代表学习输入的决定性方程,双层圆圈代表随机变量。信息流将输入层的word embedding送到双向LSTM, l(i)代表word(i)和从左边传入的历史信号,r(i)代表word(i)以及从右边传入的未来的信号,用c(i)连接这两个向量的信息,代表词word(i)。
先说Bi-LSTM这个双向模型,LSTM的变种有很多,基本流程都是一样的,文献中同样采用上一节说明的三个门,控制送入memory cell的输入信息,以及遗忘之前阶段信息的比例,再对细胞状态进行更新,最后用tanh方程对更新后的细胞状态再做处理,与sigmoid叠加相乘作为最终输出。具体的模型公式见下图,经过上一节的解释,这些符号应该不太陌生了。
双向LSTM说白了,就是先从左至右,顺序学习输入词序列的历史信息,再从右至左,学习输入词序列未来影响现在的信息,结合这两种方式的最终表示有效地描述了词的内容,在多种标注应用上取得了好效果。
如果说双向LSTM并不特殊,这个结构中另一个新的尝试,就是将深度神经网络最后学出来的结果,作为特征,用CRF模型连接起来,用P来表示双向LSTM神经网络学习出来的打分输出矩阵,它是一个 nxk 的矩阵,n是输入词序列个数,k是标记类型的数目, P(ij)指的是在一个输入句子中,第i个词在第j个tag标记上的可能性(打分)。另外一个特征函数是状态转移矩阵 A,A(ij) 代表从tag i转移到tag j的可能性(打分),但这个转移矩阵实际上有k+2维,其中包括句子的开始和结束两个状态,用公式表示如下图:
在给定输入序列X,最终定义的输出y序列的概率,则使用softmax函数表示如下:
而在训练学习目标函数的时候,要优化的就是下面这个预测输出标记序列的log概率,其中 Y(X)代表的是所有可能的tag标记序列集合,那么最后学习得到的输出,就是概率最大的那个标记序列。如果只是模拟输出的bigram交互影响方式,采用动态规划即可求解下列方程。
至此,基于双向LSTM与CRF的神经网络结构已经介绍完毕,文献中介绍的是在命名实体识别方面的一个实践应用,这个思路同样可以用在分词上。具体的实践和调参,也得应场景而异,Koth在上一篇博客中已经给出了自己的践行,读者们可以借鉴参考。
代码结构与实践
koth大神开源的项目地址为:https://github.com/koth/kcws
主要的代码在目录kcws/kcws/train路径下。(写这篇文章的时候发现K大神做了更新,我主要还是分析之前的代码)
- process_anno_file.py 将人民网2014训练语料进行单字切割,包括标点符号
- generate_training.py 生成单字的vector之后,处理每篇训练语料,以“。”划分为句子,对每个句子,如果长度大于MAX_LEN(默认设置为80,在代码里改),不处理,Long lines加一,如果长度小于MAX_LEN,则生成长度为160的vector,前80为单字在字典中的index,不足80的补0,后80为每个字对应的SBME标记(S表示单字,B表示开始,M表示中间,E表示结尾)。
- filter_sentence.py 将语料切分为训练集和测试集,作者将含有两个字以下的句子过滤掉,剩下的按照二八分,测试集最多8000篇。
- train_cws_lstm.py 主要训练代码。
作者在项目主页上很详细的写了构建和训练的步骤,按照这些步骤来实践一下不算难,我主要遇到了以下几个问题:
- 之前安装tensorflow的时候没有用bazel,不了解bazel的工作方式和原理,但是这个项目必须要用,因为需要用到third_party中word2vec的类。(可以将word2vec的某些类构建为python可以import的类?)
- 已安装的0.8.0版本的tensorflow没有实现crf,需要升级。
- 安装tensorflow 0.11.0版本后运行,出现PyUnicodeUCS4_AsUTF8String的错误,查找后发现是当前安装的python默认是unicode=ucs2,需要重新编译安装python。编译的时候设置./configure –enable-unicode=ucs4 。
- numpy,scipy都需要重新build,setup。
主要代码分析
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
Class Model:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
其他的代码比较简单,个人觉得不必要做深入分析。
- 开源项目kcws代码分析--基于深度学习的分词技术
- 开源项目kcws代码分析--基于深度学习的分词技术
- kcws分词模型
- 基于深度学习的商品检索技术
- 基于统计的分词技术
- 深度学习之六,基于RNN(GRU,LSTM)的语言模型分析与theano代码实现
- caffe架构学习之(一)--基于google protocol buffer开源项目的深度网络定义
- caffe架构学习之(一)--基于google protocol buffer开源项目的深度网络定义
- 深度学习在分词上的应用
- 基于深度学习的VQA(视觉问答)技术
- 基于深度学习的人脸识别技术综述
- 基于深度学习技术的语义分割综述
- 基于深度学习的目标检测技术演进(转)
- 基于深度学习的图像语义分析及其应用
- baidu分词技术分析
- Java开源分词系统IKAnalyzer学习(八) 基于词库分词
- 基于深度学习的图像语义分割技术概述之背景与深度网络架构
- 基于深度学习的图像语义分割技术概述之背景与深度网络架构
- 670. Maximum Swap
- 前台与PHP与Mysql
- yarn-日志聚合功能
- Dagger2入门,以初学者角度来观察
- oracle通过sqlldr导入文本数据
- 开源项目kcws代码分析--基于深度学习的分词技术
- C++ 指针篇01
- vim编辑器
- SpringMVC上传图片总结
- 关于虚拟机网络配置问题
- ActiveMQ
- SpringSecurity在SpringBoot 的实际应用
- Netty 断包
- 第一次记录