分词,难在哪里?科普+解决方案!

题图:by Lucas Davies前端

1、前言

分词,我想是大多数大前端开发人员,都不会接触到的一个概念。这个不影响咱们了解它,毕竟咱们要多方向发展。今天就来简单介绍一些分词,我尽可能用简介的语言来描述这个概念,而且最后再提供一个解决方案,但愿对你有帮助。java

分词简单来说就是把一句话,按照词义,切分红一个个单独的词。这么说可能没什么感受,先看看它适用的场景。分词是文本挖掘的基础,一般会用于天然语言处理、分词搜索、推荐等等领域。python

2、分词的原理和算法

2.1 什么是分词

先理解一下分词的概念。nginx

分词就是将连续的字序列按照必定的规范从新组合成词序列的过程。在英文中,单词之间会以空格做为分割符,将词与词之间进行分割,可是对于中文,没有一个显式的分割符。git

正是由于缺少这种显式的分割符,致使咱们对中文中的词,进行分割的时候会出现不少的误差。github

2.2 分词的算法

中文分词有难度,不过也有成熟的解决方案。现有的分词算法,大概可分为三类:算法

  • 基于字符串匹配的分词算法
  • 基于理解的分词算法
  • 基于统计的分词算法

1. 基于字符串匹配的分词算法小程序

这种分词方法,又叫机械分词算法,它会提早维护一个大的字典,而后将句子和字典中的词进行匹配,若匹配成功,则能够进行分词处理api

固然,它实际上会更复杂一些,由于当字典足够大的时候,就又涉及到不一样的匹配算法,这里就不展开讲了。一般会基于 Trie 树结构,来实现高效的词图扫描。缓存

2. 基于理解的分词算法

这种分词方法,经过让计算机,模拟人对句子的理解,达到识别词组的效果。其基本思想是在分词的同事进行句法、语义的分析,利用句法和语义信息来处理歧义现象

它一般会包含三部分:分词子系统、句法语义子系统、总控部分。在总控部分的协调下,分词子系统能够得到有关词、句子等的句法和语义信息,来对分词歧义进行判断,即它模拟了人对句子的理解过程。因为汉语语言知识的笼统、复杂性,难以将各类语言信息组织成机器可直接读取的形式,所以目前基于理解的分词系统还处在试验阶段。

3. 基于统计的分词算法

给出大量已经分词的文本,利用统计机器学习模型学习词语切分的规律(称为训练),从而实现对未知文本的切分。

随着大规模语料库的创建,统计机器学习方法的研究和发展,基于统计的中文分词方法渐渐成为了主流方法。

2.3 分词的诉求

虽然分词的算法,讲解起来很简单,可是从现有的经验来看,几乎是不存在通用且效果很是好的分词系统。

每一个领域,都有其独特的词汇,这很难经过有限的训练数据,捕捉到全部的语言特征。例如:经过人民日报训练的分词系统,在网络玄幻小说上,分词的效果就不会好。

这是必然的,在分词系统中,没有银弹。

不一样的场景,对分词的要求也差别很大,一般能够从两个维度进行区分:分词速度、分词准确性

例如分词搜索,对速度要求就高于准确性的要求。而一些问答系统中,则须要对文本实现较深的理解,要求准确性高于速度要求。

不一样的领域,不一样的使用场景,对分词的要求是不一样的,因此咱们不能片面的去理解分词的准确率。而且随着新词的增长,训练数据的变化,分词的准确率也是在波动的。这也是为何,如今吹嘘分词准确率的公司愈来愈少的缘由。

2.4 分词的解决方案

分词是能够解决实际问题的功能,通过这么长时间的反复迭代更新,市面上一家产生了一批有特点的分词系统。例如:IK、Jieba、Ansj、Hanlp、Stanford分词 等等。

有兴趣能够一个个了解,接下来就其中的一个开源库 Jieba,进行讲解。

3、jieba

3.1 jieba 的优势

jieba 是开源的,号称是 Python 中,最好的中文分词组件。而且是基于 MIT 的协议,使用起来无后顾之忧。

jieba 使用起来也很是的简单,几行代码就能够实现分词调用和词性标注,并且速度还不错。

它内部维护了一个词典,是根据人民日报分析得到,在超出词典以外的新词,会基于 HMM 模型进行识别。

