天天看点

NLPIR中文分词系统之Java接口的使用NLPIR介绍Java接口使用步骤其它知识点发现的问题(针对JNI接口)

昨天接到经理的安排,让我做项目中的分词模块并介绍说可以使用中科院的ICTCLAS(最新版本改名为NLPIR)中文分词系统。于是自己花了一下午的时间来了解它,并试着搭建测试环境;这方面的资料比较少,幸好使用起来并不复杂,借助着搜索引擎的帮助,终于在官方文档以及网络博客的帮助下弄明白了其Java接口的使用方法。

参考资源:

  • http://blog.csdn.net/hellonlp/article/details/8768611
  • http://blog.csdn.net/hellonlp/article/details/8770838
  • http://cjp1989.iteye.com/blog/1856613

在此表示感谢。

NLPIR介绍

官方网站:http://ictclas.nlpir.org/

相关论坛:http://www.bigdatabbs.com/forum.php?mod=forumdisplay&fid=64

首先贴两段NLPIR官网的介绍。

关于NLPIR

NLPIR汉语分词系统(又名ICTCLAS2013),主要功能包括中文分词;词性标注;命名实体识别;用户词典功能;支持GBK编码、UTF8编码、BIG5编码。新增微博分词、新词发现与关键词提取;张华平博士先后倾力打造十余年,内核升级10次。

全球用户突破20万,先后获得了2010年钱伟长中文信息处理科学技术奖一等奖,2003年国际SIGHAN分词大赛综合第一名,2002年国内973评测综合第一名。

NLPIR简介

应各位ICTCLAS用户的要求,张华平博士正式发布ICTCLAS2013 版本,为了与以前工作进行大的区隔,并推广NLPIR自然语言处理与信息检索共享平台,从本版本开始,系统名称调整为NLPIR汉语分词系统。张博士先后倾力打造十余年,内核升级10次,全球用户突破20万,先后获得了2010年钱伟长中文信息处理科学技术奖一等奖,2003年国际SIGHAN分词大赛综合第一名,2002年国内973评测综合第一名。 NLPIR汉语分词系统(又名ICTCLAS2013),主要功能包括中文分词;词性标注;命名实体识别;用户词典功能;支持GBK编码、UTF8编码、BIG5编码。新增微博分词、新词发现与关键词提取;

访问http://ictclas.nlpir.org/(自然语言处理与信息检索共享平台),您可以获取NLPIR系统的最新版本,我们承诺:非商业应用永久免费,欢迎您关注张华平博士的新浪微博 @ICTCLAS张华平博士 交流。 

Java接口使用步骤

不理解NLPIR中文分词的原理,没什么可说的,这里仅记录一下其Java接口的使用步骤,留以后用。

1、准备资源

在官网下载页面中下载“NLPIR汉语分词系统(又名ICTCLAS2013版)下载包(u0416)”,该下载包包括以下内容:

  1. NLPIR汉语分词Windows下的演示系统、点击bin下面的exe即可;
  2. 数据文件: data文件夹
  3. windows下的库文件,lib/NLPIR.lib;bin/NLPIR.dll
  4. 示例程序: example下
  5. 头文件说明:include/NLPIR.h

该分词系统是用C/C++编写的,所以我们要在Java环境中使用还需要下载其提供的Java接口,我下载的是“NLPIR-ICTCLAS2013-Win-32-JNI(u0416)下载包”,如果用的JDK是64位的,需要下载对应的64位下载包。

这样我们得到了20130416090617_nlpir_ictclas2013_release.zip和20130416090224_Win-32bit-JNI-lib.zip两个zip压缩文件,将它们解压开以备使用。

NLPIR中文分词系统之Java接口的使用NLPIR介绍Java接口使用步骤其它知识点发现的问题(针对JNI接口)

2、创建Java项目

创建一个Java项目,开始向其中添加dll库和JNI接口。

首先在项目下创建一个文件夹file(随便你命名)并将20130416090617_nlpir_ictclas2013_release目录(由20130416090617_nlpir_ictclas2013_release.zip解压所得)中的Data目录拷贝到file目录;再将bin目录中的NLPIR.dll动态链接库放到项目目录下,与file目录同级。

然后将Win-32bit-JNI-lib目录(由20130416090224_Win-32bit-JNI-lib.zip解压所得)中的NLPIR_JNI.dll动态链接库拷贝到项目中,与NLPIR.dll平级;再将其中的kevin目录拷贝到项目的src中(这里就是NLPIR提供的Java接口,通过JNI来调用dll中的c/c++代码)。

最后将20130416090617_nlpir_ictclas2013_release目录中的test目录(存放的是一些测试文本文件,我们也可以自行准备测试文本文件)拷贝到项目中与file目录平级。

最终形成的项目结构如下所示:

NLPIR中文分词系统之Java接口的使用NLPIR介绍Java接口使用步骤其它知识点发现的问题(针对JNI接口)

3、写例子测试

