`

基于结构化平均感知机的分词器Java实现

阅读更多

基于结构化平均感知机的分词器Java实现

作者:hankcs

最近高产似母猪,写了个基于AP的中文分词器,在Bakeoff-05的MSR语料上F值有96.11%。最重要的是,只训练了5个迭代;包含语料加载等IO操作在内,整个训练一共才花费23秒。应用裁剪算法去掉模型中80%的特征后,F值才下降不到0.1个百分点,体积控制在11兆。如果训练一百个迭代,F值可达到96.31%,训练时间两分多钟。

数据在一台普通的IBM兼容机上得到:



 

 

本模块已集成到HanLP 1.6以上版本开源,文档位于项目wiki中,欢迎使用!【hanlp1.7新版本已经发布,可以去新版本查到看使用

结构化预测

关于结构化预测和非结构化预测的区别一张讲义说明如下



 

 

更多知识请参考Neubig的讲义《The Structured Perceptron》。

 

本文实现的AP分词器预测是整个句子的BMES标注序列,当然属于结构化预测问题了。

感知机

二分类

感知机的基础形式如《统计学习方法》所述,是定义在一个超平面上的线性二分类模型。作为原著第二章,实在是简单得不能再简单了。然而实际运用中,越简单的模型往往生命力越顽强。

这里唯一需要补充的是,感知机是个在线学习模型,学习一个训练实例后,就可以更新整个模型。

多分类

怎么把二分类拓展到多分类呢?可以用多个分类器,对于BMES这4种分类,就是4个感知机了。每个感知机分别负责分辨“是不是B”“是不是M”“是不是E”“是不是S”这4个二分类问题。在实现中,当然不必傻乎乎地创建4个感知机啦。把它们的权值向量拼接在一起,就可以输出“是B的分数”“是M的分数”“是E的分数”“是S的分数”了。取其最大者,就可以初步实现多分类。但在分词中,还涉及到转移特征和HMM-viterbi搜索算法等,留到下文再说。

平均感知机

平均感知机指的是记录每个特征权值的累计值,最后平均得出最终模型的感知机。为什么要大费周章搞个平均算法出来呢?

前面提到过,感知机是个在线学习模型,学习一个训练实例后,就可以更新整个模型。假设有10000个实例,模型在前9999个实例的学习中都完美地得到正确答案,说明此时的模型接近完美了。可是最后一个实例是个噪音点,朴素感知机模型预测错误后直接修改了模型,导致前面9999个实例预测错误,模型训练前功尽弃。

有什么解决方案呢?一种方案是投票式的,即记录每个模型分类正确的次数,作为它的得票。训练结束时取得票最高的模型作为最终模型。但这种算法是不实际的,如果训练5个迭代,10000个实例,那么就需要储存50000个模型及其票数,太浪费了。

 

最好用的方法是平均感知机,将这50000个模型的权值向量累加起来,最后除以50000就行了,这样任何时候我们只额外记录了一个累加值,非常高效了。关于平均感知机的详情请参考《200行Python代码实现感知机词性标注器》。虽然那篇文章是讲解词性标注的,但相信作为万物灵长的读者一定拥有举一反三的泛化能力。

语言模型

HMM

我们不是在讲解感知机分词吗?怎么跟HMM扯上关系了?

其实任何基于序列标注的分词器都离不开隐马尔科夫链,即BMES这四个标签之间的Bigram(乃至更高阶的n-gram)转移概率。作为其中一员的AP分词器,也不例外地将前一个字符的标签作为了一个特征。该特征对预测当前的标签毫无疑问是有用的,比如前一个标签是B,当前标签就绝不可能是S。

这种类似于y[i-1]的特征在线性图模型中一般称为转移特征,而那些不涉及y[i-1]的特征通常称为状态特征。

viterbi

由于AP分词器用到了转移特征,所以肯定少不了维特比搜索。从序列全体的准确率考虑,搜索也是必不可少的。给定隐马尔可夫模型的3要素,我用Java写了一段“可运行的伪码”:



 

 

 

 

上述实现是个重视条理胜于效率的原型,古人云“过早优化是魔鬼”。相信聪明的读者一定能看懂这里面在干什么。

特征提取

定义字符序列为x,标注序列为y。

转移特征

转移特征就是上面说的y[i-1]。

状态特征

我一共使用了7种状态特征:

 



 

在邓知龙的《基于感知器算法的高效中文分词与词性标注系统设计与实现》中提到,要利用更复杂的字符n-gram、字符类别n-gram、叠字、词典等特征。但在我的实践中,除了上述7种特征外,我每减少一个特征,我的AP分词器的准确率就提高一点,也许是语料不同吧,也许是特征提取的实现不同。总之,主打精简、高效。

训练

迭代数目其实不需要太多,在3个迭代内模型基本就收敛了:

 



 

4个迭代似乎帮了倒忙,但万幸的是,我们使用的是平均感知机。权值平均之后,模型的性能反而有所提升。

此时模型大小:



 

模型裁剪

《基于感知器算法的高效中文分词与词性标注系统设计与实现》提到的模型裁剪策略是有效的,我将压缩率设为0.2,即压缩掉20%的特征,模型准确率没有变化:

 



 

由于我使用了随机shuffle算法,所以每次训练准确率都略有微小的上下波动。此时可以看到模型裁剪过程花了额外的1分钟,裁剪完毕后准确率维持96.11不变。

此时模型大小:

 



 

裁减掉50%如何呢?

 



 

此时模型大小:

 



 

可见裁剪了80%的特征,体积从54M下降到11M,模型的准确率才跌了不到0.1个百分点!这说明大部分特征都是没用的,特征裁剪非常有用、非常好用!

Reference

邓知龙 《基于感知器算法的高效中文分词与词性标注系统设计与实现》

 

  • 大小: 16.8 KB
  • 大小: 84.1 KB
  • 大小: 83.5 KB
  • 大小: 44.3 KB
  • 大小: 9.2 KB
  • 大小: 52.7 KB
  • 大小: 4 KB
  • 大小: 55.5 KB
  • 大小: 7.5 KB
  • 大小: 59.9 KB
  • 大小: 69.3 KB
分享到:
评论

相关推荐

    结构化感知器进行中文切词

    结构化感知器是基于感知器模型的一种扩展,传统的感知器主要用于二分类问题,而结构化感知器则可以处理多类别的序列标注问题。在中文切词中,每个词语被视为一个结构,整个句子则是一个由多个结构组成的序列。目标是...

    python写的基于感知机的中文分词系统

    基于字的用感知机实现的中文分词系统。完全训练后对微软的测试集精度可以达到96%多。我上传的版本是完整的代码(训练和分词),大家自己用附带的微软训练数据训练就可以了,只有一个文件。 代码总的来说写的还是很...

    使用IK Analyzer实现中文分词之Java实现

    IK Analyzer 是一个开源的,基于 java 语言开发的轻量级的中文分词工具包。从 2006年 12 月推出 1.0 版开始, IKAnalyzer 已经推出了 4 个大版本。最初,它是以开源项目Luence 为应用主体的,结合词典分词和文法分析...

    JAVA实现的中文分词程序

    Java实现的中文分词程序是一种基于Java编程语言的文本处理工具,主要应用于处理中文文本,将其拆分成有意义的词汇单元,这一过程被称为分词。在自然语言处理(NLP)领域,分词是预处理阶段的关键步骤,为后续的文本...

    使用IK Analyzer实现中文分词之Java实现(包含所有工具包)

    1、lucene-core-3.6.0.jar 2、IKAnalyzer2012.jar(主jar包) 3、IKAnalyzer.cfg.xml(分词器扩展配置文件) 4、stopword.dic(停止词典) 5、IkSegmentation.java(样例类)

    java实现英文文档分词

    "java实现英文文档分词" 本资源摘要信息主要关注java实现英文文档分词的知识点, 涵盖文档读取、分词、词频统计、结果输出等方面的内容。 一、 文档读取 在该实验中,使用java的BufferedReader类来读取文档,读取...

    基于 Java 的中文分词器分词效果评估对比项目

    基于 Java 的中文分词器分词效果评估对比项目。它主要实现了以下功能: 分词效果评估:用户可以通过程序对比不同分词器的分词结果,以及计算分词速度、行数完美率、行数错误率、字数完美率、字数错误率等指标。 ...

    中文分词java实现

    总结来说,中文分词Java实现涉及了对中文文本的预处理、调用分词库进行分词和词性标注,以及后处理阶段的数据分析。通过这些工具,我们可以有效地处理中文文本,为后续的NLP任务提供基础数据。对于Java开发者而言,...

    感知器分词软件--python实现

    感知器分词软件是自然语言处理(NLP)领域中的一种常见技术,它主要用于中文文本的分词。在这个Python实现中,我们主要关注的是如何利用词的上下文特征来进行精确的分词工作。 感知器(Perceptron)是一种简单的...

    基于感知机的分词算法简介

    我原来发过一个“python写的基于感知机的中文分词系统”的资源,那个是很完整的代码,包括训练数据等。但是代码没有任何注释,所以我又提交这个说明文档。但这个文档是用pageplayer做的(pageplayer压缩后有19M我发...

    java实现中文分词simhash算法

    总的来说,Java实现的中文分词SimHash算法结合了Sanford分词库的分词功能和SimHash的相似度检测,为中文文本的相似度分析提供了一种高效且准确的方法。在实际应用中,这种技术广泛应用于搜索引擎的去重、推荐系统、...

    jieba分词器 java版

    Java版的jieba分词器使得Java开发者也能轻松地在项目中集成这个强大的分词引擎。 1. **jieba分词器原理**: jieba分词基于最大匹配法(MaxMatch,MM)和HMM(Hidden Markov Model,隐马尔科夫模型)。在精确模式下...

    java版本结巴分词

    Java版本的结巴分词是基于Java实现的中文分词工具,它在处理中文文本时具有高效、灵活和易用的特点。结巴分词(Jieba)最初是由Python开发的,但为了满足Java开发者的需求,也有了Java版本。本文将深入探讨Java版...

    IKAnalyzer中文分词器 java

    IKAnalyzer是一个基于Java实现的全文检索分析器,主要目标是为Java开发人员提供一个简单、易用的中文分词组件。它的设计思想是灵活和可扩展,支持自定义词典和热更新,使得用户可以根据实际需求对分词结果进行调整...

    IK 分词器兼容Java

    **IK分词器兼容Java详解** IK分词器(Intelligent Chinese Analyzer for Java)是一款针对中文文本处理的开源分词工具,专为Java平台设计。它致力于提供高效、灵活的中文分词解决方案,广泛应用于搜索引擎、信息...

    jieba分词java版项目

    jieba分词是中文处理领域的一个著名...综上所述,jieba分词Java版项目提供了一种在Java环境下进行中文分词的解决方案,通过Eclipse导入并运行测试,你可以快速了解和使用这个工具,为你的中文信息处理任务带来便利。

    基于树的一个小型分词器实现

    标题中的“基于树的一个小型分词器实现”指的是在自然语言处理(NLP)领域,使用数据结构——树来设计和实现的一个简单的分词工具。分词是将连续的文本序列划分为有意义的词语单元,它是许多NLP任务的基础,如信息...

    java lucene 实现分词和词干抽取

    用java实现的,利用了lucene里面的standardAnalyzer分析器实现的分词,可以去停用词,再利用波特算法实现 词干提取 最后排序 和词频统计输出

    基于java的中文自动分词(自然语言处理)

    总的来说,这个基于Java的中文自动分词项目为开发者和研究者提供了一个实践和学习自然语言处理技术的平台,无论你是想了解分词算法的内部工作原理,还是需要一个现成的分词工具,都能从中受益。通过深入研究源码,...

    中文地址分词及匹配项目

    protobuf-java是Google的Protocol Buffers,用于序列化结构化数据,可能用在地址数据的存储和传输中。 综上所述,这个项目是围绕中文地址处理展开的,它采用了混合分词技术来处理复杂的中文地址,并利用Double ...

Global site tag (gtag.js) - Google Analytics