-
linux下使用CRF++结合java做的命名实体识别demo
- 命名实体识别自从MUC-6会议提出,经过多年的发展,现在已经成为一项成熟的技术。命名实体识别是诸多自然语言处理任务的前置条件。
- 命名实体识别的方法很多,今天我在这里写下我用CRF++做一个飞机名称识别的小demo。
系统:centos7.1
工具软件:JDK1.8.0、eclipse、gcc
1、CRF++下载和安装:
下载地址:https://sourceforge.net/projects/crfpp/files/crfpp/0.51/, 下载后安装:
进入解压的目录
./configure
make :make会报错,报不识别类型size_t ,在相应的文件加入size_t的头文件:stddef.h
su
make install
验证安装:crf_learn,出提示信息,安装成功。
2、CRF++预料训练:
CRF++自带4个样例,basenp、chunking、JapaneseNE、seg,做命名实体识别,最好的参照是JapaneseNE,它有4列:单词、词性、上下文连接词、标注。为了简便,在实验中选择单词、词性和标注做训练集(训练数据网上爬虫或者免费语料下载)。
我的训练数据格式:
更新 v O
了 ul O
机载 b O
电子 n O
系统 n O
, w O
用以 d O
替代 v O
陈旧 a O
的 uj O
轰 v B-N
教 v I-N
5 m I-N
、 w O
运 v B-N
教 v I-N
5 m I-N
、 w O
安 v B-N
- null I-N
24 m I-N
和 c O
安 v B-N
- null I-N
26 m I-N
教练 n O
型 k O
。 # O
模板解释见CRF++/doc,更深的原理待进一步学习。
生成model文件:命令参考/example/JapaneseNE/exec.sh 。参数详情见/doc。你也可以在java项目中调用ssh命名来执行。
3、CRF++编译为java可调用的so文件(win32为dll文件):
JNI,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)。此时需要将CRF++实现了JNI接口,我们可以不去关心jni的内部细节,只需将它编译。
编译工具要用到swig
安装命令: yum install swig
进入/swig目录,make
进入/java目录,make:会报错 jni.h、jni_md.h 缺少
输入命令:locate jni.h ,显示所在目录
输入命名:sudo scp /opt/jdk1.8.0_112/include/jni.h .
修改 CRFPP_warp.xx 中的#include jni.h> ——#include “jni.h”
make
生成CRFPP.jar 和 libCRFPP.so
4、java调用 so文件:
java调用见/java/test.java
有一点要注意:system.loadlibrary加载需要so文件在jvm指向的路径中,jvm路径可输出System.getProperty(“java.library.path”)获取。要将刚才生存的so文件软链接到jvm路径,ln -s 源路径 /usr/lib/libCRFPP.so 。调用要去掉lib和后缀,即System.loadLibrary(“CRFPP”);
tagger.add(“Confidence NN”);
tagger.add(“in IN”);
用分词工具词性分析,加入,我用的ANSJ。ansj_seg-3.7.3-all-in-one.jar就可搞定
代码
String text = “中国最新研制的空警-3000在上海机场试飞成功。”;
List term = ToAnalysis.parse(text);
new NatureRecognition(term).recognition();
for(int i = 0; i < term.size(); i++){
tagger.add(term.get(i).getName().toString()+" "+term.get(i).getNatureStr().toString());
}
5、结果:
String text = “中国最新研制的空警-3000在上海机场试飞成功。”;
中国 ns O
最新 a O
研制 v O
的 uj O
空警 nr B-N
- null I-N
3000 m I-N
在 p O
上海 ns O
机场 n O
试飞 v O
成功 a O
。 w O
注:第一次下载的是 CRF++0.54版本,编译的so文件,在测试的时候报错。
没有去深入了解JNI工作机制,然后下载了CRF++0.51版本,同样的步骤,测试成功。