开源中文分词工具探析(五):FNLP
2017-03-16 14:29
483 查看
FNLP是由Fudan NLP实验室的邱锡鹏老师开源的一套Java写就的中文NLP工具包,提供诸如分词、词性标注、文本分类、依存句法分析等功能。
【开源中文分词工具探析】系列:
开源中文分词工具探析(一):ICTCLAS (NLPIR)
开源中文分词工具探析(二):Jieba
开源中文分词工具探析(三):Ansj
开源中文分词工具探析(四):THULAC
开源中文分词工具探析(五):FNLP
开源中文分词工具探析(六):Stanford CoreNLP
\[
S(X,Y) = \sum_s w_s * \Phi_s(X,Y)
\]
则序列标注问题对应于求解:
\[
\mathop{\arg \max}_{Y} S(X,Y)
\]
THULAC是采用感知器来学习参数\(w_s\),而FNLP则是采用在线学习算法Passive-Aggressive(PA) [2]。PA算法结合感知器与SVM的优点,学习速度快;损失函数为hinge loss:
\[
loss(W;(X,Y)) = \left \{
{
\matrix {
{0,} & {\gamma (W;(X,Y)) \ 1} \cr
{1- \gamma (W;(X,Y))} & { otherwise} \cr
}
}
\right.
\]
其中,\(\gamma (W;(X,Y))\)为边际距离,定义为:
\[
\gamma (W;(X,Y)) = S(X,Y) - S(X,\hat{Y})
\]
\(\hat{Y}\)为错误序列标注中得分最高(score函数最大值)的标签。关于参数更新策略的细节请参看FNLP Book [3].
其中,类
类
Map的size为441006,即为特征总数(感觉FNLP的训练语料太少);特征由index + 特征值组成,共有14种。至于特征模板是如何定义,且看下下一小节。
解码同CRF、结构化感知器SP一样为Viterbi算法,具体实现见类
特征模板格式与CRF++相类似;从上可以看出,有1个类别转移特征(index 0),5个unigram字符状态特征(index 1, 4, 5, 6, 7),4个bigram字符状态特征(index 8, 9, 10, 11),1个trigram字符状态特征(index 12),3个字符状态与类型的混合特征(index 2, 3, 13)。其中,FNLP的enum
我们来直观感受下FNLP的分词效果:
可以看出,FNLP分词的粒度不均匀,准确性不是太高;应该是跟训练语料太少有关系,训练不充分而导致的。
[2] Crammer, Koby, et al. "Online passive-aggressive algorithms." Journal of Machine Learning Research 7.Mar (2006): 551-585.
[3] 邱锡鹏, “自然语言处理原理与实现”, 2014.
【开源中文分词工具探析】系列:
开源中文分词工具探析(一):ICTCLAS (NLPIR)
开源中文分词工具探析(二):Jieba
开源中文分词工具探析(三):Ansj
开源中文分词工具探析(四):THULAC
开源中文分词工具探析(五):FNLP
开源中文分词工具探析(六):Stanford CoreNLP
1. 前言
类似于THULAC,FNLP也是采用线性模型(linear model)分词。较于对数线性模型(log-linear model)HMM/CRF所不同的是,线性模型没有归一化因子而直接建模Score函数:\[
S(X,Y) = \sum_s w_s * \Phi_s(X,Y)
\]
则序列标注问题对应于求解:
\[
\mathop{\arg \max}_{Y} S(X,Y)
\]
THULAC是采用感知器来学习参数\(w_s\),而FNLP则是采用在线学习算法Passive-Aggressive(PA) [2]。PA算法结合感知器与SVM的优点,学习速度快;损失函数为hinge loss:
\[
loss(W;(X,Y)) = \left \{
{
\matrix {
{0,} & {\gamma (W;(X,Y)) \ 1} \cr
{1- \gamma (W;(X,Y))} & { otherwise} \cr
}
}
\right.
\]
其中,\(\gamma (W;(X,Y))\)为边际距离,定义为:
\[
\gamma (W;(X,Y)) = S(X,Y) - S(X,\hat{Y})
\]
\(\hat{Y}\)为错误序列标注中得分最高(score函数最大值)的标签。关于参数更新策略的细节请参看FNLP Book [3].
2. 分解
以下源码分析基于fnlp-2.1版本。训练模型
中文分词的训练模型为seg.m,由两个类
TempletGroup与
Linear序列化压缩而成:
ObjectInputStream in = new ObjectInputStream(new BufferedInputStream( new GZIPInputStream(new FileInputStream("models/seg.m")))); TempletGroup templets = (TempletGroup) in.readObject(); Linear cl = (Linear) in.readObject();
其中,类
TempletGroup定义了特征模板,
Linear包含了特征模板、特征及其偏移量、权重数组:
// main field public Inferencer inferencer; protected AlphabetFactory factory; // details about `factory` field .factory: AlphabetFactory .maps { "LABELS" -> LabelAlphabet(data: {S=0,M=2,E=3,B=1}) "FEATURES" -> StringFeatureAlphabet(data: TObjectIntCustomHashMap<String>)} // StringFeatureAlphabet记录了feature在weights数组中的偏移 // details about `inferencer` field .inferencer: LinearViterbi protected float[] weights; public TempletGroup templets;
类
StringFeatureAlphabet的变量data为一个TObjectIntMap,K为特征,V为偏移量,如下所示:
0: 32 1:供/ 414540 2:O/ 14372 2:L/ 131248 3:煞/C/ 147492 5:呼/ 20032 8:哈/钦/ 419968 12:拉/杰/沙/ 350972 13:L/文/C/ 1324032
Map的size为441006,即为特征总数(感觉FNLP的训练语料太少);特征由index + 特征值组成,共有14种。至于特征模板是如何定义,且看下下一小节。
解码
中文分词对应的解码类为CWSTagger,主要的field如下:
private Linear cl; // protected Pipe prePipe = null; // String2Sequence, 初步切分成char array形式 protected Pipe featurePipe; // Sequence2FeatureSequence, 计算特征数组 protected AlphabetFactory factory; protected TempletGroup templets; // lis of BaseTemplet, 特征模板 protected LabelAlphabet labels; // 对应于factory.maps中的LABELS,即S,M,E,B
解码同CRF、结构化感知器SP一样为Viterbi算法,具体实现见类
LinearViterbi,在此不再赘述。
特征
特征模板共定义了14个特征(对应于上面的训练模型),如下所示:0: %y[-1]%y[0] 1: %x[0,0]%y[0] 2: %x[0,1]%y[0] 3: %x[0,0]%x[0,1]%y[0] 4: %x[-1,0]%y[0] 5: %x[1,0]%y[0] 6: %x[-2,0]%y[0] 7: %x[2,0]%y[0] 8: %x[-2,0]%x[-1,0]%y[0] 9: %x[-1,0]%x[0,0]%y[0] 10: %x[0,0]%x[1,0]%y[0] 11: %x[1,0]%x[2,0]%y[0] 12: %x[-1,0]%x[0,0]%x[1,0]%y[0] 13: %x[-1,1]%x[0,0]%x[1,1]%y[0]
特征模板格式与CRF++相类似;从上可以看出,有1个类别转移特征(index 0),5个unigram字符状态特征(index 1, 4, 5, 6, 7),4个bigram字符状态特征(index 8, 9, 10, 11),1个trigram字符状态特征(index 12),3个字符状态与类型的混合特征(index 2, 3, 13)。其中,FNLP的enum
Chars.CharType定义了5种字符类型如下(与训练模型有稍许区别)。其实,字符类型特征对于分词来说比较鸡肋,可以不用。
D // 数字 L // 字母 C // 汉字 O // 其他,例如标点等 B_ // 空格 public enum CharType { C, L, D, P, // 标点 B}
我们来直观感受下FNLP的分词效果:
CWSTagger segger = new CWSTagger("models/seg.m"); segger.setEnFilter(true); String sentence = "小明硕士毕业于中国科学院计算所,后在日本京都大学深造"; List<String> words = segger.tag2List(sentence); // [小明, 硕士, 毕业于, 中国, 科学院, 计算, 所, ,, 后, 在, 日本, 京都, 大学, 深造]
可以看出,FNLP分词的粒度不均匀,准确性不是太高;应该是跟训练语料太少有关系,训练不充分而导致的。
3. 参考文献
[1] Qiu, Xipeng, Qi Zhang, and Xuanjing Huang. "FudanNLP: A Toolkit for Chinese Natural Language Processing." ACL (Conference System Demonstrations). 2013.[2] Crammer, Koby, et al. "Online passive-aggressive algorithms." Journal of Machine Learning Research 7.Mar (2006): 551-585.
[3] 邱锡鹏, “自然语言处理原理与实现”, 2014.
相关文章推荐
- 开源中文分词工具探析(三):Ansj
- 开源中文分词工具探析(七):LTP
- 开源中文分词工具探析(四):THULAC
- 开源中文分词工具探析(三):Ansj
- 开源中文分词工具探析(六):Stanford CoreNLP
- 中文分词工具探析(二):Jieba
- 中文开源汉语分词工具
- 中文分词工具探析(一):ICTCLAS (NLPIR)
- 4款开源的中文分词系统
- CRF中文分词开源版发布啦
- CRF中文分词开源版发布啦
- 14款中文分词开源软件
- 开源网站、中文分词等
- 常见中文分词开源项目
- 开源搜索引擎Solr环境配置、中文分词、数据库做为索引源及索引操作
- CRF中文分词开源版发布啦
- 开源中文分词FudanNLP
- PHP中文分词工具ICTCLAS的使用介绍
- 中文分词工具
- lucene是个全文检索工具 IKAnalyzer是个分词包 可以用来做中文的检索