它提供三种分词模式:精准模式、全模式、搜索模式。全模式是找到全部可能的词语,搜索模式是在精确模式的基础上对长词进行切分,提升分割率。

在分词的速度上,精确模式能达到 400KB/s,全模式下能达到 1.5MB/s。同时除了 Python 版本以外,还有不一样的人基于 Python 版的 jieba ,扩展出多种语言实现,包括:JavaScript、Java、Golang、R、PHP 等。

jieba 的使用

jieba 的代码对 Python 2/3 均兼容,在使用以前,须要经过命令 pip install jieba 或者 pip3 install jieba 进行安装。

具体 Api,就不展开讲了,有兴趣能够去查看 Github 上的文档(文末有地址)。

这里提供一个简单的代码示例,来感觉一下 jieba 的方便与强大。

# encoding=utf-8
import jieba

seg_list = jieba.cut("我来到北京清华大学", cut_all=True)
print("Full Mode: " + "/ ".join(seg_list))  # 全模式

seg_list = jieba.cut("我来到北京清华大学", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list))  # 精确模式

seg_list = jieba.cut("他来到了网易杭研大厦")  # 默认是精确模式
print(", ".join(seg_list))

seg_list = jieba.cut_for_search("小明硕士毕业于中国科学院计算所,后在日本京都大学深造")  # 搜索引擎模式
print(", ".join(seg_list))
复制代码

输出的结果:

【全模式】: 我/ 来到/ 北京/ 清华/ 清华大学/ 华大/ 大学

【精确模式】: 我/ 来到/ 北京/ 清华大学

【新词识别】:他, 来到, 了, 网易, 杭研, 大厦    (此处,“杭研”并无在词典中,可是也被Viterbi算法识别出来了)

【搜索引擎模式】: 小明, 硕士, 毕业, 于, 中国, 科学, 学院, 科学院, 中国科学院, 计算, 计算所, 后, 在, 日本, 京都, 大学, 日本京都大学, 深造
复制代码

前面也提到,jieba 自身维护了一个词组的字典,若是自身需求上有专有名词须要拆分,还能够经过 jieba.Tokenizer(dictionary=DEFAULT_DICT) 自定义一个字典信息。

3.2 jieba 的分词算法

匹配的算法,提及来就复杂了,这里就简单介绍一下 jiaba 分词匹配的原理。

首先,jieba 分词已经自带了一个 dict.txt 的词典,里面有 2w 多个词条,包括出现的次数和词性,这是做者本身基于人民日报为主的资料,训练的出来的。

jieba 会先将这个词典中的数据,放到一个 Trie 树中,Trie 树是有名的前缀树,当一个词语的前面几个字同样的时候,就标识他们具备相同的前缀,就可使用 Trie 数来存储,具备查找速度快的优点。

其次,在须要对句子进行分词的时候,再根据前面生成的 Trie 数,生成有向无环图(DAG),这一步的意义在于,消除分词中的歧义,提升切分准确度,找出这句话中,全部可能的词。

到这一步,基本上就完成了,全部字典中记录的词,进行分词的过程。

可是若是你把 dict.txt 这个字典删除,jieba 依然能够进行分词,只是拆分出来的词,大部分的长度为 2。这是由于,对于未在字典中收录的词,基于隐马尔科夫模型(HMM)来预测分词,使用的是 Viterbi 算法。

HMM 模型中,将中文词汇按照 BEMS 四个状态来标记, B 是开始 begin 位置, E 是 end, 是结束位置, M 是 middle, 是中间位置, S 是 singgle, 单独成词的位置, 没有前, 也没有后. 也就是说, 他采用了状态为(B,E,M,S)这四种状态来标记中文词语, 好比北京能够标注为 BE, 即 北/B 京/E, 表示北是开始位置, 京是结束位置, 中华民族能够标注为 BMME , 就是开始, 中间, 中间, 结束.

做者经过对大量语料的训练,获得了 finalseg 目录下的训练结果,有兴趣能够自行研究。

到这里基本上就清晰了,jieba 分词的过程主要有如下三步:

  1. 加载 dict.txt 字典,生成 Trie 树。
  2. 对待分词的句子,经过 Trie 树,生成 DAG 图,匹配出全部可能的词。
  3. 再使用 HMM 模型,将字典中未收录的词,匹配出来。

