中文分词
中文分词(Chinese Word Segmentation) 指的是将一个汉字序列切分成一个一个单独的词。分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。我们知道,在英文的行文中,单词之间是以空格作为自然分界符的,而中文只是字、句和段能通过明显的分界符来简单划界,唯独词没有一个形式上的分界符,虽然英文也同样存在短语的划分问题,不过在词这一层上,中文比之英文要复杂的多、困难的多。
中文名 中文分词
外文名 Chinese Word Segmentation
目录
1 基本信息
2 算法分类
3 技术难点
4 应用
5 常见项目
基本信息
背景
存在中文分词技术,是由于中文在基本文法上有其特殊性,具体表现在:
1.与英文为代表的拉丁语系语言相比,英文以空格作为天然的分隔符,而中文由于继承自古代汉语的传统,词语之间没有分隔。 古代汉语中除了连绵词和人名地名等,词通常就是单个汉字,所以当时没有分词书写的必要。而现代汉语中双字或多字词居多,一个字不再等同于一个词。
2.在中文里,“词”和“词组”边界模糊
现代汉语的基本表达单元虽然为“词”,且以双字或者多字词居多,但由于人们认识水平的不同,对词和短语的边界很难去区分。
例如:“对随地吐痰者给予处罚”,“随地吐痰者”本身是一个词还是一个短语,不同的人会有不同的标准,同样的“海上”“酒厂”等等,即使是同一个人也可能做出不同判断,如果汉语真的要分词书写,必然会出现混乱,难度很大。
中文分词的方法其实不局限于中文应用,也被应用到英文处理,如手写识别,单词之间的空格就不很清楚,中文分词方法可以帮助判别英文单词的边界。
作用
中文分词是文本挖掘的基础,对于输入的一段中文,成功的进行中文分词,可以达到电脑自动识别语句含义的效果。
中文分词技术属于自然语言处理技术范畴,对于一句话,人可以通过自己的知识来明白哪些是词,哪些不是词,但如何让计算机也能理解?其处理过程就是分词算法。
影响
中文分词对于搜索引擎来说,最重要的并不是找到所有结果,因为在上百亿的网页中找到所有结果没有太多的意义,没有人能看得完,最重要的是把最相关的结果排在最前面,这也称为相关度排序。中文分词的准确与否,常常直接影响到对搜索结果的相关度排序。从定性分析来说,搜索引擎的分词算法不同,词库的不同都会影响页面的返回结果[1] 。
算法分类
现有的分词算法可分为三大类:基于字符串匹配的分词方法、基于理解的分词方法和基于统计的分词方法。按照是否与词性标注过程相结合,又可以分为单纯分词方法和分词与标注相结合的一体化方法。
字符匹配
这种方法又叫做机械分词方法,它是按照一定的策略将待分析的汉字串与一个“充分大的”机器词典中的词条进行配,若在词典中找到某个字符串,则匹配成功(识别出一个词)。按照扫描方向的不同,串匹配分词方法可以分为正向匹配和逆向匹配;按照不同长度优先匹配的情况,可以分为最大(最长)匹配和最小(最短)匹配;常用的几种机械分词方法如下:
1)正向最大匹配法(由左到右的方向);
2)逆向最大匹配法(由右到左的方向);
3)最少切分(使每一句中切出的词数最小);
4)双向最大匹配法(进行由左到右、由右到左两次扫描)
还可以将上述各种方法相互组合,例如,可以将正向最大匹配方法和逆向最大匹配方法结合起来构成双向匹配法。由于汉语单字成词的特点,正向最小匹配和逆向最小匹配一般很少使用。一般说来,逆向匹配的切分精度略高于正向匹配,遇到的歧义现象也较少。统计结果表明,单纯使用正向最大匹配的错误率为1/169,单纯使用逆向最大匹配的错误率为1/245。但这种精度还远远不能满足实际的需要。实际使用的分词系统,都是把机械分词作为一种初分手段,还需通过利用各种其它的语言信息来进一步提高切分的准确率。
一种方法是改进扫描方式,称为特征扫描或标志切分,优先在待分析字符串中识别和切分出一些带有明显特征的词,以这些词作为断点,可将原字符串分为较小的串再来进机械分词,从而减少匹配的错误率。另一种方法是将分词和词类标注结合起来,利用丰富的词类信息对分词决策提供帮助,并且在标注过程中又反过来对分词结果进行检验、调整,从而极大地提高切分的准确率。
对于机械分词方法,可以建立一个一般的模型,在这方面有专业的学术论文,这里不做详细论述。
理解法
这种分词方法是通过让计算机模拟人对句子的理解,达到识别词的效果。其基本思想就是在分词的同时进行句法、语义分析,利用句法信息和语义信息来处理歧义现象。它通常包括三个部分:分词子系统、句法语义子系统、总控部分。在总控部分的协调下,分词子系统可以获得有关词、句子等的句法和语义信息来对分词歧义进行判断,即它模拟了人对句子的理解过程。这种分词方法需要使用大量的语言知识和信息。由于汉语语言知识的笼统、复杂性,难以将各种语言信息组织成机器可直接读取的形式,因此目前基于理解的分词系统还处在试验阶段。
统计法
从形式上看,词是稳定的字的组合,因此在上下文中,相邻的字同时出现的次数越多,就越有可能构成一个词。因此字与字相邻共现的频率或概率能够较好的反映成词的可信度。可以对语料中相邻共现的各个字的组合的频度进行统计,计算它们的互现信息。定义两个字的互现信息,计算两个汉字X、Y的相邻共现概率。互现信息体现了汉字之间结合关系的紧密程度。当紧密程度高于某一个阈值时,便可认为此字组可能构成了一个词。这种方法只需对语料中的字组频度进行统计,不需要切分词典,因而又叫做无词典分词法或统计取词方法。但这种方法也有一定的局限性,会经常抽出一些共现频度高、但并不是词的常用字组,例如“这一”、“之一”、“有的”、“我的”、“许多的”等,并且对常用词的识别精度差,时空开销大。实际应用的统计分词系统都要使用一部基本的分词词典(常用词词典)进行串匹配分词,同时使用统计方法识别一些新的词,即将串频统计和串匹配结合起来,既发挥匹配分词切分速度快、效率高的特点,又利用了无词典分词结合上下文识别生词、自动消除歧义的优点。
另外一类是基于统计机器学习的方法。首先给出大量已经分词的文本,利用统计机器学习模型学习词语切分的规律(称为训练),从而实现对未知文本的切分。我们知道,汉语中各个字单独作词语的能力是不同的,此外有的字常常作为前缀出现,有的字却常常作为后缀(“者”“性”),结合两个字相临时是否成词的信息,这样就得到了许多与分词有关的知识。这种方法就是充分利用汉语组词的规律来分词。这种方法的最大缺点是需要有大量预先分好词的语料作支撑,而且训练过程中时空开销极大。
到底哪种分词算法的准确度更高,目前并无定论。对于任何一个成熟的分词系统来说,不可能单独依靠某一种算法来实现,都需要综合不同的算法。例如,海量科技的分词算法就采用“复方分词法”,所谓复方,就是像中西医结合般综合运用机械方法和知识方法。对于成熟的中文分词系统,需要多种算法综合处理问题。
技术难点
有了成熟的分词算法,是否就能容易的解决中文分词的问题呢?事实远非如此。中文是一种十分复杂的语言,让计算机理解中文语言更是困难。在中文分词过程中,有两大难题一直没有完全突破。
歧义识别
歧义是指同样的一句话,可能有两种或者更多的切分方法。主要的歧义有两种:交集型歧义和组合型歧义,例如:表面的,因为“表面”和“面的”都是词,那么这个短语就可以分成“表面 的”和“表 面的”。这种称为交集型歧义(交叉歧义)。像这种交集型歧义十分常见,前面举的“和服”的例子,其实就是因为交集型歧义引起的错误。“化妆和服装”可以分成“化妆 和 服装”或者“化妆 和服 装”。由于没有人的知识去理解,计算机很难知道到底哪个方案正确。
交集型歧义相对组合型歧义来说是还算比较容易处理,组合型歧义就必须根据整个句子来判断了。例如,在句子“这个门把手坏了”中,“把手”是个词,但在句子“请把手拿开”中,“把手”就不是一个词;在句子“将军任命了一名中将”中,“中将”是个词,但在句子“产量三年中将增长两倍”中,“中将”就不再是词。这些词计算机又如何去识别?
如果交集型歧义和组合型歧义计算机都能解决的话,在歧义中还有一个难题,是真歧义。真歧义意思是给出一句话,由人去判断也不知道哪个应该是词,哪个应该不是词。例如:“乒乓球拍卖完了”,可以切分成“乒乓 球拍 卖 完 了”、也可切分成“乒乓球 拍卖 完 了”,如果没有上下文其他的句子,恐怕谁也不知道“拍卖”在这里算不算一个词。
新词识别
命名实体(人名、地名)、新词,专业术语称为未登录词。也就是那些在分词词典中没有收录,但又确实能称为词的那些词。最典型的是人名,人可以很容易理解。句子“王军虎去广州了”中,“王军虎”是个词,因为是一个人的名字,但要是让计算机去识别就困难了。如果把“王军虎”做为一个词收录到字典中去,全世界有那么多名字,而且每时每刻都有新增的人名,收录这些人名本身就是一项既不划算又巨大的工程。即使这项工作可以完成,还是会存在问题,例如:在句子“王军虎头虎脑的”中,“王军虎”还能不能算词?
除了人名以外,还有机构名、地名、产品名、商标名、简称、省略语等都是很难处理的问题,而且这些又正好是人们经常使用的词,因此对于搜索引擎来说,分词系统中的新词识别十分重要。新词识别准确率已经成为评价一个分词系统好坏的重要标志之一。
应用
在自然语言处理技术中,中文处理技术比西文处理技术要落后很大一段距离,许多西文的处理方法中文不能直接采用,就是因为中文必需有分词这道工序。中文分词是其他中文信息处理的基础,搜索引擎只是中文分词的一个应用。其他的比如机器翻译(MT)、语音合成、自动分类、自动摘要、自动校对等等,都需要用到分词。因为中文需要分词,可能会影响一些研究,但同时也为一些企业带来机会,因为国外的计算机处理技术要想进入中国市场,首先也是要解决中文分词问题。
分词准确性对搜索引擎来说十分重要,但如果分词速度太慢,即使准确性再高,对于搜索引擎来说也是不可用的,因为搜索引擎需要处理数以亿计的网页,如果分词耗用的时间过长,会严重影响搜索引擎内容更新的速度。因此对于搜索引擎来说,分词的准确性和速度,二者都需要达到很高的要求。研究中文分词的大多是科研院校,清华、北大、哈工大、中科院、北京语言学院、山西大学、东北大学、IBM研究院、微软中国研究院等都有自己的研究队伍,而真正专业研究中文分词的商业公司除了海量科技以外,几乎没有了。科研院校研究的技术,大部分不能很快产品化,而一个专业公司的力量毕竟有限,看来中文分词技术要想更好的服务于更多的产品,还有很长一段路。
常见项目
word分词
word分词是一个Java实现的分布式的中文分词组件,提供了多种基于词典的分词算法,并利用ngram模型来消除歧义。能准确识别英文、数字,以及日期、时间等数量词,能识别人名、地名、组织机构名等未登录词。能通过自定义配置文件来改变组件行为,能自定义用户词库、自动检测词库变化、支持大规模分布式环境,能灵活指定多种分词算法,能使用refine功能灵活控制分词结果,还能使用词性标注、同义标注、反义标注、拼音标注等功能。同时还无缝和Lucene、Solr、ElasticSearch、Luke集成。
智呈分词
功能描述:
1.新词自动识别
对词典中不存在的词,可以自动识别,对词典的依赖较小;
2.词性输出
分词结果中带有丰富的词性;
3.动态词性输出
分词结果中的词性并非固定,会根据不同的语境,赋予不同的词性;
4.特殊词识别
比如化学、药品等行业词汇,地名、品牌、媒体名等;
5.智能歧义解决
根据内部规则,智能解决常见分词歧义问题;
6.多种编码识别
自动识别各种单一编码,并支持混合编码;
7.数词量词优化
自动识别数量词;
性能介绍:
处理器:AMD Athlon II x2 250 3GHZ
单线程大于833KB/s,多线程安全。
MFSOU中文分词PHP扩展
一个PHP函数实现中文分词。使分词更容易,使用如下图:
SCWS调用示例
SCWS调用示例
SCWS
Hightman开发的一套基于词频词典的机械中文分词引擎,它能将一整段的汉字基本正确的切分成词。采用的是采集的词频词典,并辅以一定的专有名称,人名,地名,数字年代等规则识别来达到基本分词,经小范围测试大概准确率在 90% ~ 95% 之间,已能基本满足一些小型搜索引擎、关键字提取等场合运用。45Kb左右的文本切词时间是0.026秒,大概是1.5MB文本/秒,支持PHP4和PHP 5。
FudanNLP
FudanNLP主要是为中文自然语言处理而开发的工具包,也包含为实现这些任务的机器学习算法和数据集。本工具包及其包含数据集使用LGPL3.0许可证。开发语言为Java。功能包括中文分词等,不需要字典支持。
ICTCLAS
这是最早的中文开源分词项目之一,ICTCLAS在国内973专家组组织的评测中活动获得了第一名,在第一届国际中文处理研究机构SigHan组织的评测中都获得了多项第一名。ICTCLAS3.0分词速度单机996KB/s,分词精度98.45%,API不超过200KB,各种词典数据压缩后不到3M.ICTCLAS全部采用C/C++编写,支持Linux、FreeBSD及Windows系列操作系统,支持C/C++、C#、Delphi、Java等主流的开发语言。
HTTPCWS
HTTPCWS 是一款基于HTTP协议的开源中文分词系统,目前仅支持Linux系统。HTTPCWS 使用“ICTCLAS 3.0 2009共享版中文分词算法”的API进行分词处理,得出分词结果。HTTPCWS 将取代之前的 PHPCWS 中文分词扩展。
CC-CEDICT
一个中文词典开源项目,提供一份以汉语拼音为中文辅助的汉英辞典,截至2009年2月8日,已收录82712个单词。其词典可以用于中文分词使用,而且不存在版权问题。Chrome中文版就是使用的这个词典进行中文分词的。
IK
IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始,IKAnalyzer已经推出了3个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。新版本的IKAnalyzer3.0则发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。
Paoding
Paoding(庖丁解牛分词)基于Java的开源中文分词组件,提供lucene和solr 接口,具有极 高效率和 高扩展性。引入隐喻,采用完全的面向对象设计,构思先进。
高效率:在PIII 1G内存个人机器上,1秒可准确分词 100万汉字。
采用基于 不限制个数的词典文件对文章进行有效切分,使能够将对词汇分类定义。
能够对未知的词汇进行合理解析。
仅支持Java语言。
MMSEG4J
MMSEG4J基于Java的开源中文分词组件,提供lucene和solr 接口:
1.mmseg4j 用 Chih-Hao Tsai 的 MMSeg 算法实现的中文分词器,并实现 lucene 的 analyzer 和 solr 的TokenizerFactory 以方便在Lucene和Solr中使用。
2.MMSeg 算法有两种分词方法:Simple和Complex,都是基于正向最大匹配。Complex 加了四个规则过虑。官方说:词语的正确识别率达到了 98.41%。mmseg4j 已经实现了这两种分词算法。
盘古分词
盘古分词是一个基于.net 平台的开源中文分词组件,提供lucene(.net 版本) 和HubbleDotNet的接口
高效:Core Duo 1.8 GHz 下单线程 分词速度为 390K 字符每秒
准确:盘古分词采用字典和统计结合的分词算法,分词准确率较高。
功能:盘古分词提供中文人名识别,简繁混合分词,多元分词,英文词根化,强制一元分词,词频优先分词,停用词过滤,英文专名提取等一系列功能。
Jcseg
jcseg是使用Java开发的一个中文分词器,使用流行的mmseg算法实现。[4]
1。mmseg四种过滤算法,分词准确率达到了98.4%以上。
2。支持自定义词库。在lexicon文件夹下,可以随便添加/删除/更改词库和词库内容,并且对词库进行了分类,词库整合了《现代汉语词典》和cc-cedict辞典。
3。词条拼音和同义词支持,jcseg为所有词条标注了拼音,并且词条可以添加同义词集合,jcseg会自动将拼音和同义词加入到分词结果中。
4。中文数字和分数识别,例如:"四五十个人都来了,三十分之一。"中的"四五十"和"三十分之一",并且jcseg会自动将其转换为对应的阿拉伯数字。
5。支持中英混合词的识别。例如:B超,x射线。
6。支持基本单字单位的识别,例如2012年。
7。良好的英文支持,自动识别电子邮件,网址,分数,小数,百分数……。
8。智能圆角半角转换处理。
9。特殊字母识别:例如:Ⅰ,Ⅱ
10。特殊数字识别:例如:①,⑩
11。配对标点内容提取:例如:最好的Java书《java编程思想》,‘畅想杯黑客技术大赛’,被《,‘,“,『标点标记的内容。
12。智能中文人名识别。中文人名识别正确率达94%以上。
jcseg佩带了jcseg.properties配置文档,使用文本编辑器就可以自主的编辑其选项,配置适合不同应用场合的分词应用。例如:最大匹配分词数,是否开启中文人名识别,是否载入词条拼音,是否载入词条同义词……。
friso
friso是使用c语言开发的一个中文分词器,使用流行的mmseg算法实现。完全基于模块化设计和实现,可以很方便的植入到其他程序中,例如:MySQL,PHP等。并且提供了一个php中文分词扩展robbe。
1。只支持UTF-8编码。【源码无需修改就能在各种平台下编译使用,加载完20万的词条,内存占用稳定为14M。】。
2。mmseg四种过滤算法,分词准确率达到了98.41%。
3。支持自定义词库。在dict文件夹下,可以随便添加/删除/更改词库和词库词条,并且对词库进行了分类。
4。词库使用了friso的Java版本jcseg的简化词库。
5。支持中英混合词的识别。例如:c语言,IC卡。
7。很好的英文支持,电子邮件,网址,小数,分数,百分数。
8。支持阿拉伯数字基本单字单位的识别,例如2012年,5吨,120斤。
9。自动英文圆角/半角,大写/小写转换。
并且具有很高的分词速度:简单模式:3.7M/秒,复杂模式:1.8M/秒。
========
中文分词原理
一、为什么要进行中文分词?
词是最小的能够独立活动的有意义的语言成分,英文单词之间是以空格作为自然分界符的,而汉语是以字为基本的书写单位,词语之间没有明显的区分标记,因此,中文词语分析是中文信息处理的基础与关键。
Lucene中对中文的处理是基于自动切分的单字切分,或者二元切分。除此之外,还有最大切分(包括向前、向后、以及前后相结合)、最少切分、全切分等等。
二、中文分词技术的分类
我们讨论的分词算法可分为三大类:基于字典、词库匹配的分词方法;基于词频度统计的分词方法和基于知识理解的分词方法。
第一类方法应用词典匹配、汉语词法或其它汉语语言知识进行分词,如:最大匹配法、最小分词方法等。这类方法简单、分词效率较高,但汉语语言现象复杂丰富,词典的完备性、规则的一致性等问题使其难以适应开放的大规模文本的分词处理。第二类基于统计的分词方法则基于字和词的统计信息,如把相邻字间的信息、词频及相应的共现信息等应用于分词,由于这些信息是通过调查真实语料而取得的,因而基于统计的分词方法具有较好的实用性。
下面简要介绍几种常用方法:
1).逐词遍历法。
逐词遍历法将词典中的所有词按由长到短的顺序在文章中逐字搜索,直至文章结束。也就是说,不管文章有多短,词典有多大,都要将词典遍历一遍。这种方法效率比较低,大一点的系统一般都不使用。
2).基于字典、词库匹配的分词方法(机械分词法)
这种方法按照一定策略将待分析的汉字串与一个“充分大的”机器词典中的词条进行匹配,若在词典中找到某个字符串,则匹配成功。识别出一个词,根据扫描方向的不同分为正向匹配和逆向匹配。根据不同长度优先匹配的情况,分为最大(最长)匹配和最小(最短)匹配。根据与词性标注过程是否相结合,又可以分为单纯分词方法和分词与标注相结合的一体化方法。常用的方法如下:
(一)最大正向匹配法 (MaximumMatchingMethod)通常简称为MM法。其基本思想为:假定分词词典中的最长词有i个汉字字符,则用被处理文档的当前字串中的前i个字作为匹配字段,查找字典。若字典中存在这样的一个i字词,则匹配成功,匹配字段被作为一个词切分出来。如果词典中找不到这样的一个i字词,则匹配失败,将匹配字段中的最后一个字去掉,对剩下的字串重新进行匹配处理…… 如此进行下去,直到匹配成功,即切分出一个词或剩余字串的长度为零为止。这样就完成了一轮匹配,然后取下一个i字字串进行匹配处理,直到文档被扫描完为止。
其算法描述如下:
(1)初始化当前位置计数器,置为0;
(2)从当前计数器开始,取前2i个字符作为匹配字段,直到文档结束;
(3)如果匹配字段长度不为0,则查找词典中与之等长的作匹配处理。
如果匹配成功,
则,
a)把这个匹配字段作为一个词切分出来,放入分词统计表中;
b)把当前位置计数器的值加上匹配字段的长度;
c)跳转到步骤2);
否则
a) 如果匹配字段的最后一个字符为汉字字符,
则
①把匹配字段的最后一个字去掉;
②匹配字段长度减2;
否则
①把匹配字段的最后一个字节去掉;
②匹配字段长度减1;
b)跳转至步骤3);
否则
a)如果匹配字段的最后一个字符为汉字字符,
则 当前位置计数器的值加2;
否则当前位置计数器的值加1;
b)跳转到步骤2)。
(二)逆向最大匹配法 (ReverseMaximumMatcingMethod)通常简称为RMM法。RMM法的基本原理与MM法相同 ,不同的是分词切分的方向与MM法相反,而且使用的分词辞典也不同。逆向最大匹配法从被处理文档的末端开始匹配扫描,每次取最末端的2i个字符(i字字串)作为匹配字段,若匹配失败,则去掉匹配字段最前面的一个字,继续匹配。相应地,它使用的分词词典是逆序词典,其中的每个词条都将按逆序方式存放。在实际处理时,先将文档进行倒排处理,生成逆序文档。然后,根据逆序词典,对逆序文档用正向最大匹配法处理即可。
由于汉语中偏正结构较多,若从后向前匹配,可以适当提高精确度。所以,逆向最大匹配法比正向最大匹配法的误差要小。统计结果表明 ,单纯使用正向最大匹配的错误率为 1/16 9,单纯使用逆向最大匹配的错误率为 1/245。例如切分字段“硕士研究生产”,正向最大匹配法的结果会是“硕士研究生 / 产”,而逆向最大匹配法利用逆向扫描,可得到正确的分词结果“硕士 / 研究 / 生产”。
当然,最大匹配算法是一种基于分词词典的机械分词法,不能根据文档上下文的语义特征来切分词语,对词典的依赖性较大,所以在实际使用时,难免会造成一些分词错误,为了提高系统分词的准确度,可以采用正向最大匹配法和逆向最大匹配法相结合的分词方案(即双向匹配法,见(四)。)
(三)最少切分法:使每一句中切出的词数最小。
(四)双向匹配法:将正向最大匹配法与逆向最大匹配法组合。先根据标点对文档进行粗切分,把文档分解成若干个句子,然后再对这些句子用正向最大匹配法和逆向最大匹配法进行扫描切分。如果两种分词方法得到的匹配结果相同,则认为分词正确,否则,按最小集处理。
3). 全切分和基于词的频度统计的分词方法
基于词的频度统计的分词方法是一种全切分方法。在讨论这个方法之前我们先要明白有关全切分的相关内容。
全切分
全切分要求获得输入序列的所有可接受的切分形式,而部分切分只取得一种或几种可接受的切分形式,由于部分切分忽略了可能的其他切分形式,所以建立在部分切分基础上的分词方法不管采取何种歧义纠正策略,都可能会遗漏正确的切分,造成分词错误或失败。而建立在全切分基础上的分词方法,由于全切分取得了所有可能的切分形式,因而从根本上避免了可能切分形式的遗漏,克服了部分切分方法的缺陷。
全切分算法能取得所有可能的切分形式,它的句子覆盖率和分词覆盖率均为100%,但全切分分词并没有在文本处理中广泛地采用,原因有以下几点:
1)全切分算法只是能获得正确分词的前提,因为全切分不具有歧义检测功能,最终分词结果的正确性和完全性依赖于独立的歧义处理方法,如果评测有误,也会造成错误的结果。
2)全切分的切分结果个数随句子长度的增长呈指数增长,一方面将导致庞大的无用数据充斥于存储数据库;另一方面当句长达到一定长度后,由于切分形式过多,造成分词效率严重下降。
基于词的频度统计的分词方法:
这是一种全切分方法。它不依靠词典,而是将文章中任意两个字同时出现的频率进行统计,次数越高的就可能是一个词。它首先切分出与词表匹配的所有可能的词,运用统计语言模型和决策算法决定最优的切分结果。它的优点在于可以发现所有的切分歧义并且容易将新词提取出来。
4).基于知识理解的分词方法。
该方法主要基于句法、语法分析,并结合语义分析,通过对上下文内容所提供信息的分析对词进行定界,它通常包括三个部分:分词子系统、句法语义子系统、总控部分。在总控部分的协调下,分词子系统可以获得有关词、句子等的句法和语义信息来对分词歧义进行判断。这类方法试图让机器具有人类的理解能力,需要使用大量的语言知识和信息。由于汉语语言知识的笼统、复杂性,难以将各种语言信息组织成机器可直接读取的形式。因此目前基于知识的分词系统还处在试验阶段。
5).一种新的分词方法
并行分词方法:这种分词方法借助于一个含有分词词库的管道进行 ,比较匹配过程是分步进行的 ,每一步可以对进入管道中的词同时与词库中相应的词进行比较 ,由于同时有多个词进行比较匹配 ,因而分词速度可以大幅度提高。这种方法涉及到多级内码理论和管道的词典数据结构。(详细算法可以参考吴胜远的《并行分词方法的研究》。)
常用中文分词包
1. 庖丁解牛分词包,适用于与Lucene整合。http://www.oschina.net/p/paoding
庖丁中文分词库是一个使用Java开发的,可结合到Lucene应用中的,为互联网、企业内部网使用的中文搜索引擎分词组件。
Paoding填补了国内中文分词方面开源组件的空白,致力于此并希翼成为互联网网站首选的中文分词开源组件。 Paoding中文分词追求分词的高效率和用户良好体验。
Paoding's Knives 中文分词具有极 高效率 和 高扩展性 。引入隐喻,采用完全的面向对象设计,构思先进。
高效率:在PIII 1G内存个人机器上,1秒 可准确分词 100万 汉字。
采用基于 不限制个数的词典文件对文章进行有效切分,使能够将对词汇分类定义。
能够对未知的词汇进行合理解析
2. LingPipe,开源自然语言处理的Java开源工具包。http:/alias-i.com/lingpipe/
功能非常强大,最重要的是文档超级详细,每个模型甚至连参考论文都列出来了,不仅使用方便,也非常适合模型的学习。
主题分类(Top Classification)、命名实体识别(Named Entity Recognition)、词性标注(Part-of Speech Tagging)、句题检测(Sentence Detection)、查询拼写检查(Query Spell Checking)、兴趣短语检测(Interseting Phrase Detection)、聚类(Clustering)、字符语言建模(Character Language Modeling)、医学文献下载/解析/索引(MEDLINE Download, Parsing and Indexing)、数据库文本挖掘(Database Text Mining)、中文分词(Chinese Word Segmentation)、情感分析(Sentiment Analysis)、语言辨别(Language Identification)等
3. JE分词包
4. LibMMSeg http://www.oschina.net/p/libmmseg
采用C++开发,同时支持Linux平台和Windows平台,切分速度大约在300K/s(PM-1.2G),截至当前版本(0.7.1)。
LibMMSeg没有为速度仔细优化过,进一步的提升切分速度应仍有空间。
5. IKAnalyzer http://www.oschina.net/p/ikanalyzer
IKAnalyzer基于lucene2.0版本API开发,实现了以词典分词为基础的正反向全切分算法,是LuceneAnalyzer接口的实现。
该算法适合与互联网用户的搜索习惯和企业知识库检索,用户可以用句子中涵盖的中文词汇搜索,如用"人民"搜索含"人民币"的文章,这是大部分用户的搜索思维;
不适合用于知识挖掘和网络爬虫技术,全切分法容易造成知识歧义,因为在语义学上"人民"和"人民币"是完全搭不上关系的。
6. PHPCWS http://www.oschina.net/p/phpcws
PHPCWS 是一款开源的PHP中文分词扩展,目前仅支持Linux/Unix系统。
PHPCWS 先使用“ICTCLAS 3.0 共享版中文分词算法”的API进行初次分词处理,再使用自行编写的“逆向最大匹配算法”对分词和进行词语合并处理,并增加标点符号过滤功能,得出分词结果。
ICTCLAS(Institute of Computing Technology, Chinese Lexical Analysis System)是中国科学院计算技术研究所在多年研究工作积累的基础上,基于多层隐马模型研制出的汉语词法分析系统,主要功能包括中文分词;词性标注;命名实体识别;新词识别;同时支持用户词典。ICTCLAS经过五年精心打造,内核升级6次,目前已经升级到了ICTCLAS3.0,分词精度 98.45%,各种词典数据压缩后不到3M。ICTCLAS在国内973专家组组织的评测中活动获得了第一名,在第一届国际中文处理研究机构SigHan 组织的评测中都获得了多项第一名,是当前世界上最好的汉语词法分析器。
ICTCLAS 3.0 商业版是收费的,而免费提供的 ICTCLAS 3.0 共享版不开源,词库是根据人民日报一个月的语料得出的,很多词语不存在。所以本人对ICTCLAS分词后的结果,再采用逆向最大匹配算法,根据自己补充的一个9万条词语的自定义词库(与ICTCLAS词库中的词语不重复),对ICTCLAS分词结果进行合并处理,输出最终分词结果。
由于 ICTCLAS 3.0 共享版只支持GBK编码,因此,如果是UTF-8编码的字符串,可以先用PHP的iconv函数转换成GBK编码,再用phpcws_split函数进行分词处理,最后转换回UTF-8编码。
7、KTDictSeg 一个C#.net做的简单快速准确的开源中文分词组件(这个分词算法效果也不错)
http://www.cnblogs.com/eaglet/archive/2007/05/24/758833.html
代码下载:http://download.csdn.net/source/521857
========
中文分词和TF-IDF
中文分词(Chinese Word Segmentation)指的是将一个汉字序列切分成一个一个单独的词。中文分词是文本挖掘的基础,对于输入的一段中文,成功的进行中文分词,可以达到电脑自动识别语句含义的效果。
TF-IDF(term frequency–inverse document frequency)是一种用于信息搜索和信息挖掘的常用加权技术。在搜索、文献分类和其他相关领域有广泛的应用。
TF-IDF的主要思想是,如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。TF词频(Term Frequency)指的是某一个给定的词语在该文件中出现的次数。IDF反文档频率(Inverse Document Frequency)的主要思想是:如果包含词条的文档越少,IDF越大,则说明词条具有很好的类别区分能力。
使用TF*IDF可以计算某个关键字在某篇文章里面的重要性,因而识别这篇文章的主要含义,实现计算机读懂文章的功能。
常见中文分词开源项目:
SCWS:
Hightman开发的一套基于词频词典的机械中文分词引擎,它能将一整段的汉字基本正确的切分成词。采用的是采集的词频词典,并辅以一定的专有名称,人名,地名,数字年代等规则识别来达到基本分词,经小范围测试大概准确率在 90% ~ 95% 之间,已能基本满足一些小型搜索引擎、关键字提取等场合运用。45Kb左右的文本切词时间是0.026秒,大概是1.5MB文本/秒,支持PHP4和PHP 5。
ICTCLAS:
这可是最早的中文开源分词项目之一,ICTCLAS在国内973专家组组织的评测中活动获得了第一名,在第一届国际中文处理研究机构SigHan组织的评测中都获得了多项第一名。ICTCLAS3.0分词速度单机996KB/s,分词精度98.45%,API不超过200KB,各种词典数据压缩后不到3M.ICTCLAS全部采用C/C++编写,支持Linux、FreeBSD及Windows系列操作系统,支持C/C++、C#、Delphi、Java等主流的开发语言。
HTTPCWS:
HTTPCWS 是一款基于HTTP协议的开源中文分词系统,目前仅支持Linux系统。HTTPCWS 使用“ICTCLAS 3.0 2009共享版中文分词算法”的API进行分词处理,得出分词结果。HTTPCWS 将取代之前的 PHPCWS 中文分词扩展。
庖丁解牛分词:
Java 提供lucence 接口,仅支持Java语言。
CC-CEDICT:
一个中文词典开源项目,提供一份以汉语拼音为中文辅助的汉英辞典,截至2009年2月8日,已收录82712个单词。其词典可以用于中文分词使用,而且不存在版权问题。Chrome中文版就是使用的这个词典进行中文分词的。
基于VB/ASP的中文分词
上面的开源项目没有给予VB和ASP的,这里提供一个简单的VB/ASP类,加上词典之后就可以进行分词了,注意这个类只供演示,其分词速度极慢不适合实际应用。
类名为:WordSplit
Private rootTable As String
Private Function GetCount(ByVal s As String) As Long
GetCount = InStr(1, rootTable, s)
End Function
Public Function WordCount(ByVal strString As String, ByVal strGetWord As String) As Long
Dim k
k = Split(strString, strGetWord)
WordCount = UBound(k)
End Function
' 分析输入的字符串,将其切割成一个个的词语。
'
待切割的字符串
'
所切割得到的中文词语数组
Public Function ParseChinese(ByVal s As String, ByVal separator As String) As String
Dim lngLength As Long
Dim strTemp As String
Dim ArrayList As String
Dim i, j
ArrayList = ""
lngLength = Len(s)
i = 1
While i < lngLength
strTemp = Mid(s, i, 1)
If GetCount(strTemp) > 1 Then
j = 2
While i + j < lngLength + 1 And GetCount(Mid(s, i, j)) > 0
j = j + 1
Wend
strTemp = Mid(s, i, j - 1)
i = i + j - 2
End If
i = i + 1
'WordAdd (temp)
ArrayList = ArrayList + strTemp + separator
Wend
ParseChinese = ArrayList
End Function
Private Sub Class_Initialize()
Dim fso, templetfile, txtfile
templetfile = App.Path + "\ChineseDictionary.txt"
Set fso = CreateObject("Scripting.FileSystemObject")
Set txtfile = fso.OpenTextFile(templetfile, 1)
rootTable = txtfile.ReadAll
txtfile.Close
End Sub
调用示例:
strInput = "中文分词指的是将一个汉字序列切分成一个一个单独的词。中文分词是文本挖掘的基础,对于输入的一段中文,成功的进行中文分词,可以达到电脑自动识别语句含义的效果。"
Dim strWordSplit As New WordSplit
strSubject = strWordSplit.ParseChinese(strInput, "|")
arrSubject = Split(strSubject, "|")
========
开源 Java 中文分词器 Ansj
Ansj 是一个开源的 Java 中文分词工具,基于中科院的 ictclas 中文分词算法,比其他常用的开源分词工具(如mmseg4j)的分词准确率更高。
在线演示:http://ansj.sdapp.cn/demo/seg.jsp
官网地址:http://www.ansj.org/
Github地址:https://github.com/ansjsun/ansj_seg
Ansj中文分词是一款纯Java的、主要应用于自然语言处理的、高精度的中文分词工具,目标是“准确、高效、自由地进行中文分词”,可用于人名识别、地名识别、组织机构名识别、多级词性标注、关键词提取、指纹提取等领域,支持行业词典、用户自定义词典。
1. 中文歧义的识别
比较出名的一句话“结婚的和尚未结婚的”,如果使用正向最大匹配,容易分成“结婚/的/和尚/未/结婚的”,于是有的学者试图倒过来识别,逆向匹配会大于正向。但是碰到这句“结合成分子时”,采用逆向最大匹配,则会分为“结合/成分/子时”,更有甚者像“咬了猎人的狗”这种语意不明的词语,就更不容易正确分词了。这是中文分词的软肋。下面是些典型的歧义句:
交叉歧义(多种切分交织在一起):内塔内亚胡说的/确实/在理
组合歧义(不同情况下切分不同):这个人/手上有痣、我们公司人手
真歧义(几种切分都可以):乒乓球拍/卖/完了、乒乓球/拍卖/完了
2. 实体名识别
这个是中文分词遇到的最大的难点,也是最最紧迫的。实体名识别包括人名识别、地名识别、机构名识别,还包括有监督识别和无监督识别。有监督的还好,无监督基本是无解的,比如“王大力发球”是“王大力”还是“大力发球”,一般人都难以识别。
3. 新词热词发现
目前常用的新词发现还是一个比较有研究性的课题,虽然有些论文在准确率很高,但是大多是封闭测试,这意味着结果很难应用到实际工程中。目前Ansj采用的新词发现方式比较简单,采用了高频词的匹配方式,不使用规则,用统计重复串识别新词,根据词性去掉干扰词,虽然有一定的效果,但还是差强人意。
4. 颗粒度问题
这个就是一个规则探讨的问题了,比如“北京大学”是“北京”+“大学”还是“北京大学”,人各有志,就连同一个人不同时间的标注也有可能是有区别的,虽然这个问题严格上来说不属于技术问题,但是对分词结果的评测却有着很大的关系,Ansj采用“能识别就识别”的策略方针,所以在真正R值的时候偏低,总之一句话,适合学术的不一定适合工业,反之亦然。
简单介绍一下Ansj分词用到的算法,其分词原理是什么? Top
Ansj,可以说是一个ictclas的Java版本,基本原理一致,只不过在分词优化算法上做了一些改进。
该算法实现分词有以下几个步骤:
全切分,原子切分;
N最短路径的粗切分,根据隐马尔科夫模型和viterbi算法,达到最优路径的规划;
人名识别;
系统词典补充;
用户自定义词典的补充;
词性标注(可选)
Ansj分词的准确率大概是多少?
这是我采用人民日报1998年1月语料库的一个测试结果,首先要说明的是这份人工标注的语料库本身就有错误。
P(准确率):0.984887218571267
R(召回率):0.9626488103178712
F(综合指标F值):0.9736410471396494
在歧义、未登录词问题上,Ansj表现怎样?
歧异方面的处理方式自我感觉还可以,基于“最佳实践规则+统计”的方式,虽然还有一部分歧异无法识别,但是已经完全能满足工程应用了。
至于未登录词的识别,目前重点做了中文人名的识别,效果还算满意,识别方式用的“字体+前后监督”的方式,也算是目前我所知道的效果最好的一种识别方式了。
Ansj的性能如何?
在我的测试中,Ansj的效率已经远超ictclas的其他开源实现版本。
核心词典利用双数组规划,每秒钟能达到千万级别的粗分。在我的MacBookAir上面,分词速度大约在300w/字/秒,在酷睿i5+4G内存组装机器上,更是达到了400w+/字/秒的速度。
如何添加自定义词典?
Ansj已经实现了用户自定义词典的动态添加删除,当然,也支持从文件加载词典。
从硬盘加载用户自定义词典的方法:
用户自定义词典默认路径:项目目录/library/userLibrary/userLibrary.dic
格式为:[自定义词] [词性] [词频],如:csdn创新院 userDefine 1000,中间用TAB键隔开
原分词结果:[csdn, 创新, 院, 是, 一个, 好, 公司]
增加词典后:[csdn创新院, 是, 一个, 好, 公司]
详细内容见:用户自定义词典的添加
用户自定义词典的动态添加删除方法见:用户自定义词典的动态添加删除Demo
你
========
java中文分词
最近由于工作原因,接触到了JAVA的中文分词, 现在来讲讲具体操作.
java的分词器都是基于 lucene 核心的.
我选择的是
ikanalyzer2.0.2的最新版本
具体调用过程如下:
[java]
import java.io.Reader;
import java.io.StringReader;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.StopFilter;
import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.TokenFilter;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.cjk.CJKAnalyzer;
import org.apache.lucene.analysis.cn.ChineseAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.mira.lucene.analysis.MIK_CAnalyzer;
public class JeAnalyzer
{
//private static String testString1 = "/u4E2D/u56FD/u4EBA/u52A0/u6CB9";
private static String testString1 = "中国人加油";
public static void testStandard(String testString)
{
try
{
Analyzer analyzer = new StandardAnalyzer();
Reader r = new StringReader(testString);
StopFilter sf = (StopFilter) analyzer.tokenStream("", r);
System.err.println("=====standard analyzer====");
Token t;
while ((t = sf.next()) != null)
{
System.out.println(t.termText());
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
public static void testCJK(String testString)
{
try
{
Analyzer analyzer = new CJKAnalyzer();
Reader r = new StringReader(testString);
StopFilter sf = (StopFilter) analyzer.tokenStream("", r);
System.err.println("=====cjk analyzer====");
Token t;
while ((t = sf.next()) != null)
{
System.out.println(t.termText());
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
public static void testChiniese(String testString)
{
try
{
Analyzer analyzer = new ChineseAnalyzer();
Reader r = new StringReader(testString);
TokenFilter tf = (TokenFilter) analyzer.tokenStream("", r);
System.err.println("=====chinese analyzer====");
Token t;
while ((t = tf.next()) != null)
{
System.out.println(t.termText());
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
public static String transJe(String testString,String c1,String c2)
{
String result = "";
try
{
Analyzer analyzer = new MIK_CAnalyzer();
Reader r = new StringReader(testString);
TokenStream ts = (TokenStream)analyzer.tokenStream("", r);
//System.out.println("=====je analyzer====");
Token t;
while ((t = ts.next()) != null)
{
result += t.termText()+",";
}
}
catch(Exception e)
{
e.printStackTrace();
}
return result;
}
public static void main(String[] args)
{
try
{
//String testString = testString1;
String testString = testString1;
System.out.println(testString);
//testStandard(testString);
//testCJK(testString);
//testPaoding(testString);
//testChiniese(testString);
//testString = new TestT().convert(testString);
//testString = "/u636E/u8DEF/u900F/u793E/u62A5/u9053/uff0C/u5370/u5EA6/u5C3C/u897F/u4E9A/u793E/u4f1A/u4E8B/u52A1/u90E8/u4E00/u5B98/u5458/u661F/u671F/u4E8C";
String sResult[] = transJe(testString,"gb2312","utf-8").split(",");
for(int i = 0 ; i< sResult.length ; i++)
{
System.out.println(sResult[i]);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
需要 的JAR如下:
lucene-analyzers-2.4.1.jar
lucene-core-2.4.1.jar
当然少不了
IKAnalyzer2.0.2OBF.jar
在UNIX下使用的话,注意对中文的编码问题.
========
使用IK Analyzer实现中文分词(JAVA)
IK Analyzer是基于lucene实现的分词开源框架;
下载路径:http://code.google.com/p/ik-analyzer/downloads/list
需要在项目中引入:IKAnalyzer.cfg.xml 、IKAnalyzer2012.jar 、lucene-core-3.6.0.jar 、stopword.dic
IK Analyzer 示例代码如下:
[java]
package com.haha.test;
import java.io.IOException;
import java.io.StringReader;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.wltea.analyzer.lucene.IKAnalyzer;
public class Test2 {
public static void main(String[] args) throws IOException {
String text="基于java语言开发的轻量级的中文分词工具包";
//创建分词对象
Analyzer anal=new IKAnalyzer(true);
StringReader reader=new StringReader(text);
//分词
TokenStream ts=anal.tokenStream("", reader);
CharTermAttribute term=ts.getAttribute(CharTermAttribute.class);
//遍历分词数据
while(ts.incrementToken()){
System.out.print(term.toString()+"|");
}
reader.close();
System.out.println();
}
}
lucene 示例代码如下:
[java]
package com.haha.test;
import java.io.IOException;
import java.io.StringReader;
import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;
public class Test3 {
public static void main(String[] args) throws IOException {
String text="基于java语言开发的轻量级的中文分词工具包";
StringReader sr=new StringReader(text);
IKSegmenter ik=new IKSegmenter(sr, true);
Lexeme lex=null;
while((lex=ik.next())!=null){
System.out.print(lex.getLexemeText()+"|");
}
}
}
========