OpenNLP:驾驭文本,分词那些事

OpenNLP:驾驭文本,分词那些事

作者 白宁超

2016年3月27日19:55:03

摘要:字符串、字符数组以及其他文本表示的处理库构成大部分文本处理程序的基础。大部分语言都包括基本的处理库,这也是对文本处理或自然语言处理的前期必要工作。典型代表便是分词、词性标注、句子识别等等。本文所介绍的工具主要针对英文分词,对于英文分词工具很多,笔者经比较Apache OpenNLP效率和使用便捷度较好。另外其针对Java开发提供开源的API。开篇简介OpenNLP的情况,随后介绍6种常用模型,最后针对每种模型的使用和Java实现进行总结。部分笔者可能质疑那么中文分词怎么办?随后篇章会单独介绍中科院研究团队基于隐马尔可夫模型开发的中文分词工具NLPIR(ICTCLA)。内容经过多篇文档和书籍整理汇编,代码经运行无误。(本文原创,转载请标明出处:OpenNLP:驾驭文本,分词那些事

1 什么是OpenNLP,其具有哪些"内功"?

OpenNLP是为何物?

维基百科Apache OpenNLP库是一个基于机器学习自然语言文本处理的开发工具包,它支持自然语言处理中一些共有的任务,例如:标记化句子分割词性标注固有实体提取(指在句子中辨认出专有名词,例如:人名)、浅层分析句字分块)、语法分析指代。这些任务通常都需要较为先进的文字处理服务功能。

官方文档:Apache的OpenNLP库是自然语言文本的处理基于机器学习的工具包。它支持最常见的NLP任务,如断词,句子切分,部分词性标注,命名实体提取,分块,解析和指代消解。这些任务通常需要建立更先进的文字处理服务。OpenNLP还包括最大熵和基于感知机器学习。该OpenNLP项目的目标是创造上述任务的成熟工具包。一个附加的目的是提供一种大量预建模型为各种语言,以及这些模型衍生自注释文本资源。

使用:其支持Windows、linux等多个操作系统,本文主要介绍Windows下:

1 命令行界面(CLI):OpenNLP脚本使用JAVA_CMD和JAVA_HOME变量,以确定哪些命令用来执行Java虚拟机。OpenNLP脚本使用OPENNLP_HOME变量来确定OpenNLP的二进制分发的位置。建议这个变量指向当前OpenNLP版本和更新PATH变量的二进制分发版包括$OPENNLP_HOME/bin or %OPENNLP_HOME%\bin。这样的配置允许方便调用OpenNLP。下面的例子假设这个配置已经完成。使用如下:

$ opennlp ToolName lang-model-name.bin < input.txt > output.txt
当工具被执行这种方式,模型是装载和工具正在等待来自标准输入的输入。此输入处理,并打印到标准输出。

2 Java在控制台:进行其API的调用,以下代码演示均采用此法。

2 句子探测器

功能介绍:该OpenNLP句子探测器可以检测到一个标点符号标志着一个句子的结尾与否。在这个意义上一个句子被定义为最长空白修整的标点符号之间的字符序列。第一和最后一句作出例外。第一个非空白字符被假定为开始一个句子,以及最后的非空白字符被假定为一个句子端。下面的示例文本应该分割成它的句子。

API:句子探测器还提供了一个API来培养一个新的句子检测模型。三个基本步骤是必要的训练它:

  • 应用程序必须打开一个示例数据流
  • 调用SentenceDetectorME.t??rain方法
  • 保存SentenceModel到文件或直接使用它

代码实现:

	/**
	 * 1.句子探测器:Sentence Detector
	 * @deprecated Sentence detector is for detecting sentence boundaries. Given the following paragraph:
	 * Hi. How are you? This is Mike.
	 * 如:Hi. How are you? This is Mike.将返回如下:
	 * Hi. How are you?
	 * This is Mike.
	 * @throws IOException
	 * @throws InvalidFormatException
	 */
	public static void SentenceDetector(String str) throws InvalidFormatException, IOException
	{
		//always start with a model, a model is learned from training data
		InputStream is = new FileInputStream("./nlpbin/en-sent.bin");
		SentenceModel model = new SentenceModel(is);
		SentenceDetectorME sdetector = new SentenceDetectorME(model);

		String sentences[] = sdetector.sentDetect(str);

		System.out.println(sentences[0]);
		System.out.println(sentences[1]);
		is.close();
		System.out.println("---------------1------------");
	}

运行结果:

3 标记生成器

功能介绍:该OpenNLP断词段输入字符序列为标记。符号通常是词语,标点符号,数字等OpenNLP提供多种标记生成器的实现:

  • 空白标记生成器 - 一个空白标记生成器,非空白序列被确定为符号
  • 简单的标记生成器 - 一个字符类标记生成器,同样的字符类的序列标记
  • 可学习标记生成器 - 一个最大熵标记生成器,检测基于概率模型符号边界