这就是 jieba 分词的执行过程。

4、jieba(Java or Android)

4.1 Java 版的 jieba

jieba 发展到如今,已经支持众多的版本。Java 版并不是原做者开发,而是 hanban 参考原做者的分词原理,进行开发的。

不过 Java 版并无原版 Python 版本那么强大,作了部分阉割,例如关键词提取就没有实现。

有兴趣能够直接去看 Github : https://github.com/huaban/jieba-analysis/

1. 引入依赖(稳定版)

<dependency>
  <groupId>com.huaban</groupId>
  <artifactId>jieba-analysis</artifactId>
  <version>1.0.2</version>
</dependency>
复制代码

2. 如何使用

@Test
public void testDemo() {
    JiebaSegmenter segmenter = new JiebaSegmenter();
    String[] sentences =
        new String[] {"这是一个伸手不见五指的黑夜。我叫孙悟空,我爱北京,我爱Python和C++。""我不喜欢日本和服。""雷猴回归人间。",
                      "工信处女干事每个月通过下属科室都要亲口交代24口交换机等技术性器件的安装工做""结果婚的和还没有结过婚的"};
    for (String sentence : sentences) {
        System.out.println(segmenter.process(sentence, SegMode.INDEX).toString());
    }
}
复制代码

3. 性能评估

做者在测试机上进行测试,配置为:

Processor 2 Intel(R) Pentium(R) CPU G620 @ 2.60GHz
Memory:8GB
复制代码

测试结果还算理想,单线程,对测试文本逐行分词,并循环调用上万次的效率分析。

循环调用一万次
第一次测试结果:
time elapsed:12373, rate:2486.986533kb/s, words:917319.94/s
第二次测试结果:
time elapsed:12284, rate:2505.005241kb/s, words:923966.10/s
第三次测试结果:
time elapsed:12336, rate:2494.445880kb/s, words:920071.30/s

循环调用2万次
第一次测试结果:
time elapsed:22237, rate:2767.593144kb/s, words:1020821.12/s
第二次测试结果:
time elapsed:22435, rate:2743.167762kb/s, words:1011811.87/s
第三次测试结果:
time elapsed:22102, rate:2784.497726kb/s, words:1027056.34/s
统计结果:词典加载时间1.8s左右,分词效率每秒2Mb多,近100万词。

2 Processor Intel(R) Core(TM) i3-2100 CPU @ 3.10GHz
12G 测试效果
time elapsed:19597, rate:3140.428063kb/s, words:1158340.52/s
time elapsed:20122, rate:3058.491639kb/s, words:1128118.44/s
复制代码

4.2 在 Android 下使用 jieba

jieba(Java)版本,自己也是自带词典的,因此在 Android 下引入,会增大 Apk 的体积,这没有什么很好的规避方法。并且由于设备的配置,还会影响到分词的效率。

不过若是非要使用在 Android 设备上,例如对搜索词进行一个预处理,也是能够的。

jieba(java) 使用 maven 管理,因此须要 Gradle 简单配置一下,让其支持。

1. 配置 build.gradle

repositories {
    google()
    jcenter()
    mavenCentral()
}
复制代码

2. 引入依赖

api 'com.huaban:jieba-analysis:1.0.2'
复制代码

引入以后,使用细节就没什么好说的了,和 Java 版本无差异。

参考:

https://github.com/fxsjy/jieba

https://github.com/huaban/jieba-analysis/

https://blog.csdn.net/John_xyz/article/details/54645527

http://www.infoq.com/cn/articles/nlp-word-segmentation


公众号后台回复成长『成长』,将会获得我准备的学习资料,也能回复『加群』,一块儿学习进步;你还能回复『提问』,向我发起提问。

推荐阅读:

写做是核心竞争力 | Google 工程师解密“猜画小歌” | 图解:HTTP 范围请求 | Android P 适配经验 | 技术创业选择清单 | HTTP传输编码 | 什么正在消耗你? | HTTP 内容编码 | 图解 HTTP 缓存 | 聊聊 HTTP 的 Cookie | 辅助模式实战 | Accessibility 辅助模式 | 小程序 Flex 布局 | 好的 PR 让你更靠谱 | 密码管理之道

相关文章
相关标签/搜索