ansj 有没有blending集成算法nagao算法

新词发现初研究
据统计,近来中文每年大概出现800-1k个新词。60%的分词错误是由新词导致的
一、新词的概念
目前,在中文分词领域出现了新词(New Words)和未登录词(Unknown Words)两种概念。很多研究者并没有对未登录词和新词加以区别,认为它们是一样的[12][13]。通常,未登录词被定义为未在词典中出现的词[3][4][5]。(Chen,1997)通过对一个规模为300万词汇的语料统计,将未登录词分为五种类别,包括
(a) 缩略词(abbreviation),如“中油”、“日韩”;
(b) 专有名词(Proper names),主要包括人名、地名、机构名。如“张三”、“北京”、“微软”;
(c) 派生词(derived words),主要指含有后缀词素的词,如“电脑化”;
(d) 复合词(compounds),由动词或名词等组合而成,如“获允”、“搜寻法”、“电脑桌”;
(e) 数字类复合词(numeric type compounds),即组成成分中含有数字,包括时间、日期、电话号码、地址、数字等,如“2005年”、“三千”。
二、新词的识别方法
1.基与规则通过构词,前缀,后缀(词边界),词形,编写规则....化,....族大概准确率90%
2.基与统计方法.俩个/三个 相邻单字 的频率....大概准确录88%
3.基与搜索引擎这个准确度非常高.. 几乎95%了...bg str feodg se hetu,auto pop ...yaos chwlai ,shg word...beir, bsd ..
4.单字构词能力以及频率.词素级的判断...
5.基与sns。。类似于智能+人工这个也能是准确度非常高,近乎100% ...因为是人工反馈。。。
三、基于大规模语料的新词发现算法
对中文资料进行自然语言处理时,我们会遇到很多其他语言不会有的困难,例如分词——汉语的词与词之间没有空格,那计算机怎么才知道“已结婚的和尚未结婚的”究竟是“已/结婚/的/和/尚未/结婚/的”,还是“已/结婚/的/和尚/未/结婚/的”呢?这就是所谓的分词歧义难题。不过,现在很多语言模型都已能比较漂亮地解决这一问题了。但在中文分词领域里,还有一个比分词歧义更令人头疼的东西——未登录词。中文没有首字母大写,专名号也被取消了,这叫计算机如何辨认人名地名之类的东西?更惨的则是机构名、品牌名、专业名词、缩略语、网络新词等,它们的产生机制似乎完全无规律可寻。
最近十年来,中文分词领域都在集中攻克这一难关,自动发现新词成为关键的环节。挖掘新词的传统方法是,先对文本进行分词,然后猜测未能成功匹配的剩余片段就是新词。这似乎陷入了一个怪圈:分词的准确性本身就依赖于词库的完整性,如果词库中根本没有新词,我们又怎能信任分词结果呢?
此时,一种大胆的想法是,首先不依赖于任何已有的词库,仅仅根据词的共同特征,将一段大规模语料中可能成词的文本片段全部提取出来,不管它是新词还是旧词。然后,再把所有抽出来的词和已有词库进行比较,不就能找出新词了吗?有了抽词算法后,我们还能以词为单位做更多有趣的数据挖掘工作。
成词标准之一:内部凝固程度
要想从一段文本中抽出词来,我们的第一个问题就是,怎样的文本片段才算一个词?大家想到的第一个标准或许是,看这个文本片段出现的次数是否足够多。我们可以把所有出现频数超过某个阈值的片段提取出来,作为该语料中的词汇输出。不过,光是出现频数高还不够,一个经常出现的文本片段有可能不是一个词,而是多个词构成的词组。在某网的用户状态中,“的电影”出现了389次,“电影院”只出现了175次,然而我们却更倾向于把“电影院”当作一个词,因为直觉上看,“电影”和“院”凝固得更紧一些。为了证明“电影院”一词的内部凝固程度确实很高,我们可以计算一下,如果“电影”和“院”真的是各自独立地在文本中随机出现,它俩正好拼到一起的概率会有多小。在整个2400万字的数据中,“电影”一共出现了2774次,出现的概率约为0.000113。“院”字则出现了4797次,出现的概率约为0.0001969。如果两者之间真的毫无关系,它们恰好拼在了一起的概率就应该是0..0001969,约为2.223乘以10的–8次方。但事实上,“电影院”在语料中一共出现了175次,出现概率约为7.183乘以10的–6次方,是预测值的300多倍。类似地,统计可得“的”字的出现概率约为0.0166,因而“的”和“电影”随机组合到了一起的理论概率值为0.113,约为1.875乘以10的–6次方,这与“的电影”出现的真实概率很接近——真实概率约为1.6乘以10的–5次方,是预测值的8.5倍。计算结果表明,“电影院”可能是一个更有意义的搭配,而“的电影”则更像是“的”和“电影”这两个成分偶然拼到一起的。当然,作为一个无知识库的抽词程序,我们并不知道“电影院”是“电影”加“院”得来的,也并不知道“的电影”是“的”加上“电影”得来的。错误的切分方法会过高地估计该片段的凝合程度。如果我们把“电影院”看作是“电”加“影院”所得,由此得到的凝合程度会更高一些。因此,为了算出一个文本片段的凝合程度,我们需要枚举它的凝合方式——这个文本片段是由哪两部分组合而来的。令p(x)为文本片段x在整个语料中出现的概率,那么我们定义“电影院”的凝合程度就是p(电影院)与p(电)·p(影院)的比值和p(电影院)与p(电影)·p(院)的比值中的较小值,“的电影”的凝合程度则是p(的电影)分别除以p(的)·p(电影)和p(的电)·p(影)所得的商的较小值。可以想到,凝合程度最高的文本片段就是诸如“蝙蝠”、“蜘蛛”、“彷徨”、“忐忑”之类的词了,这些词里的每一个字几乎总是会和另一个字同时出现,从不在其他场合中使用。
成词标准之二:自由运用程度
光看文本片段内部的凝合程度还不够,我们还需要从整体来看它在外部的表现。考虑“被子”和“辈子”这两个片段。我们可以说“买被子”、“盖被子”、“进被子”、“好被子”、“这被子”等,在“被子”前面加各种字;但“辈子”的用法却非常固定,除了“一辈子”、“这辈子”、“上辈子”、“下辈子”,基本上“辈子”前面不能加别的字了。“辈子”这个文本片段左边可以出现的字太有限,以至于直觉上我们可能会认为,“辈子”并不单独成词,真正成词的其实是“一辈子”、“这辈子”之类的整体。可见,文本片段的自由运用程度也是判断它是否成词的重要标准。如果一个文本片段能够算作一个词的话,它应该能够灵活地出现在各种不同的环境中,具有非常丰富的左邻字集合和右邻字集合。
“信息熵”是一个非常神奇的概念,它能够反映一个事件的结果平均会给你带来多大的信息量。如果某个结果的发生概率为p,当你知道它确实发生了,你得到的信息量就被定义为-log(p)。p越小,你得到的信息量就越大。如果一颗骰子的六个面分别是1、1、1、2、2、3,那么你知道了投掷的结果是1时可能并不会那么吃惊,它给你带来的信息量是-log(1/2),约为0.693。知道投掷结果是2,给你带来的信息量则是-log(1/3)≈1.0986。知道投掷结果是3,给你带来的信息量则有-log(1/6)≈1.79。但你只有1/2的机会得到0.693的信息量,只有1/3的机会得到1.0986的信息量,只有1/6的机会得到1.79的信息量,因而平均情况下你会得到0.693/2+1..79/6≈1.0114的信息量。这个1.0114就是那颗骰子的信息熵。现在,假如某颗骰子有100个面,其中99个面都是1,只有一个面上写的2。知道骰子的抛掷结果是2会给你带来一个巨大无比的信息量,它等于-log(1/100),约为4.605;但你只有1%的概率获取到这么大的信息量,其他情况下你只能得到-log(99/100)≈0.01005的信息量。平均情况下,你只能获得0.056的信息量,这就是这颗骰子的信息熵。再考虑一个最极端的情况:如果一颗骰子的六个面都是1,投掷它不会给你带来任何信息,它的信息熵为-log(1)=0。什么时候信息熵会更大呢?换句话说,发生了怎样的事件之后,你最想问一下它的结果如何?直觉上看,当然就是那些结果最不确定的事件。没错,信息熵直观地反映了一个事件的结果有多么的随机。我们用信息熵来衡量一个文本片段的左邻字集合和右邻字集合有多随机。考虑这么一句话“吃葡萄不吐葡萄皮不吃葡萄倒吐葡萄皮”,“葡萄”一词出现了四次,其中左邻字分别为{吃,
吐, 吃, 吐},右邻字分别为{不, 皮, 倒, 皮}。根据公式,“葡萄”一词的左邻字的信息熵为-(1/2)·log(1/2)-(1/2)·log(1/2)≈0.693,它的右邻字的信息熵则为-(1/2)·log(1/2)-(1/4)·log(1/4)-(1/4)·log(1/4)≈1.04。可见,在这个句子中,“葡萄”一词的右邻字更加丰富一些。凝固程度和自由程度,两种判断标准缺一不可。若只看前者,程序会找出实际上是“半个词”的片段;若只看后者,程序则会找出诸如“了一”、“的电影”一类的“垃圾词组”。在人人网用户状态中,“被子”一词一共出现了956次,“辈子”一词一共出现了2330次,两者的右邻字集合的信息熵分别为3.844,数值上非常接近。但“被子”的左邻字用例非常丰富:用得最多的是“晒被子”,它一共出现了162次;其次是“的被子”,出现了85次;接下来分别是“条被子”、“在被子”、“床被子”,分别出现了69次、64次和52次;当然,还有“叠被子”、“盖被子”、“加被子”、“新被子”、“掀被子”、“收被子”、“薄被子”、“踢被子”、“抢被子”等100多种不同的用法构成的长尾。所有左邻字的信息熵为3.67453。但“辈子”的左邻字就很可怜了,2330个“辈子”中有1276个是“一辈子”,有596个“这辈子”,有235个“下辈子”,有149个“上辈子”,有32个“半辈子”,有10个“八辈子”,有7个“几辈子”,有6个“哪辈子”,以及“n辈子”、“两辈子”等13种更罕见的用法。所有左邻字的信息熵仅为1.25963。因而,“辈子”能否成词,明显就有争议了。“下子”则是更典型的例子,310个“下子”的用例中有294个出自“一下子”,5个出自“两下子”,5个出自“这下子”,其余的都是只出现过一次的罕见用法。事实上,“下子”的左邻字信息熵仅为0.294421,我们不应该把它看作一个能灵活运用的词。当然,一些文本片段的左邻字没啥问题,右邻字用例却非常贫乏,例如“交响”、“后遗”、“鹅卵”等,把它们看作单独的词似乎也不太合适。我们不妨就把一个文本片段的自由运用程度定义为它的左邻字信息熵和右邻字信息熵中的较小值。在实际运用中你会发现,文本片段的凝固程度和自由程度,两种判断标准缺一不可。只看凝固程度的话,程序会找出“巧克”、“俄罗”、“颜六色”、“柴可夫”等实际上是“半个词”的片段;只看自由程度的话,程序则会把“吃了一顿”、“看了一遍”、“睡了一晚”、“去了一趟”中的“了一”提取出来,因为它的左右邻字都太丰富了。
四、抽词算法的实现
我们把文本中出现过的所有长度不超过d的子串都当作潜在的词(即候选词,其中d为自己设定的候选词长度上限,我设定的值为5),再为出现频数、凝固程度和自由程度各设定一个阈值,然后只需要提取出所有满足阈值要求的候选词即可。为了提高效率,我们可以把语料全文视作一整个字符串,并对该字符串的所有后缀按字典序排序。这样的话,相同的候选词便都集中在了一起,从头到尾扫描一遍便能算出各个候选词的频数和右邻字信息熵。将整个语料逆序后重新排列现在所有的后缀,再扫描一遍后便能统计出每个候选词在原文中所有左邻字的信息熵。另外,有了频数信息后,凝固程度也都很好计算了。这样,我们便得到了一个无须任何知识库的抽词算法,输入一段充分长的文本,这个算法能以大致O(n
logn)的效率提取出可能的词来。实际上我们只需要在内存中储存这些后缀的前d+1个字,或者更好地,只储存它们在语料中的起始位置。对不同的语料进行抽词,并且按这些词的频数从高到低排序。你会发现,不同文本的用词特征是非常明显的。
《西游记》上册:
行者、师父、三藏、八戒、大圣、菩萨、悟空、怎么、和尚、唐僧……
《资本论》全文:
商品、形式、货币、我们、过程、自己、机器、社会、部分、表现……
《圣经》全文:
以色列、没有、自己、一切、面前、大卫、知道、什么、犹大、祭司……
《时间简史》全文:
黑洞、必须、非常、任何、膨胀、科学、预言、太阳、观察、定律……
当然,我也没有忘记对某网用户状态进行分析——某网用户状态中最常出现的10个词是:
什么、今天、怎么、现在、可以、知道、喜欢、终于、这样。
事实上,程序从某网的状态数据中一共抽出了大约1200个词,里面大多数词也确实都是标准的现代汉语词汇。
不过别忘了,我们的目标是新词抽取。将所有抽出来的词与已有词库作对比,于是得到了某网特有的词汇(同样按频数从高到低排序):
尼玛、伤不起、给力、有木有、挂科、坑爹、神马、淡定、老爸、卧槽、牛逼、肿么、苦逼、无语、微博、六级、高数、选课、悲催、基友、蛋疼、很久、人人网、情何以堪、童鞋、哇咔咔、脑残、吐槽、猥琐、奶茶、我勒个去、刷屏、妹纸、胃疼、飘过、考研、弱爆了、太准了、搞基、忽悠、羡慕嫉妒恨、手贱、柯南、狗血、秒杀、装逼、真特么、碎觉、奥特曼、内牛满面、斗地主、腾讯、灰常、偶遇、拉拉、九把刀、高富帅、阿内尔卡、魔兽世界、线代、三国杀、林俊杰、速速、臭美、花痴……我还想到了更有意思的玩法。为什么不拿每天状态里的词去和前一天作对比,从而提取出这一天里特有的词呢?这样一来,我们就能从用户状态中提取出每日热点了!事实上,有了抽词算法之后,我们就能够以词语为单位,在各个维度上挖掘人们在社交网络中的用词动向:今年网络上最流行的新词是什么?男生和女生都喜欢说些什么?不同地方、不同年龄段的人都爱用什么样的词?这些问题曾经需要靠大规模语言统计调查才能得到一个满意的回答,而现在,借助互联网海量的用户生成内容,我们可以轻而易举地得到答案,为社会语言学的研究提供真实可靠材料。
五、N-Gram发现新词
1 N-Gram算法
N-Gram算法具有语种无关、不需要语言学处理、对拼写错误的容错能力强、不需要词典和规则等优点。基于新词识别领域的研究现状,本文采用N-Gram作为基本算法。
N-Gram算法的基本思想是:
(1)将文本内容按字节流进行大小为N的滑动窗口操作,形成长度为N的字符串,每个字符串称为
(2)对全部gram的出现频度进行统计,并按照事先设定的阈值进行过滤,抛弃垃圾字符串,得到新词。
基于N-Gram算法的新词识别方法根据是否分词分为基于字符和基于词两类。贺敏等[]在基于字和基于字符的新词识别试验中证明基于词的N-Gram识别效率更高。张海军等[]证明基于字符的N-Gram识别能够得到较高的召回率,而基于分词的字符串识别能够得到较高的准确率。随着样本数据容量的增大,两者的差别先是增大继而减少,当样本容量极为巨大时,差距很小,但是这种量几乎不可能达到。
因此本文采用了基于词的N-Gram算法识别新词。对样本使用ICTCLAS分词系统处理后,以词为单位进行大小为N的滑动窗口操作。
本研究以植物学作为专业领域的样本,选取《中国植物志》作为样本文本集来源。从中国植物志网络版(http://frps.plantphoto.cn/dzb_list2.asp)中随机抽取了200篇植物的物种描述文本,长度在300-600字之间,总样本字数超过70 000字。选取这样的样本集有两个原因:
(1)植物物种描述文本包含大量新词,其行文方式和构词方式与日常用语不同,能够有效地代表专业领域的特殊语境,很好地反映专业语境对于新词识别带来的影响。显示了中国科学院计算技术研究所研发的ICTCLAS分词系统对番茄枝科植物毛叶鹰爪花的描述文本分词的结果,“小枝”、“长圆形”、“长椭圆形”、“基部”等专业词汇都不能正确切分。
图1 切词结果
(2)《中国植物志》是目前世界上规模庞大、所含种类非常丰富的一部植物学巨著,全书80卷126分册5 000多万字。记载了我国301科3 408属31 142种植物的科学名称、形态特征、生态环境、地理分布、经济用途和物候期等[]。这本书是中文植物描述最权威的著作,适合作为植物学领域文本的代表。
3 研究步骤
在ICTCLAS切词的基础上采用基于N-Gram统计的方法提取新词的候选词,通过不同的评价函数过滤垃圾串,识别新词,从而形成专业领域的用户词典,提高ICTCLAS在专业领域的切词精度。主要分为以下几个步骤:
(1)样本数据预处理:将从网上得到的PDF格式文档转变为TXT格式的纯文本文档,去除其中的英文字符,将部分英文标点更换为中文标点格式,得到纯中文文本,每个植物描述单独作为一个文档,这些文档形成实验集。
(2)制作标准集:对实验集中的文档手工分词,切分后的文档集合作为标准集。本研究以手工分词作为正确的分词结果,通过与标准集的对比判断新词识别算法的优劣。
(3)字符切分:使用ICTCLAS分词系统对样本进行初步切分,分出的词作为元字符(Gram),初步切分产生的样本集合为切词集合。
(4)识别候选词:按照标点符号,将文本切分成句;识别N-Gram,去掉标点,以切词得到的字符串整体作为单位即一个Gram,N取值2-4,分别识别2-Gram、3-Gram、4-Gram字符串;获得新词候选项,删除字符串长度超过6的N-Gram,其余作为新词候选项。以切词集合中的一句话为例,识别候选词的过程如所示:
图2 识别候选词
(5)删除垃圾串:根据评价函数对新词候选词进行排序,对比观察几种评价函数对于词语排序的影响,按照一定的阈值筛选新词。根据已有研究,本文选取了三种常用的评价函数:词频、文档频率、平均词频[]。上述指标的定义如下:
①词频(TF)指字符串在文本中出现的频率。字符串作为整体同时出现的次数越多,越有可能是独立的词语。
②文档频率(D)是指出现字符串的文档数目。D计算量小,有些字符串也许出现总次数不多,但是每篇文献都有提到,那么也可能是独立的词语。
③平均词频(TF/D)是指平均每篇文档中字符串出现的次数,该值越高,字符串越可能是新词。计算公式为TF/D= 字符串出现的频率/出现字符串的文档数目。
六、新词发现程序演示
词典中没有的,但是结合紧密的字或词有可能组成一个新词。 比如:"水立方"如果不在词典中,可能会切分成两个词"水"和"立方"。如果在一篇文档中"水"和"立方"结合紧密,则"水立方"可能是一个新词。可以用信息熵来度量两个词的结合紧密程度。信息熵的一般公式是: 如果X和Y的出现相互独立,则P(X,Y)的值和P(X)P(Y)的值相等,I(X,Y)为0。如果X和Y密切相关,P(X,Y)将比P(X)P(Y)大很多,I(X,Y)值也就远大于0。如果X和Y的几乎不会相邻出现,而它们各自出现的概率又比较大,那么I
(X,Y)将取负值,这时候X和Y负相关。设f(C)是词C出现的次数,N是文档的总词数,则: 因此,两个词的信息熵计算如下: 两个相邻出现的词叫做二元连接串。
从二元连接串中计算其信息熵的代码如下所示:
新词语有些具有普遍意义的构词规则,例如"模仿秀"由"动词+名词"组成。统计的方法和规则的方法结合对每个文档中重复子串组成的候选新词打分,超过阈值的候选新词选定为新词。此外,可以用Web信息挖掘的方法辅助发现新词:网页锚点上的文字可能是新词,例如"美甲"。另外,可以考虑先对文档集合聚类,然后从聚合出来的相关文档中挖掘新词。
七、新词发现案例
(1) 地址 http://nlpchina.github.io/ansj_seg/,点击
新词发现小工具即可,按照上面的操作即可进行
(2)项目地址 https://code.csdn.net/helihongzhizhuo/wordfind
该项目中有两种发现新词的方式
1、NewWordDiscoverTest类运行
2、NagaoAlgorithm 类运行
其中 第一种运用的是Chinese
T New words Finder. 中文三段式机械分词算法; 未登录新词发现算法
第二种运用
采用Nagao算法统计各个子字符串的频次,然后基于这些频次统计每个字符串的词频、左右邻个数、左右熵、交互信息(内部凝聚度)
(3)张华平老师的新词发现
项目首页 https://code.csdn.net/helihongzhizhuo/ictclas2013
但是调用的dll是32位的,64位系统中总报Exception in thread "main" java.lang.UnsatisfiedLinkError: ----异常,找了一下没找到32的系统
八、效果比较
对于第一种,ansj_seg中的新词发现效果
效果较好的人名、地名等,应该是按规则识别的。就是按统计规律总结出,词头、中间字和词尾的常见字,然后将句子的各个切片与之匹配,进而发现可能的词,再结合消歧处理,决定最后分词时是否使用该新词。
同时,会统计新词出现的频率,给出排序。
项目https://code.csdn.net/helihongzhizhuo/wordfind中的第一种效果
NewWordDiscoverTest类运行的效果
返回的词相对比较好,可以自定义词典和停用词,但是运行速度较慢
NagaoAlgorithm
类运行的效果 返回的词不太好,且文件一大就内存溢出
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!记录工作中的所见、所想,欢迎与广大网友交流探讨
开源 Java 中文分词器 Ansj
ansj 是一个开源的 Java 中文分词工具,基于中科院的 ictclas 中文分词算法,比其他常用的开源分词工具(如mmseg4j)的分词准确率更高。
在线演示:
官网地址:
Github地址:
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!IK,ansj,mmseg4j分词性能比较
下载ik最新版本:这个版本是支持lucene4的.其主页为:
下载ansj最新版本:
下载mmesg4j最新版本选择其中版本
然后建立一个web project,把相应的包导入,具体细节不用再详述。建立一个测试类,贴出其中关键代码:
使用ik进行分词:
public String ikAnalyzer(String str) {
Reader input = new StringReader(str);
// 智能分词关闭(对分词的精度影响很大)
IKSegmenter iks = new IKSegmenter(input, true);
Lexeme lexeme = null;
StringBuilder sb = new StringBuilder();
while ((lexeme = iks.next()) != null) {
sb.append(lexeme.getLexemeText()).append("|");
} catch (IOException e) {
e.printStackTrace();
return sb.toString();
使用ansj进行分词
public String ansjAnalyzer(String str) {
List&Term& terms = NlpAnalysis.paser(str);
new NatureRecognition(terms).recognition();
StringBuilder sb = new StringBuilder();
for (Term term : terms) {
if (!" ".equals(term.getName()) && !" ".equals(term.getName()) && term.getName().trim().replaceAll("[\\pP\\pM\\pS]", "").length() & 1) {
sb.append(term.getName()).append("|");
return sb.toString();
使用ansj分词找出词性为名词的
public String ansjAnalyzerNature(String str) {
List&Term& terms = NlpAnalysis.paser(str);
new NatureRecognition(terms).recognition();
StringBuilder sb = new StringBuilder();
System.out.println(terms.toString());
// 词性过滤
Nature nature;
for (Term term : terms) {
nature = term.getNatrue();
if (nature.natureStr.subSequence(0, 1).equals("n") || nature.natureStr.subSequence(0, 1).equals("h")) {
if (!" ".equals(term.getName()) && !" ".equals(term.getName()) && term.getName().trim().replaceAll("[\\pP\\pM\\pS]", "").length() & 1) {
sb.append(term.getName()).append("|");
return sb.toString();
使用mmseg4j进行分词:
public String mmseg4jAnalyzer(String str)throws IOException{
Reader input = new StringReader(str);
return segWords(input, "|");
public String segWords(Reader input, String wordSpilt) throws IOException {
StringBuilder sb = new StringBuilder();
Seg seg = getSeg(); //取得不同的分词具体算法
MMSeg mmSeg = new MMSeg(input, seg);
Word word = null;
boolean first = true;
while((word=mmSeg.next())!=null) {
if(!first) {
sb.append(wordSpilt);
String w = word.getString();
sb.append(w);
first = false;
return sb.toString();
protected Seg getSeg() {
return new ComplexSeg(Dictionary.getInstance());
输入的文章:测试结果为:
再输入别的文章:测试结果为:
通过输入别的文章发现,速度基本上差不多,分词效果也还差不多。只不过ansj提供了分析词性的功能。算法比较复杂。个别词有的词未认识出来,是由于词库的原因。
总结在实际应用中,根据个人的以上项目熟悉程度,随便选择以上三种分词算法的任意一种,其实速度和效果都差不多。重要的是词库。根据业务的需要,整理出相应的词库,这会对分词效果有比较大的提升。
如果搞源码研究,个人推荐ik分词和mmseg4j分词,这两个算法也比较简单,可以比较快的吃透。
http://www.chepoo.com/ik-ansj-mmseg4j-segmentation-performance-comparison.html
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长! 上传我的文档
 下载
 收藏
粉丝量:15
该文档贡献者很忙,什么也没留下。
 下载此文档
Nagao的串频统计算法
下载积分:350
内容提示:Nagao的串频统计算法
文档格式:PPT|
浏览次数:839|
上传日期: 23:19:16|
文档星级:
全文阅读已结束,如果下载本文需要使用
 350 积分
下载此文档
该用户还上传了这些文档
Nagao的串频统计算法
关注微信公众号会一些前端,懂一些后端,做过一些管理,弄过一些运维,我是一枚爱折腾的程序猿...
开源 Java 中文分词器 Ansj 作者孙健专访
Ansj 是一个开源的 Java 中文分词工具,基于中科院的 ictclas 中文分词算法,比其他常用的开源分词工具(如mmseg4j)的分词准确率更高。
在线演示:
官网地址:
Github地址:
我们本期采访了Ansj的作者孙健,请他为大家详细介绍一下这个分词工具。 ITeye期待并致力于为国内优秀的开源项目提供一个免费的推广平台,如果你和你的团队希望将自己的开源项目介绍给更多的开发者,或者你希望我们对哪些开源项目进行专访,请告诉我们,发站内短信给或者发邮件到即可。
先来个自我介绍吧!
孙健,胸无大志,没想过创业,没想过发财,只想高高兴兴写两行代码,做了近五年Java程序员,写过页面,干过运维,做过人力,忽悠过客户,擅长字符串操作,擅长数据结构和算法。现在主要从事检索、自然语言处理、数据挖掘等方面工作。
介绍一下Ansj!
Ansj中文分词是一款纯Java的、主要应用于自然语言处理的、高精度的中文分词工具,目标是“准确、高效、自由地进行中文分词”,可用于人名识别、地名识别、组织机构名识别、多级词性标注、关键词提取、指纹提取等领域,支持行业词典、用户自定义词典。
上面是客套话,先说明一下Ansj命名的由来吧。本来开始打算叫totoro分词(同事帮忙起的名),最后发现好多厕所中卫生洁具都叫“TOTO” ^_^
正好我注册了域名,于是乎,就叫这个名字吧。
你认为中文分词的难点是什么?
在这里说分词有点老生常谈了。的确,中文分词已经非常成熟了,但是之间有一些问题依旧比较难解。个人认为大致有以下几点吧: 1.
中文歧义的识别
比较出名的一句话“结婚的和尚未结婚的”,如果使用正向最大匹配,容易分成“结婚/的/和尚/未/结婚的”,于是有的学者试图倒过来识别,逆向匹配会大于正向。但是碰到这句“结合成分子时”,采用逆向最大匹配,则会分为“结合/成分/子时”,更有甚者像“咬了猎人的狗”这种语意不明的词语,就更不容易正确分词了。这是中文分词的软肋。下面是些典型的歧义句: 交叉歧义(多种切分交织在一起):内塔内亚胡说的/确实/在理组合歧义(不同情况下切分不同):这个人/手上有痣、我们公司人手真歧义(几种切分都可以):乒乓球拍/卖/完了、乒乓球/拍卖/完了2.
实体名识别
这个是中文分词遇到的最大的难点,也是最最紧迫的。实体名识别包括人名识别、地名识别、机构名识别,还包括有监督识别和无监督识别。有监督的还好,无监督基本是无解的,比如“王大力发球”是“王大力”还是“大力发球”,一般人都难以识别。 3.
新词热词发现
目前常用的新词发现还是一个比较有研究性的课题,虽然有些论文在准确率很高,但是大多是封闭测试,这意味着结果很难应用到实际工程中。目前Ansj采用的新词发现方式比较简单,采用了高频词的匹配方式,不使用规则,用统计重复串识别新词,根据词性去掉干扰词,虽然有一定的效果,但还是差强人意。 4.
颗粒度问题
这个就是一个规则探讨的问题了,比如“北京大学”是“北京”+“大学”还是“北京大学”,人各有志,就连同一个人不同时间的标注也有可能是有区别的,虽然这个问题严格上来说不属于技术问题,但是对分词结果的评测却有着很大的关系,Ansj采用“能识别就识别”的策略方针,所以在真正R值的时候偏低,总之一句话,适合学术的不一定适合工业,反之亦然。
简单介绍一下Ansj分词用到的算法,其分词原理是什么?
Ansj并非我创新,可以说是一个ictclas的Java版本,基本原理一致,只不过在分词优化算法上做了一些改进。
该算法实现分词有以下几个步骤: 全切分,原子切分;N最短路径的粗切分,根据隐马尔科夫模型和viterbi算法,达到最优路径的规划;人名识别;系统词典补充;用户自定义词典的补充;词性标注(可选)
Ansj分词的准确率大概是多少?
这是我采用人民日报1998年1月语料库的一个测试结果,首先要说明的是这份人工标注的语料库本身就有错误。 P(准确率):0.267R(召回率):0.8712F(综合指标F值):0.6494
在歧义、未登录词问题上,Ansj表现怎样?
歧异方面的处理方式自我感觉还可以,基于“最佳实践规则+统计”的方式,虽然还有一部分歧异无法识别,但是已经完全能满足工程应用了。
至于未登录词的识别,目前重点做了中文人名的识别,效果还算满意,识别方式用的“字体+前后监督”的方式,也算是目前我所知道的效果最好的一种识别方式了。
Ansj的性能如何?
在我的测试中,Ansj的效率已经远超ictclas的其他开源实现版本。
核心词典利用双数组规划,每秒钟能达到千万级别的粗分。在我的MacBookAir上面,分词速度大约在300w/字/秒,在酷睿i5+4G内存组装机器上,更是达到了400w+/字/秒的速度。
如何添加自定义词典?
Ansj已经实现了用户自定义词典的动态添加删除,当然,也支持从文件加载词典。
从硬盘加载用户自定义词典的方法:
用户自定义词典默认路径:项目目录/library/userLibrary/userLibrary.dic
格式为:[自定义词]
[词频],如:csdn创新院
userDefine
1000,中间用TAB键隔开
原分词结果:[csdn, 创新, 院, 是, 一个, 好, 公司]
增加词典后:[csdn创新院, 是, 一个, 好, 公司]
详细内容见:
用户自定义词典的动态添加删除方法见:
你在开发过程中,遇到哪些困难?
最大的困难是训练样本和语料库的不足,遗憾国内没有共享,大多数都是收费的,而且好贵。
你认为Ansj还需要在哪些方面进行完善?
我打算下一版的改进将围绕未登录词进行,采用crf来做新词的识别。当然随着系统的庞大,每次修改都要考虑效率内存占用。
虽然已经着手开始进行中,但是进展一直不快。有兴趣的同学可以多提意见,可以通过Github参与到该项目中,让我们做一个真正的Java版的高准确率分词。
Github地址:
dsx1013 写道
这个为什么没有跟别的分词一样 给个停用词字典,自己加载呢?感觉还要自己去读字典再加再加进去有点麻烦呢,楼主有没有想过整合这快呢?初学者,别见怪哈
补充问一句,加了停用词后,原本的为N的词性都变了,没在词性说明中找到nis,nnt对应的说明
[检察院/n,董事长/n,有限公司/n]
[检察院/nis,董事长/nnt,有限公司/nis]
你加的不是停用词词典。是用户自定义词典把。。你e可以参看我的文档
http://nlpchina.github.io/ansj_seg/
wyyina 写道
wyyina 写道
楼主你好,为什么 我导入ansj_seg-2.0.7.jar包 测试一下List&Term& parse = NlpAnalysis.parse("洁面仪配合洁面深层清洁毛孔");
System.out.println(parse);
这个代码 eclispe提示 我的包错误
找到原因了 要导入nlp-lang的一个包
但我在官网没看到~
不报错了 但是运行出来 内存溢出! Java heap space
把jvm内存给大点
这个为什么没有跟别的分词一样 给个停用词字典,自己加载呢?感觉还要自己去读字典再加再加进去有点麻烦呢,楼主有没有想过整合这快呢?初学者,别见怪哈
补充问一句,加了停用词后,原本的为N的词性都变了,没在词性说明中找到nis,nnt对应的说明
[检察院/n,董事长/n,有限公司/n]
[检察院/nis,董事长/nnt,有限公司/nis]
wyyina 写道
楼主你好,为什么 我导入ansj_seg-2.0.7.jar包 测试一下List&Term& parse = NlpAnalysis.parse("洁面仪配合洁面深层清洁毛孔");
System.out.println(parse);
这个代码 eclispe提示 我的包错误
找到原因了 要导入nlp-lang的一个包
但我在官网没看到~
不报错了 但是运行出来 内存溢出! Java heap space
楼主你好,为什么 我导入ansj_seg-2.0.7.jar包 测试一下List&Term& parse = NlpAnalysis.parse("洁面仪配合洁面深层清洁毛孔");
System.out.println(parse);
这个代码 eclispe提示 我的包错误
找到原因了 要导入nlp-lang的一个包
但我在官网没看到~
楼主,我发现那个lucene的插件分出来的token会将逗号,《》书名号等都符号都作为一个词,这个看上去没有意义,谁会搜索一个逗号呢?有什么方法可以去掉这些符号?
lucene插件支持 停用词表
十分感谢你的回答:
1.测试时内存是调整到1024m的
2.并且先测试一句话加载词库到内存
3.测试简单的一句话,然后累计测试是可以达到180w字/s,比如测试“我是中国人”,测试十万次,计算总时间为time,500000/time.
4.测试大文本进行反复测试,明显效率下降很多,一般在30w/s
5.我是抽取关键词使用,所以必须获取词性,大文本获取词性,内存瞬间上G
6.另外我只需要分词结果,不需要人名 新词 等发现策略,这个自己有单独的模块去实现了。
,合适的话加我下,我把测试文本传给你。
明白了你加我吧..5144694
我把8w字的文档提前分句然后拼装结果,测试结果如下:
List&Term& terms = ToAnalysis.parse(lines[i]);
new NatureRecognition(terms).recognition();
说明文本过长建立到一个图里面对获取词性影响很大
还有一个慢的原因.如果内存不够.你把内存调整大点..应该速度会快..试试调整到 -xms1024m
多谢解答,
测试没算读取文本的时间,采用的就是ToAnaysis方法 ,测试一个8w字的文档:
List&Term& terms = ToAnalysis.parse(input);
占时间:143ms
new NatureRecognition(terms).recognition();
占时间:2473ms
另外有几个疑问:
1.为何不根据空格和标点分割建立多个有向图,这样计算最短路径时应该会提高效率。
2.标注词性时候占用时间过长,能否在分词的过程中去标注词性而非出来结果后再标注
3.有咩有考虑如果一个句子过长,假设一句话全是汉字且非常长的情况下,计算最短路径时会比较耗时。
请问你qq多少,我加你qq聊下。
1.空格和标点对分词结果也有影响的.比如 人名 顿号 人名 都是需要考虑进来的
2.词性标注如果分词的时候就标注.速度会慢更多.词性标注.不建议句子太长.太长的话对内存占用太多..
3.其实最短路径.和句子长短关系不大.短句反而时间长..
最后.我估计你时间长是把加载词典的时间也算进去了吧?否则不可能这么慢...你可以在分词前先分一句话.."孙健123好公司...."类似这样然后在开始算时间
我测试了分词速度,大文本在28w/s,用户词库自己整的,有30万左右,是什么原因呢
1.你不是在lucene中用的吧?
2.你用的NlpAnalysis吧?
你常识用下 ToAnalysis 。这个速度快。应该是200w/s左右。。。还有你读文本的方式。。最好能把代码发上来我看看
ansjsun 写道
BeMyself_wangl 写道
Exception in thread "main" java.lang.NoSuchMethodError: org.ansj.splitWord.analysis.ToAnalysis.&init&(Ljava/io/R)V
at org.ansj.lucene4.AnsjAnalysis.createComponents(AnsjAnalysis.java:38)
at org.apache.lucene.analysis.Analyzer.tokenStream(Analyzer.java:142)
ansj_seg-1.1以后就报这个错了。
是我调用的不对?
应该不是..treesplit包更新了.你得更新到1.2版本..通过http://maven.ansj.org/org/ansj/tree_split/1.2/ 下载
我一开始就是tree_split-1.2.jar+ansj_lucene4_plug-1.0.jar+ansj_seg-1.3.jar
就是报错。
把ansj_seg-1.3.jar 退回到 ansj_seg-1.1.jar 就不报错了。
你好.你联系我qq吧..因为我现在都不怎么做lucene了.而且1.3改动的地方比较大..我有点担心,偏移量我写的不对.你要是还在做.有兴趣.我帮你调试.你帮我反馈问题.我的q是5144694
BeMyself_wangl 写道
Exception in thread "main" java.lang.NoSuchMethodError: org.ansj.splitWord.analysis.ToAnalysis.&init&(Ljava/io/R)V
at org.ansj.lucene4.AnsjAnalysis.createComponents(AnsjAnalysis.java:38)
at org.apache.lucene.analysis.Analyzer.tokenStream(Analyzer.java:142)
ansj_seg-1.1以后就报这个错了。
是我调用的不对?
应该不是..treesplit包更新了.你得更新到1.2版本..通过http://maven.ansj.org/org/ansj/tree_split/1.2/ 下载
我一开始就是tree_split-1.2.jar+ansj_lucene4_plug-1.0.jar+ansj_seg-1.3.jar
就是报错。
把ansj_seg-1.3.jar 退回到 ansj_seg-1.1.jar 就不报错了。
Exception in thread "main" java.lang.NoSuchMethodError: org.ansj.splitWord.analysis.ToAnalysis.&init&(Ljava/io/R)V
at org.ansj.lucene4.AnsjAnalysis.createComponents(AnsjAnalysis.java:38)
at org.apache.lucene.analysis.Analyzer.tokenStream(Analyzer.java:142)
ansj_seg-1.1以后就报这个错了。
是我调用的不对?
应该不是..treesplit包更新了.你得更新到1.2版本..通过http://maven.ansj.org/org/ansj/tree_split/1.2/ 下载
另外在arrays.dic里面出现的词,用户词库里面去重这些词不会影响分词效果吧?
如果 你的分词是1个月前的。。那个辞典是不去重的。。。用户自定义辞典优先最大匹配原则。。
对于这种词语 “他/从/马上/掉/了/下来”会是这个结果.最新版的对用户自定义辞典中的词。进行了去重设置。
总而言之。不怕重复。对分词影响微乎其微。就算用户自定义辞典本身有词重复。也没有影响。
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!

我要回帖

更多关于 nagao算法 的文章

 

随机推荐