文章目录
- 自然语言处理系列十八
- 分词工具实战
- Java的HanLP分词
- 总结
自然语言处理系列十八
分词工具实战
分词工具有Java、Python、C++实现的,这里给大家推荐目前最流行的分词工具。CRF++是采用C++语言编写,但可以用Python来调用。HanLP是用Java编写的,也可以用Python调用。IK分词和mmseg4j分词也是用Java编写,经常集成在搜索引擎Solr和Elasticsearch里。下面分别进行讲解这几个开源分词包。
Java的HanLP分词
HanLP是一系列模型与算法组成的NLP工具包,使用Java语言开发,并支持Python语言调用,目标是普及自然语言处理在生产环境中的应用。HanLP具备功能完善、性能高效、架构清晰、语料时新、可自定义的特点。
HanLP提供下列功能:
中文分词:
HMM-Bigram(速度与精度最佳平衡;一百兆内存)
最短路分词、N-最短路分词
由字构词(侧重精度,全世界最大语料库,可识别新词;适合NLP任务)
感知机分词、CRF分词
词典分词(侧重速度,每秒数千万字符;省内存)
极速词典分词
所有分词器都支持:
索引全切分模式
用户自定义词典
兼容繁体中文
训练用户自己的领域模型
词性标注:
HMM词性标注(速度快)
感知机词性标注、CRF词性标注(精度高)
命名实体识别:
基于HMM角色标注的命名实体识别 (速度快)
中国人名识别、音译人名识别、日本人名识别、地名识别、实体机构名识别
基于线性模型的命名实体识别(精度高)
感知机命名实体识别、CRF命名实体识别
关键词提取:
TextRank关键词提取
自动摘要:
TextRank自动摘要
短语提取:
基于互信息和左右信息熵的短语提取
拼音转换:
多音字、声母、韵母、声调
简繁转换:
简繁分歧词(简体、繁体、臺灣正體、香港繁體)
文本推荐:
语义推荐、拼音推荐、字词推荐
依存句法分析:
基于神经网络的高性能依存句法分析器
基于ArcEager转移系统的柱搜索依存句法分析器
文本分类:
情感分析
文本聚类:
KMeans、Repeated Bisection、自动推断聚类数目k
word2vec:
词向量训练、加载、词语相似度计算、语义运算、查询、KMeans聚类
文档语义相似度计算
语料库工具:
部分默认模型训练自小型语料库,鼓励用户自行训练。所有模块提供训练接口,语料可参考98年人民日报语料库。
在提供丰富功能的同时,HanLP内部模块坚持低耦合、模型坚持惰性加载、服务坚持静态提供、词典坚持明文发布,使用非常方便。默认模型训练自全世界最大规模的中文语料库,同时自带一些语料处理工具,帮助用户训练自己的模型。支持自定义词典。
下面我们通过Java代码来演示HanLP的几种中文分词使用,代码如下所示:
【代码6.14】 PrefixSpanJob.scala
package com.chongdianleme.job;
import com.hankcs.hanlp.HanLP;
import com.hankcs.hanlp.seg.CRF.CRFSegment;
import com.hankcs.hanlp.seg.Dijkstra.DijkstraSegment;
import com.hankcs.hanlp.seg.NShort.NShortSegment;
import com.hankcs.hanlp.seg.Segment;
import com.hankcs.hanlp.seg.common.Term;
import com.hankcs.hanlp.tokenizer.IndexTokenizer;
import com.hankcs.hanlp.tokenizer.NLPTokenizer;
import com.hankcs.hanlp.tokenizer.SpeedTokenizer;
import com.hankcs.hanlp.tokenizer.StandardTokenizer;
import java.util.List;
/**
* Created by 充电了么App - 陈敬雷
* 充电了么App官网:http://chongdianleme.com/
* 充电了么App - 专注上班族职业技能提升充电学习的在线教育平台
* HanLP中文分词功能演示,开源地址:https://github.com/hankcs/HanLP
*/
public class HanLPDemo {
public static void main(String[] args) {
segment();//常用默认分词:HanLP.segment
standardSegment();//标准分词:StandardTokenizer.segment
NLPSegment();// NLP分词
indexTokenizerSegment();//索引分词
nShortSegment();//N-最短路径分词
CRFSegment();//CRF分词
highSpeedSegment();//极速词典分词
}
/**
*1.常用默认分词:HanLP.segment
* HanLP对词典的数据结构进行了长期的优化,可以应对绝大多数场景。哪怕HanLP的词典上百兆也无需担心,因为在内存中被精心压缩过。
* 如果内存非常有限,请使用小词典。HanLP默认使用大词典,同时提供小词典。全部词典和模型都是惰性加载的,不使用的模型相当于不存在,可以自由删除。
* HanLP.segment其实是对StandardTokenizer.segment标准分词的包装,和标准分词的结果是一样的。
*/
public static void segment() {
String s = "分布式机器学习实战(人工智能科学与技术丛书)深入浅出,逐步讲解分布式机器学习的框架及应用配套个性化推荐算法系统、人脸识别、对话机器人等实战项目。";
List<Term> termList =HanLP.segment(s);
System.out.println(termList);
//输出结果如下:分词结果包含词性,比如分布式的词性b代表区别词,机器学习的词性gi代表计算机相关词汇,实战的词性n代表名称,
// 后面每个词都返回了对应的词性,这里不一一举例,下章我们会单独讲词性标注,列出所有的词性表。
//[分布式/b, 机器学习/gi, 实战/n, (/w, 人工智能/n, 科学/n, 与/p, 技术/n, 丛书/n, )/w, 深入浅出/i, ,/w, 逐步/d, 讲解/v, 分布式/b, 机器学习/gi, 的/uj, 框架/n, 及/c, 应用/vn, 配套/a, 个性化/v, 推荐/v, 算法/n, 系统/n, 、/w, 人脸/n, 识别/v, 、/w, 对话/vn, 机器人/n, 等/u, 实战/n, 项目/n, 。/w]
}
/**
*2.标准分词:StandardTokenizer.segment
* HanLP中有一系列“开箱即用”的静态分词器,以Tokenizer结尾,在接下来的例子中会继续介绍。
* HanLP.segment其实是对StandardTokenizer.segment的包装。
* 分词结果包含词性,每个词性的意思下章详细讲解。
*/
public static void standardSegment() {
String s = "分布式机器学习实战(人工智能科学与技术丛书)深入浅出,逐步讲解分布式机器学习的框架及应用配套个性化推荐算法系统、人脸识别、对话机器人等实战项目。";
List<Term> termList = StandardTokenizer.segment(s);
System.out.println(termList);
termList = HanLP.segment(s);
//输出结果如下:可以看到和上面的HanLP.segment结果是一样的。
//[分布式/b, 机器学习/gi, 实战/n, (/w, 人工智能/n, 科学/n, 与/p, 技术/n, 丛书/n, )/w, 深入浅出/i, ,/w, 逐步/d, 讲解/v, 分布式/b, 机器学习/gi, 的/uj, 框架/n, 及/c, 应用/vn, 配套/a, 个性化/v, 推荐/v, 算法/n, 系统/n, 、/w, 人脸/n, 识别/v, 、/w, 对话/vn, 机器人/n, 等/u, 实战/n, 项目/n, 。/w]
}
/**
*3.NLP分词:NLPTokenizer.segment
NLP分词NLPTokenizer会执行词性标注和命名实体识别,由结构化感知机序列标注框架支撑。默认模型训练自9970万字的大型综合语料库,是已知范围内全世界最大的中文分词语料库。
语料库规模决定实际效果,面向生产环境的语料库应当在千万字量级。用户可以在自己的语料上训练新模型以适应新领域、识别新的命名实体。
*/
public static void NLPSegment() {
String s = "分布式机器学习实战(人工智能科学与技术丛书)深入浅出,逐步讲解分布式机器学习的框架及应用配套个性化推荐算法系统、人脸识别、对话机器人等实战项目。";
System.out.println(NLPTokenizer.segment(s));
//输出结果如下:
//[分布式/b, 机器学习/gi, 实战/n, (/w, 人工智能/n, 科学/n, 与/p, 技术/n, 丛书/n, )/w, 深入浅出/i, ,/w, 逐步/d, 讲解/v, 分布式/b, 机器学习/gi, 的/uj, 框架/n, 及/c, 应用/vn, 配套/a, 个性化/v, 推荐/v, 算法/n, 系统/n, 、/w, 人脸/n, 识别/v, 、/w, 对话/vn, 机器人/n, 等/u, 实战/n, 项目/n, 。/w]
}
/**
*4.索引分词:IndexTokenizer.segment
索引分词IndexTokenizer是面向搜索引擎的分词器,能够对长词全切分,另外通过term.offset可以获取单词在文本中的偏移量。
任何分词器都可以通过基类Segment的enableIndexMode方法激活索引模式。
*/
public static void indexTokenizerSegment() {
String s = "分布式机器学习实战(人工智能科学与技术丛书)深入浅出,逐步讲解分布式机器学习的框架及应用配套个性化推荐算法系统、人脸识别、对话机器人等实战项目。";
List<Term> termList = IndexTokenizer.segment(s);
for (Term term : termList)
{
System.out.println(term + " [" + term.offset + ":" + (term.offset + term.word.length()) + "]");
}
//输出结果如下:
/**
分布式/b [0:3]
分布/v [0:2]
机器学习/gi [3:7]
机器/n [3:5]
学习/v [5:7]
实战/n [7:9]
(/w [9:10]
人工智能/n [10:14]
人工/n [10:12]
智能/n [12:14]
科学/n [14:16]
与/p [16:17]
技术/n [17:19]
丛书/n [19:21]
)/w [21:22]
深入浅出/i [22:26]
深入/v [22:24]
,/w [26:27]
逐步/d [27:29]
讲解/v [29:31]
分布式/b [31:34]
分布/v [31:33]
机器学习/gi [34:38]
机器/n [34:36]
学习/v [36:38]
的/uj [38:39]
框架/n [39:41]
及/c [41:42]
应用/vn [42:44]
配套/a [44:46]
个性化/v [46:49]
个性/n [46:48]
推荐/v [49:51]
算法/n [51:53]
系统/n [53:55]
、/w [55:56]
人脸/n [56:58]
识别/v [58:60]
、/w [60:61]
对话/vn [61:63]
机器人/n [63:66]
机器/n [63:65]
等/u [66:67]
实战/n [67:69]
项目/n [69:71]
。/w [71:72]
*/
}
/**
* 5.N-最短路径分词:nShortSegment.seg
N最短路分词器NShortSegment比最短路分词器慢,但是效果稍微好一些,对命名实体识别能力更强。
一般场景下最短路分词的精度已经足够,而且速度比N最短路分词器快几倍,请酌情选择。
*/
public static void nShortSegment() {
String s = "分布式机器学习实战(人工智能科学与技术丛书)深入浅出,逐步讲解分布式机器学习的框架及应用配套个性化推荐算法系统、人脸识别、对话机器人等实战项目。";
Segment nShortSegment = new NShortSegment().enableCustomDictionary(false).enablePlaceRecognize(true).enableOrganizationRecognize(true);
Segment shortestSegment = new DijkstraSegment().enableCustomDictionary(false).enablePlaceRecognize(true).enableOrganizationRecognize(true);
System.out.println("N-最短分词:" + nShortSegment.seg(s) + "\n最短路分词:" + shortestSegment.seg(s));
//输出结果如下:
//N-最短分词:[分布式/b, 机器/n, 学习/v, 实战/n, (/w, 人工智能/n, 科学/n, 与/p, 技术/n, 丛书/n, )/w, 深入浅出/i, ,/w, 逐步/d, 讲解/v, 分布式/b, 机器/n, 学习/v, 的/uj, 框架/n, 及/c, 应用/vn, 配套/a, 个性化/v, 推荐/v, 算法/n, 系统/n, 、/w, 人脸/n, 识别/v, 、/w, 对话/vn, 机器人/n, 等/u, 实战/n, 项目/n, 。/w]
//最短路分词:[分布式/b, 机器/n, 学习/v, 实战/n, (/w, 人工智能/n, 科学/n, 与/p, 技术/n, 丛书/n, )/w, 深入浅出/i, ,/w, 逐步/d, 讲解/v, 分布式/b, 机器/n, 学习/v, 的/uj, 框架/n, 及/c, 应用/vn, 配套/a, 个性化/v, 推荐/v, 算法/n, 系统/n, 、/w, 人脸/n, 识别/v, 、/w, 对话/vn, 机器人/n, 等/u, 实战/n, 项目/n, 。/w]
}
/**
*6.CRF分词:CRFSegment
CRF对新词有很好的识别能力,但是开销较大。
*/
public static void CRFSegment() {
String s = "分布式机器学习实战(人工智能科学与技术丛书)深入浅出,逐步讲解分布式机器学习的框架及应用配套个性化推荐算法系统、人脸识别、对话机器人等实战项目。";
Segment crfSegment = new CRFSegment();
System.out.println(crfSegment.seg(s));
}
/**
*7.极速词典分词:SpeedTokenizer.segment
极速分词是词典最长分词,速度极其快,精度一般。在i7-6700K上跑出了4500万字每秒的速度。
*/
public static void highSpeedSegment() {
String s = "分布式机器学习实战(人工智能科学与技术丛书)深入浅出,逐步讲解分布式机器学习的框架及应用配套个性化推荐算法系统、人脸识别、对话机器人等实战项目。";
System.out.println(SpeedTokenizer.segment(s));
long start = System.currentTimeMillis();
int pressure = 100;
for (int i = 0; i < pressure; ++i)
{
SpeedTokenizer.segment(s);
}
double costTime = (System.currentTimeMillis() - start) / (double)1000;
System.out.printf("分词速度:%.2f字每秒", s.length() * pressure / costTime);
}
}