API:的断词可以被集成到由定义的API的应用程序。该WhitespaceTokenizer的共享实例可以从静态字段WhitespaceTokenizer.INSTANCE进行检索。该SimpleTokenizer的共享实例可以在从SimpleTokenizer.INSTANCE相同的方式进行检索。实例化TokenizerME(中可以学习标记生成器)符号模型必须先创建。

代码实现:

	/**
	 * 2.标记生成器:Tokenizer
	 * @deprecated Tokens are usually words which are separated by space, but there are exceptions.  For example, "isn‘t" gets split into "is" and "n‘t, since it is a a brief format of "is not". Our sentence is separated into the following tokens:
	 * @param str
	 */
	public static void Tokenize(String str) throws InvalidFormatException, IOException {
		InputStream is = new FileInputStream("./nlpbin/en-token.bin");
		TokenizerModel model = new TokenizerModel(is);
		Tokenizer tokenizer = new TokenizerME(model);
		String tokens[] = tokenizer.tokenize(str);
		for (String a : tokens)
			System.out.println(a);
		is.close();
		System.out.println("--------------2-------------");
	}

运行结果:

4 名称搜索

功能介绍:名称查找器可检测文本命名实体和数字。为了能够检测实体名称搜索需要的模型。该模型是依赖于语言和实体类型这是训练。所述OpenNLP项目提供了许多这些各种免费提供的语料库训练有素预训练名取景模式。他们可以在我们的模型下载页进行下载。要查找原始文本的文本必须分割成符号和句子的名字。详细描述中的一句话探测器和标记生成器教程中给出。其重要的,对于训练数据和输入的文本的标记化是相同的。

API:从应用程序中训练名字发现者的建议使用培训API而不是命令行工具。三个基本步骤是必要的训练它:

  • 应用程序必须打开一个示例数据流
  • 调用NameFinderME.t??rain方法
  • 保存TokenNameFinderModel到文件或数据库

代码实现:

	/**
	 * 3.名称搜索:Name Finder
	 * @deprecated By its name, name finder just finds names in the context. Check out the following example to see what name finder can do. It accepts an array of strings, and find the names inside.
	 * @param str
	 */
	public static void findName() throws IOException {
		InputStream is = new FileInputStream("./nlpbin/en-ner-person.bin");
		TokenNameFinderModel model = new TokenNameFinderModel(is);
		is.close();
		NameFinderME nameFinder = new NameFinderME(model);
		String[] sentence = new String[]{
			    "Mike",
			    "Tom",
			    "Smith",
			    "is",
			    "a",
			    "good",
			    "person"
			    };
		Span nameSpans[] = nameFinder.find(sentence);
		for(Span s: nameSpans)
			System.out.println(s.toString());
		System.out.println("--------------3-------------");
	}

运行结果:

5 POS标注器

功能介绍:语音标记器的部分标记符号与基于符号本身和符号的上下文中它们的相应字类型。符号可能取决于符号和上下文使用多个POS标签。该OpenNLP POS标注器使用的概率模型来预测正确的POS标记出了标签组。为了限制可能的标记的符号标记字典可以使用这增加了捉人者的标记和运行时性能。

API:部分的词类打标签训练API支持一个新的POS模式的培训。三个基本步骤是必要的训练它:

  • 应用程序必须打开一个示例数据流
  • 调用POSTagger.train方法
  • 保存POSModel到文件或数据库

代码实现:

	/**
	 * 4.POS标注器:POS Tagger
	 * @deprecated Hi._NNP How_WRB are_VBP you?_JJ This_DT is_VBZ Mike._NNP
	 * @param str
	 */
	public static void POSTag(String str) throws IOException {
		POSModel model = new POSModelLoader().load(new File("./nlpbin/en-pos-maxent.bin"));
		PerformanceMonitor perfMon = new PerformanceMonitor(System.err, "sent");//显示加载时间
		POSTaggerME tagger = new POSTaggerME(model);
		ObjectStream<String> lineStream = new PlainTextByLineStream(new StringReader(str));
		perfMon.start();
		String line;
		while ((line = lineStream.read()) != null) {
			String whitespaceTokenizerLine[] = WhitespaceTokenizer.INSTANCE.tokenize(line);
			String[] tags = tagger.tag(whitespaceTokenizerLine);
			POSSample sample = new POSSample(whitespaceTokenizerLine, tags);
			System.out.println(sample.toString());
			perfMon.incrementCounter();
		}
		perfMon.stopAndPrintFinalResult();
		System.out.println("--------------4-------------");
	}

运行结果:

6 细节化

