深度解析中文分词器算法(最大正向/逆向匹配)

中文分词算法概述:

1:非基于词典的分词(人工智能领域)

相当于人工智能领域计算。一般用于机器学习,特定领域等方法,这种在特定领域的分词可以让计算机在现有的规则模型中,

推理如何分词。在某个领域(垂直领域)分词精度较高。但是实现比较复杂。

例:比较流行的语义网:基于本体的语义检索。

大致实现:用protege工具构建一个本体(在哲学中也叫概念,在80年代开始被人工智能),通过jena的推理机制和实现方法。

实现对Ontology的语义检索。

Ontology语义检索这块自己和一朋友也还在琢磨,目前也只处于初级阶段。这一块有兴趣的朋友可以留言

一起共享资源。

2:基于词典的分词(最为常见)

这类分词算法比较常见,比如正向/逆向匹配。例如: mmseg分词器 就是一种基于词典的分词算法。以最大正向匹配为主,多

种 消除歧义算法为辅。但是不管怎么分。该类分词方法,分词精度不高。由于中文比较复杂,不推荐采用正向最大匹配算法的中文

分词器。。逆向最大匹配算法在处理中文往往会比正向要准确。

接下来分析第2种:基于词典的分词算法(最长的词优先匹配)。 先分析最大正向匹配算法

一: 具体流程图如下:

一:以下代码片段为最大正向匹配算法:

package hhc.forwardAlgorithm;

import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * @Description:
 * @Date: 2015-2-7上午02:00:51
 * @Author 胡慧超
 * @Version 1.0
 */
@SuppressWarnings("unchecked")
public class TokenizerAlgorithm {
	private static final List<String> DIC=new ArrayList<String>();
	private static int MAX_LENGTH;