写个简单的例子测试一下,这里处理的是采用UTF8编码的测试文件(需要注意测试文本文件的编码也要是UTF-8),GBK编码类似,只要程序与文本编码统一即可。

package com.zyh.nlpir;

import kevin.zhang.NLPIR;

public class TestUTF8 {

	public static void main(String[] args) {
		try {
			testUTF8();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	static void testUTF8() throws Exception {
		// 创建接口实例
		NLPIR nlpir = new NLPIR();
		// NLPIR_Init方法第二个参数设置0表示编码为GBK, 1表示UTF8编码(此处结论不够权威)
		if (!NLPIR.NLPIR_Init("./file/".getBytes("utf-8"), 1)) {
			System.out.println("NLPIR初始化失败...");
			return;
		}
		String temp = "每天的日报都记得要发送, 以配合经理掌握项目的进度情况.";
		// 要统一编码, 否则分词结果会产生乱码
		byte [] resBytes = nlpir.NLPIR_ParagraphProcess(temp.getBytes("UTF-8"), 1);
		System.out.println("分词结果: " + new String(resBytes, "UTF-8"));
		
		String utf8File = "./test/test-utf8.TXT";
		String utf8FileResult = "./test/test-utf8_result.TXT";
		nlpir.NLPIR_FileProcess(utf8File.getBytes("utf-8"), utf8FileResult.getBytes("utf-8"), 1);
		
		// 退出, 释放资源
		NLPIR.NLPIR_Exit();
	}
}
           

测试输出(关于输出内容的词性含义,可以参考前面下载包中的参考文档):

分词结果: 每天/r 的/ude1 日报/n 都/d 记得/v 要/v 发送/v ,/wd   以/p 配合/v 经理/n 掌握/v 项目/n 的/ude1 进度/n 情况/n ./wj 
           

文件输出test-utf8_result.TXT也正常;另外前面的下载包中也提供了一个示例程序,可以将其复制到项目中,加以修改后运行,该测试中有NLPIR新特性--提取新词、关键词识别等测试内容。

其它知识点

1、输出不带词性的分词结果

上面例子中不论输出到控制台还是文本文件中的分词结果都带有词性,如果我想输出不带词性的分词结果,需要将NLPIR_ParagraphProcess方法和NLPIR_FileProcess方法中的第二个参数设置为0:

byte [] resBytes = nlpir.NLPIR_ParagraphProcess(temp.getBytes("UTF-8"), 0);
System.out.println("分词结果: " + new String(resBytes, "UTF-8"));

String utf8File = "./test/test-utf8.TXT";
String utf8FileResult = "./test/test-utf8_result.TXT";
nlpir.NLPIR_FileProcess(utf8File.getBytes("utf-8"), utf8FileResult.getBytes("utf-8"), 0);
           

这样输出结果会如下所示:

分词结果: 每天 的 日报 都 记得 要 发送 ,   以 配合 经理 掌握 项目 的 进度 情况 . 
           

可以看到输出的词语之间仅用空格分隔并不带有词性。

2、添加用户词典

NLPIR支持用户词典,将上面的代码第23至26行部分改为如下代码:

String temp = "每天的日报都记得要发送, 以配合经理掌握项目的进度情况.";
// 要统一编码, 否则分词结果会产生乱码
nlpir.NLPIR_AddUserWord("进度情况 nl".getBytes("utf-8"));
byte [] resBytes = nlpir.NLPIR_ParagraphProcess(temp.getBytes("UTF-8"), 1);
System.out.println("分词结果: " + new String(resBytes, "UTF-8"));
           

这样我们将“进度情况”作为用户词典添加到NLPIR中,分词结果为:

分词结果: 每天/r 的/ude1 日报/n 都/d 记得/v 要/v 发送/v ,/wd   以/p 配合/v 经理/n 掌握/v 项目/n 的/ude1 进度情况/nl ./wj 
           

很明显,NLPIR将“进度情况”作为一个词语来分析,词性为我们设置的“nl”;添加用户词典时词语和词性需要用空格分隔开,这样添加的词语是临时添加的,只在这个程序中有效,程序关闭之后就无效了。如果在使用了上面的函数之后,再调用NLPIR_SaveTheUsrDic()方法,上面添加的词就完全的保存了,下次运行程序即使不导入这个词,NLPIR仍然会将这个词分出来;NLPIR_DelUsrWord方法与NLPIR_AddUserWord方法相反,是将用户添加的词语删除掉,改变同样是临时的,需要调用NLPIR_SaveTheUsrDic()方法来保存;如果用户词语比较多可以定义在文本文件中,然后调用NLPIR_ImportUserDict方法来将其一次性导入。

其它的接口请参照下载包中提供的接口说明文档中的JNI接口部分。

发现的问题(针对JNI接口)

其一、调用NLPIR_AddUserWord方法添加用户词典后,NLPIR_DelUsrWord方法将添加的词删掉,然后再不能添加该词了。