功能介绍:文本分块由除以单词句法相关部分,如名词基,动词基的文字,但没有指定其内部结构,也没有其在主句作用。

API:该概括化提供了一个API来培养新的概括化的模式。下面的示例代码演示了如何做到这一点:

代码实现:

	/**
	 * 5.序列标注:Chunker
	 * @deprecated 通过使用标记生成器生成的tokens分为一个句子划分为一组块。What chunker does is to partition a sentence to a set of chunks by using the tokens generated by tokenizer.
	 * @param str
	 */
	public static void chunk(String str) throws IOException {
		POSModel model = new POSModelLoader().load(new File("./nlpbin/en-pos-maxent.bin"));
		//PerformanceMonitor perfMon = new PerformanceMonitor(System.err, "sent");
		POSTaggerME tagger = new POSTaggerME(model);
		ObjectStream<String> lineStream = new PlainTextByLineStream(new StringReader(str));
		//perfMon.start();
		String line;
		String whitespaceTokenizerLine[] = null;
		String[] tags = null;
		while ((line = lineStream.read()) != null) {
			whitespaceTokenizerLine = WhitespaceTokenizer.INSTANCE.tokenize(line);
			tags = tagger.tag(whitespaceTokenizerLine);
			POSSample sample = new POSSample(whitespaceTokenizerLine, tags);
			System.out.println(sample.toString());
				//perfMon.incrementCounter();
		}
		//perfMon.stopAndPrintFinalResult();

		// chunker
		InputStream is = new FileInputStream("./nlpbin/en-chunker.bin");
		ChunkerModel cModel = new ChunkerModel(is);
		ChunkerME chunkerME = new ChunkerME(cModel);
		String result[] = chunkerME.chunk(whitespaceTokenizerLine, tags);
		for (String s : result)
			System.out.println(s);
		Span[] span = chunkerME.chunkAsSpans(whitespaceTokenizerLine, tags);
		for (Span s : span)
			System.out.println(s.toString());
		System.out.println("--------------5-------------");
	}

运行结果:

7 分析器

功能介绍:尝试解析器最简单的方法是在命令行工具。该工具仅用于演示和测试。请从我们网站上的英文分块解析器模型,并用以下命令启动解析工具。

代码实现:

	/**
	 * 6.分析器: Parser
	 * @deprecated Given this sentence: "Programcreek is a very huge and useful website.", parser can return the following:
	 * (TOP (S (NP (NN Programcreek) ) (VP (VBZ is) (NP (DT a) (ADJP (RB very) (JJ huge) (CC and) (JJ useful) ) ) ) (. website.) ) )
	 * (TOP
	 *     (S
	 *        (NP
	 *           (NN Programcreek)
	 *        )
	 *        (VP
	 *           (VBZ is)
	 *           (NP
	 *              (DT a)
	 *              (ADJP
	 *                   (RB very)
	 *                   (JJ huge)
	 *                   (CC and)
	 *                   (JJ userful)
	 *              )
	 *           )
	 *        )
	 *        (. website.)
	 *     )
	 * )
	 * @param str
	 */
	public static void Parse() throws InvalidFormatException, IOException {
		// http://sourceforge.net/apps/mediawiki/opennlp/index.php?title=Parser#Training_Tool
		InputStream is = new FileInputStream("./nlpbin/en-parser-chunking.bin");
		ParserModel model = new ParserModel(is);
		Parser parser = ParserFactory.create(model);
		String sentence = "Programcreek is a very huge and useful website.";
		opennlp.tools.parser.Parse topParses[] = ParserTool.parseLine(sentence, parser, 1);
		for (opennlp.tools.parser.Parse p : topParses)
			p.show();
		is.close();
	}

运行结果:

8 参考文献

1 官方教程Apache OpenNLP Developer Documentation

2 openNLP 中的各种模型

3 openNLP开源工具

4 维基百科:OpenNLP

驾驭文本第二章第二节

时间: 2024-08-28 19:02:45

OpenNLP:驾驭文本,分词那些事的相关文章

文本分词

分词的目的是将测试文本按一定的根据一定的规则进行分词处理[2]:便于提取文本的特征值,为文本提供特征值对比的词组.英文词组是以单词为单位,以空格为分隔,在分词上具有巨大的便利性,相对而言中文因为自身常以词语.短语.俗语等表现形式,因此中文分词具有很大的不确定性.我国经过多年的发展已经取得巨大的成就,出现了一系列具有较高的分词准确率和快速的分词系统.并且在1992年我国就制订了<信息处理用现代汉语分词规范>[9],旨在为中文信息处理提供一个国家标准化的使用标准.本文即采用张华平的NLPIR/IC

驾驭文本:文本的发现、组织和处理——互动出版网