	/**
	 * 把词库词典转化成dic对象,并解析词典信息
	 */
	static {
		try {
			System.out.println("开始初始化字典...");
			int max=1;
			int count=0;
			//读取词典中的每一个词
			URL url=TokenizerAlgorithm.class.getClassLoader().getResource("hhc/dic.txt");
			Path path=Paths.get(url.toString().replaceAll("file:/", ""));
			List<String> list=Files.readAllLines(path, Charset.forName("UTF-8"));
			System.out.println("读取词典文件结束,词总数为:"+list.size());
			for(String line:list){
				DIC.add(line);
				count++;
				//获取词库中 ,最大长度的词的长度
				if(line.length()>max){
					max=line.length();
				}
			}
			MAX_LENGTH=max;
			System.out.println("初始化词典结束,最大分词长度为:"+max+"  !!");
			System.out.println("------------------------------------------------------------------------");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 正向分词算法
	 * @param text
	 * @return
	 */
	public static List forwardSeg(String text){
	    List result=new ArrayList();
		while(text.length()>0){
			int len=MAX_LENGTH;
			if(text.length()<MAX_LENGTH){
				len=text.length();
			}
			//取指定的最大长度 文本去字典中匹配
			String tryWord=text.substring(0, len);
			while(!DIC.contains(tryWord)){//如果词典中不包含该段文本
				//如果长度为1 的话,且没有在字典中匹配,返回
				if(tryWord.length()==1){
					break;
				}
				//如果匹配不到,则长度减1,继续匹配
				/**
				 * --这里就是最关键的地方,把最右边的词去掉一个,继续循环
				 */
				tryWord=tryWord.substring(0, tryWord.length()-1);
			}
			result.add(tryWord);
			//移除该次tryWord,继续循环
			text=text.substring(tryWord.length());
		}
		return result;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		List<String> lst=new ArrayList();
		lst.add("研究生命起源");
		lst.add("食物和服装");
		lst.add("乒乓球拍卖完了");
		for(String str:lst){
			List<String> list=forwardSeg(str);
			String word="";
			for(String s:list){
				s+="/";
				word+=s;
			}
			System.out.println(word);
		}
	}

执行正向分词结果:

二:最大逆向分词算法

考虑到逆向,为了 区分分词的数据的连贯性。我们采用Stack(栈对象,数据结果,后进先出,不同于Queue和ArrayList有顺序的先进先出) 这个对象来存储分词结果。。

	/**
	 * 逆向分词算法
	 * @param text
	 * @return
	 */
	public static List reverseSeg(String text){
		Stack<String> result=new Stack();
		while(text.length()>0){
			int len=MAX_LENGTH;
			if(text.length()<MAX_LENGTH){
				len=text.length();
			}
			//取指定的最大长度 文本去字典中匹配
			String tryWord=text.substring(text.length()-len);
			while(!DIC.contains(tryWord)){//如果词典中不包含该段文本
				//如果长度为1 的话,且没有在字典中匹配,返回
				if(tryWord.length()==1){
					break;
				}
				//如果匹配不到,则长度减1,继续匹配
				/**
				 * --这里就是最关键的地方,把最左边的词去掉一个,继续循环
				 */
				tryWord=tryWord.substring(1);
			}
			result.add(tryWord);
			//移除该次tryWord,继续循环
			text=text.substring(0,text.length()-tryWord.length());
		}
		int size=result.size();
		List list =new ArrayList(size);
		for(int i=0;i<size;i++){
			list.add(result.pop());
		}
		return list;
	}

执行逆向分词结果

以上代码实现了两种正向和逆向的算法,可以很明显的比较中文分词结果。

但是效率,,呵呵!确实不咋的。欢迎打脸。

比如:数据结构就先不提。text.substring(0, 0+len)会导致产生大量的新的字符串的产生,消耗CPU的同时还会促发垃圾回收频繁

发生导致性能下降。随着最大长度的增加,性能会严重下降。

像之前介绍的采取正向最大匹配算法的mmseg分词器,内部设置了4个消除歧义的过滤算法,这四个歧义解析规则表明是相当有效率

的。总体来讲。mmseg的分词精度还是值得推荐的。。。下篇博客解析 最小正向/逆向匹配算法。

时间: 2024-10-08 11:34:45

深度解析中文分词器算法(最大正向/逆向匹配)的相关文章

中文分词常用算法之基于词典的正向最大匹配

算法描述: S1为带切分字符串,S2为空,MaxLen为词典中的最大词长 判断S1是否为空,若是则输出S2 从S1左边开始,取出待处理字符串str(其中str的长度小于MaxLen) 查看str是否在词典中,若是则转5,若否则转6 S2+=str+”/”,S1-=str,转2 将str最右边的一个字去掉 判断str是否为单字,若是则转5,若否则转4 Java实现代码: 1 public static List<String> FMM(String text) { 2 List<Strin

11大Java开源中文分词器的使用方法和分词效果对比

本文的目标有两个: 1.学会使用11大Java开源中文分词器 2.对比分析11大Java开源中文分词器的分词效果 本文给出了11大Java开源中文分词的使用方法以及分词结果对比代码,至于效果哪个好,那要用的人结合自己的应用场景自己来判断. 11大Java开源中文分词器,不同的分词器有不同的用法,定义的接口也不一样,我们先定义一个统一的接口: /** * 获取文本的所有分词结果, 对比不同分词器结果 * @author 杨尚川 */ public interface WordSegmenter {

9大Java开源中文分词器的使用方法和分词效果对比

本文的目标有两个: 1.学会使用9大Java开源中文分词器 2.对比分析9大Java开源中文分词器的分词效果 9大Java开源中文分词器,不同的分词器有不同的用法,定义的接口也不一样,我们先定义一个统一的接口: /**  * 获取文本的所有分词结果, 对比不同分词器结果  * @author 杨尚川  */ public interface WordSegmenter {     /**      * 获取文本的所有分词结果      * @param text 文本      * @retur

当前几个主要的Lucene中文分词器的比较

1. 基本介绍: paoding:Lucene中文分词"庖丁解牛" Paoding Analysis imdict :imdict智能词典所采用的智能中文分词程序 mmseg4j: 用 Chih-Hao Tsai 的 MMSeg 算法 实现的中文分词器 ik :采用了特有的"正向迭代最细粒度切分算法",多子处理器分析模式 2. 开发者及开发活跃度: paoding :qieqie.wang, google code 上最后一次代码提交:2008-06-12,svn

中文分词常用算法之基于词典的逆向最大匹配

算法描述: S1为带切分字符串,S2为空,MaxLen为词典中的最大词长 判断S1是否为空,若是则输出S2 从S1右边开始,取出待处理字符串str(其中str的长度小于MaxLen) 查看str是否在词典中,若是则转5,若否则转6 S2+=str+”/”,S1-=str,转2 将str最左边的一个字去掉 判断str是否为单字,若是则转5,若否则转4 Java实现代码: 1 public static List<String> BMM(String text) { 2 Stack<Stri

Lucene的中文分词器IKAnalyzer

分词器对英文的支持是非常好的. 一般分词经过的流程: 1)切分关键词 2)去除停用词 3)把英文单词转为小写 但是老外写的分词器对中文分词一般都是单字分词,分词的效果不好. 国人林良益写的IK Analyzer应该是最好的Lucene中文分词器之一,而且随着Lucene的版本更新而不断更新,目前已更新到IK Analyzer 2012版本. IK Analyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包.到现在,IK发展为面向Java的公用分词组件,独立于Lucene项目,同时

转:从头开始编写基于隐含马尔可夫模型HMM的中文分词器

http://blog.csdn.net/guixunlong/article/details/8925990 从头开始编写基于隐含马尔可夫模型HMM的中文分词器之一 - 资源篇 首先感谢52nlp的系列博文(http://www.52nlp.cn/),提供了自然语言处理的系列学习文章,让我学习到了如何实现一个基于隐含马尔可夫模型HMM的中文分词器. 在编写一个中文分词器前,第一步是需要找到一些基础的词典库等资源,用以训练模型参数,并进行后续的结果评测,这里直接转述52nlp介绍的"中文分词入门

如何在Elasticsearch中安装中文分词器(IK)和拼音分词器?

声明:我使用的Elasticsearch的版本是5.4.0,安装分词器前请先安装maven 一:安装maven https://github.com/apache/maven 说明: 安装maven需要java1.7+ 编译安装分词器时,可能会报错,报错信息如下: [ERROR] COMPILATION ERROR : [INFO] -------------------------------------------------------------[ERROR] No compiler i

Solr4.10与tomcat整合并安装中文分词器

1.solr Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器.Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置.可扩展,并对索引.搜索性能进行了优化. Solr可以从Solr官方网站(http://lucene.apache.org/solr/ )下载,解压后目录如下: bin:solr的运行脚本 contrib:solr的一些贡献软件/插件,用于增强solr的功能. dist:该目录包含build过程中产生的war和jar文