这篇是计算机类的优质预售推荐>>>><驾驭文本:文本的发现.组织和处理> 编辑推荐 本书适合于互联网文本内容处理领域的开发人员阅读,也适合有志于加入这一领域的学生.从业人员阅读.即使对于已经从事多年文本处理研究和开发工作的人员来说,本书也不失为一种有益的补充性读物. 内容简介 文本处理是目前互联网内容应用(如搜索引擎.推荐引擎)的关键技术.本书涵盖了文本处理概念和技术的多个方面,包括文本预处理.搜索.字符串匹配.信息抽取.命名实体识别.分类.聚类.标签生成.摘要.问答等

Studio 爬虫 文本分词 化词云个性化设计

Studio 爬虫 文本分词 化词云个性化设计 分析步骤 设置工作目录 下载依赖包 加载依赖包 设置爬虫数据的URL地址 爬取数据 数据清洗 产看数据 制作词云 加载停用词表 去掉停用词 查看数据 生成Top100 词云 生成完整词云 个性化设计 setwd() install.packages("rjava") install.packages("wordcound") install.packages("wordcound2") librar

搜索引擎与网页文本分词的原理

对于SEO人员来说,自己工作的主要目标就是搜索引擎,所以深刻理解搜索引擎运行机制有助于我们针对搜索引擎进行优化,这就相当于两国交兵,必须要知道对方的虚实,再分析自己的优势,然后才能够一举进兵消灭对方,如果你还不知道对方的虚实,别人以逸待劳,那你失败是肯定的了!而在分析搜索引擎方面,知道其运行机制和分词技术是非常重要的一环! 搜索引擎工作的第一步:提取页面文字 首先就是抓取页面的文字,一般而言搜索引擎会把相关关键词的对应文字提取出来,还有就是meta标签等等,还有就是关键词和描述以及图片的ATL属

seo与python大数据结合给文本分词并提取高频词

最近研究seo和python如何结合,参考网上的一些资料,写的这个程序. 目的:分析某个行业(例如:圆柱模板)用户最关心的一些词,根据需求去自动调整TDK,以及栏目,内容页的规划 使用方法: 1.下载安装cygwin:http://www.cygwin.com/ 2.cygwin安装时别忘记安装curl,wget,iconv,lynx,dos2unix,Python等常用工具,特别是Python,这次主要就是用它了. 3.去下载jieba中文分词组件: 首选:https://github.com

驾驭文本部分内容总结

(1)词向量模型(vector space model),它将文档中的词项映射到$n$维线性空间. (2) 词项频率-逆文档频率(term frequncy-inverse document frequency)模型,简称TF-IDF.这种模型的本质是:文档中出现频繁(TF),但在整个文档集中出现相对不频繁(IDF)的词要比在大量文档中普遍存在的词更重要.它用来得到词项的权重,并由此构成词向量. (3)文本聚类.文本聚类就是用某种相似度计算方法将未标记文档分组,即将文档集中所有文档分成多簇,簇中

NLPIR_Init文本分词-总是初始化失败,false,Init ICTCLAS failed!

前段时间用这个分词用的好好的,突然间就总是初始化失败了: 网上搜了很多,但是不是我想要的答案,最终去了官网看了下:官网链接 发现哇,版本更新了啊,下载页面链接 麻利的下载好了最新的文档,一看压缩包名字:20161115173728_ICTCLAS2016分词系统下载包 现在是2016-11-17 11:49:08估计是刚更新的, 果然,将原来的Data文件夹删除之后,再将最新的Data文件夹放到原来的目录下就Ok了, 貌似初始化失败还有权限的问题什么的,,,遇上再总结,,, 初始化的时候还可能遇

文本向量化(理论篇)

本文介绍常见的文本表示模型,One-hot.词袋模型(BOW).TF-IDF.N-Gram和Word2Vec 一.离散表示 1.One-hot编码 One-hot编码是非常用的方法,我们可以用One-hot编码的方式将句子向量化,大致步骤为: 用构造文本分词后的字典 对词语进行One-hot编码 John likes to watch movies. Mary likes too John also likes to watch football games. 上面的两句话分词后可以构造一个字典

[大数据]-Elasticsearch5.3.1 IK分词,同义词/联想搜索设置

--题外话:最近发现了一些问题,一些高搜索量的东西相当一部分没有价值.发现大部分是一些问题的错误日志.而我是个比较爱贴图的.搜索引擎的检索会将我们的博文文本分词.所以图片内容一般是检索不到的,也就是说同样的问题最好是帖错误代码,日志,虽然图片很直观,但是并不利与传播.希望大家能够优化一部分博文的内容,这样有价值的东西传播量可能会更高. 本文主要是记录Elasticsearch5.3.1 IK分词,同义词/联想搜索设置,本来是要写fscrawler的多种格式(html,pdf,word...)数据