中文分词原理及经常使用Python中文分词库介绍

原理

中文分词,即 Chinese Word Segmentation,即将一个汉字序列进行切分,获得一个个单独的词。表面上看,分词其实就是那么回事,但分词效果好很差对信息检索、实验结果仍是有很大影响的,同时分词的背后实际上是涉及各类各样的算法的。html

中文分词与英文分词有很大的不一样,对英文而言,一个单词就是一个词,而汉语是以字为基本的书写单位,词语之间没有明显的区分标记,须要人为切分。根据其特色,能够把分词算法分为四大类:git

  • 基于规则的分词方法
  • 基于统计的分词方法
  • 基于语义的分词方法
  • 基于理解的分词方法

下面咱们对这几种方法分别进行总结。github

基于规则的分词方法

这种方法又叫做机械分词方法、基于字典的分词方法,它是按照必定的策略将待分析的汉字串与一个“充分大的”机器词典中的词条进行匹配。若在词典中找到某个字符串,则匹配成功。该方法有三个要素,即分词词典、文本扫描顺序和匹配原则。文本的扫描顺序有正向扫描、逆向扫描和双向扫描。匹配原则主要有最大匹配、最小匹配、逐词匹配和最佳匹配。web

  • 最大匹配法(MM)。基本思想是:假设自动分词词典中的最长词条所含汉字的个数为 i,则取被处理材料当前字符串序列中的前 i 个字符做为匹配字段,查找分词词典,若词典中有这样一个 i 字词,则匹配成功,匹配字段做为一个词被切分出来;若词典中找不到这样的一个 i 字词,则匹配失败,匹配字段去掉最后一个汉字,剩下的字符做为新的匹配字段,再进行匹配,如此进行下去,直到匹配成功为止。统计结果代表,该方法的错误率 为 1/169。
  • 逆向最大匹配法(RMM)。该方法的分词过程与 MM 法相同,不一样的是从句子(或文章)末尾开始处理,每次匹配不成功时去掉的是前面的一个汉字。统计结果代表,该方法的错误率为 1/245。
  • 逐词遍历法。把词典中的词按照由长到短递减的顺序逐字搜索整个待处理的材料,一直到把所有的词切分出来为止。不论分词词典多大,被处理的材料多么小,都得把这个分词词典匹配一遍。
  • 设立切分标志法。切分标志有天然和非天然之分。天然切分标志是指文章中出现的非文字符号,如标点符号等;非天然标志是利用词缀和不构成词的词(包 括单音词、复音节词以及象声词等)。设立切分标志法首先收集众多的切分标志,分词时先找出切分标志,把句子切分为一些较短的字段,再用 MM、RMM 或其它的方法进行细加工。这种方法并不是真正意义上的分词方法,只是自动分词的一种前处理方式而已,它要额外消耗时间扫描切分标志,增长存储空间存放那些非 天然切分标志。
  • 最佳匹配法(OM)。此法分为正向的最佳匹配法和逆向的最佳匹配法,其出发点是:在词典中按词频的大小顺序排列词条,以求缩短对分词词典的检索时 间,达到最佳效果,从而下降分词的时间复杂度,加快分词速度。实质上,这种方法也不是一种纯粹意义上的分词方法,它只是一种对分词词典的组织方式。OM 法的分词词典每条词的前面必须有指明长度的数据项,因此其空间复杂度有所增长,对提升分词精度没有影响,分词处理的时间复杂度有所下降。

此种方法优势是简单,易于实现。但缺点有不少:匹配速度慢;存在交集型和组合型歧义切分问题;词自己没有一个标准的定义,没有统一标准的词集;不一样词典产生的歧义也不一样;缺少自学习的智能性。算法

基于统计的分词方法

该方法的主要思想:词是稳定的组合,所以在上下文中,相邻的字同时出现的次数越多,就越有可能构成一个词。所以字与字相邻出现的几率或频率能较好地反映成词的可信度。能够对训练文本中相邻出现的各个字的组合的频度进行统计,计算它们之间的互现信息。互现信息体现了汉字之间结合关系的紧密程度。当紧密程 度高于某一个阈值时,即可以认为此字组可能构成了一个词。该方法又称为无字典分词。bash

该方法所应用的主要的统计模型有:N 元文法模型(N-gram)、隐马尔可夫模型(Hiden Markov Model,HMM)、最大熵模型(ME)、条件随机场模型(Conditional Random Fields,CRF)等。微信

在实际应用中此类分词算法通常是将其与基于词典的分词方法结合起来,既发挥匹配分词切分速度快、效率高的特色,又利用了无词典分词结合上下文识别生词、自动消除歧义的优势。网络

基于语义的分词方法

语义分词法引入了语义分析,对天然语言自身的语言信息进行更多的处理,如扩充转移网络法、知识分词语义分析法、邻接约束法、综合匹配法、后缀分词法、特征词库法、矩阵约束法、语法分析法等。dom

  • 扩充转移网络法。该方法以有限状态机概念为基础。有限状态机只能识别正则语言,对有限状态机做的第一次扩充使其具备递归能力,造成递归转移网络 (RTN)。在RTN 中,弧线上的标志不只能够是终极符(语言中的单词)或非终极符(词类),还能够调用另外的子网络名字分非终极符(如字或字串的成词条件)。这样,计算机在 运行某个子网络时,就能够调用另外的子网络,还能够递归调用。词法扩充转移网络的使用, 使分词处理和语言理解的句法处理阶段交互成为可能,而且有效地解决了汉语分词的歧义。
  • 矩阵约束法。其基本思想是:先创建一个语法约束矩阵和一个语义约束矩阵, 其中元素分别代表具备某词性的词和具备另外一词性的词相邻是否符合语法规则, 属于某语义类的词和属于另外一词义类的词相邻是否符合逻辑,机器在切分时以之约束分词结果。

基于理解的分词方法

基于理解的分词方法是经过让计算机模拟人对句子的理解,达到识别词的效果。其基本思想就是在分词的同时进行句法、语义分析,利用句法信息和语义信息来处理歧义现象。它一般包括三个部分:分词子系统、句法语义子系统、总控部分。在总控部分的协调下,分词子系统能够得到有关词、句子等的句法和语义信息来对分词歧义进行判断,即它模拟了人对句子的理解过程。这种分词方法须要使用大量的语言知识和信息。目前基于理解的分词方法主要有专家系统分词法和神经网络分词法等。ide

  • 专家系统分词法。从专家系统角度把分词的知识(包括常识性分词知识与消除歧义切分的启发性知识即歧义切分规则)从实现分词过程的推理机中独立出来,使知识库的维护与推理机的实现互不干扰,从而使知识库易于维护和管理。它还具备发现交集歧义字段和多义组合歧义字段的能力和必定的自学习功能。
  • 神经网络分词法。该方法是模拟人脑并行,分布处理和创建数值计算模型工做的。它将分词知识所分散隐式的方法存入神经网络内部,经过自学习和训练修改内部权值,以达到正确的分词结果,最后给出神经网络自动分词结果,如使用 LSTM、GRU 等神经网络模型等。
  • 神经网络专家系统集成式分词法。该方法首先启动神经网络进行分词,当神经网络对新出现的词不能给出准确切分时,激活专家系统进行分析判断,依据知识库进行推理,得出初步分析,并启动学习机制对神经网络进行训练。该方法能够较充分发挥神经网络与专家系统两者优点,进一步提升分词效率。

以上即是对分词算法的基本介绍,接下来咱们再介绍几个比较实用的分词 Python 库及它们的使用方法。

分词工具

在这里介绍几个比较有表明性的支持分词的 Python 库,主要有:

1. jieba

专用于分词的 Python 库,GitHub:github.com/fxsjy/jieba,分词效果较好。

支持三种分词模式:

  • 精确模式,试图将句子最精确地切开,适合文本分析。
  • 全模式,将句子中全部的可能成词的词语都扫描出来,速度很是快,可是不能解决歧义。
  • 搜索引擎模式:在精确模式的基础上,对长词再次切分,提升召回率,适用于搜索引擎分词。

另外 jieba 支持繁体分词,支持自定义词典。

其使用的算法是基于统计的分词方法,主要有以下几种:

  • 基于前缀词典实现高效的词图扫描,生成句子中汉字全部可能成词状况所构成的有向无环图 (DAG)
  • 采用了动态规划查找最大几率路径, 找出基于词频的最大切分组合
  • 对于未登陆词,采用了基于汉字成词能力的 HMM 模型,使用了 Viterbi 算法

精确模式分词

首先咱们来看下精确模式分词,使用 lcut() 方法,相似 cut() 方法,其参数和 cut() 是一致的,只不过返回结果是列表而不是生成器,默认使用精确模式,代码以下:

1234import jiebastring = '这个把手该换了,我不喜欢日本和服,别把手放在个人肩膀上,工信处女干事每个月通过下属科室都要亲口交代24口交换机等技术性器件的安装工做'result = jieba.lcut(string)print(len(result), '/'.join(result))复制代码

结果:

1
38 这个/把手/该换/了/,/我/不/喜欢/日本/和服/,/别/把手/放在/我/的/肩膀/上/,/工信处/女干事/每个月/通过/下属/科室/都/要/亲口/交代/24/口/交换机/等/技术性/器件/的/安装/工做

可见分词效果仍是不错的。

全模式分词

使用全模式分词须要添加 cut_all 参数,将其设置为 True,代码以下:

12result = jieba.lcut(string, cut_all=True)print(len(result), '/'.join(result))复制代码

结果以下:

1
51 这个/把手/该换/了///我/不/喜欢/日本/和服///别/把手/放在/我/的/肩膀/上///工信处/处女/女干事/干事/每个月/月经/通过/下属/科室/都/要/亲口/口交/交代/24/口交/交换/交换机/换机/等/技术/技术性/性器/器件/的/安装/安装工/装工/工做

搜索引擎模式分词

使用搜索引擎模式分词须要调用 cut_for_search() 方法,代码以下:

12result = jieba.lcut_for_search(string)print(len(result), '/'.join(result))复制代码

结果以下:

1
42 这个/把手/该换/了/,/我/不/喜欢/日本/和服/,/别/把手/放在/我/的/肩膀/上/,/工信处/干事/女干事/每个月/通过/下属/科室/都/要/亲口/交代/24/口/交换/换机/交换机/等/技术/技术性/器件/的/安装/工做

另外能够加入自定义词典,如咱们想把 日本和服 做为一个总体,能够把它添加到词典中,代码以下:

123jieba.add_word('日本和服')result = jieba.lcut(string)print(len(result), '/'.join(result))复制代码

结果以下:

1
37 这个/把手/该换/了/,/我/不/喜欢/日本和服/,/别/把手/放在/我/的/肩膀/上/,/工信处/女干事/每个月/通过/下属/科室/都/要/亲口/交代/24/口/交换机/等/技术性/器件/的/安装/工做

能够看到切分结果中,日本和服 四个字就做为一个总体出如今结果中了,分词数量比精确模式少了一个。

词性标注

另外 jieba 还支持词性标注,能够输出分词后每一个词的词性,实例以下:

12words = pseg.lcut(string)print(list(map(lambda x: list(x), words)))复制代码

运行结果:

1
[['这个', 'r'], ['把手', 'v'], ['该', 'r'], ['换', 'v'], ['了', 'ul'], [',', 'x'], ['我', 'r'], ['不', 'd'], ['喜欢', 'v'], ['日本和服', 'x'], [',', 'x'], ['别', 'r'], ['把手', 'v'], ['放在', 'v'], ['我', 'r'], ['的', 'uj'], ['肩膀', 'n'], ['上', 'f'], [',', 'x'], ['工信处', 'n'], ['女干事', 'n'], ['每个月', 'r'], ['通过', 'p'], ['下属', 'v'], ['科室', 'n'], ['都', 'd'], ['要', 'v'], ['亲口', 'n'], ['交代', 'n'], ['24', 'm'], ['口', 'n'], ['交换机', 'n'], ['等', 'u'], ['技术性', 'n'], ['器件', 'n'], ['的', 'uj'], ['安装', 'v'], ['工做', 'vn']]

关于词性的说明能够参考:gist.github.com/luw2007/601…

2. SnowNLP

SnowNLP: Simplified Chinese Text Processing,能够方便的处理中文文本内容,是受到了 TextBlob 的启发而写的,因为如今大部分的天然语言处理库基本都是针对英文的,因而写了一个方便处理中文的类库,而且和 TextBlob 不一样的是,这里没有用 NLTK,全部的算法都是本身实现的,而且自带了一些训练好的字典。GitHub地址:github.com/isnowfy/sno…

分词

这里的分词是基于 Character-Based Generative Model 来实现的,论文地址:aclweb.org/anthology//…,咱们仍是以上面的例子说明,相关使用说明以下:

123456from snownlp import SnowNLP string = '这个把手该换了,我不喜欢日本和服,别把手放在个人肩膀上,工信处女干事每个月通过下属科室都要亲口交代24口交换机等技术性器件的安装工做's = SnowNLP(string)result = s.wordsprint(len(result), '/'.join(result))复制代码

运行结果:

1
40 这个/把手/该/换/了/,/我/不/喜欢/日本/和/服/,/别把手/放在/我/的/肩膀/上/,/工/信处女/干事/每个月/通过/下属/科室/都/要/亲口/交代/24/口/交换机/等/技术性/器件/的/安装/工做

通过观察,能够发现分词效果其实不怎么理想,和服 被分开了,工信处 也被分开了,女干事 也被分开了。

另外 SnowNLP 还支持不少功能,例如词性标注(HMM)、情感分析、拼音转换(Trie树)、关键词和摘要生成(TextRank)。

咱们简单看一个实例:

123print('Tags:', list(s.tags))print('Sentiments:', s.sentiments)print('Pinyin:', s.pinyin)复制代码

运行结果:

123Tags: [('这个', 'r'), ('把手', 'Ng'), ('该', 'r'), ('换', 'v'), ('了', 'y'), (',', 'w'), ('我', 'r'), ('不', 'd'), ('喜欢', 'v'), ('日本', 'ns'), ('和', 'c'), ('服', 'v'), (',', 'w'), ('别把手', 'ad'), ('放在', 'v'), ('我', 'r'), ('的', 'u'), ('肩膀', 'n'), ('上', 'f'), (',', 'w'), ('工', 'j'), ('信处女', 'j'), ('干事', 'n'), ('每个月', 'r'), ('通过', 'p'), ('下属', 'v'), ('科室', 'n'), ('都', 'd'), ('要', 'v'), ('亲口', 'd'), ('交代', 'v'), ('24', 'm'), ('口', 'q'), ('交换机', 'n'), ('等', 'u'), ('技术性', 'n'), ('器件', 'n'), ('的', 'u'), ('安装', 'vn'), ('工做', 'vn')]Sentiments: 0.015678817603646866Pinyin: ['zhe', 'ge', 'ba', 'shou', 'gai', 'huan', 'liao', ',', 'wo', 'bu', 'xi', 'huan', 'ri', 'ben', 'he', 'fu', ',', 'bie', 'ba', 'shou', 'fang', 'zai', 'wo', 'de', 'jian', 'bang', 'shang', ',', 'gong', 'xin', 'chu', 'nv', 'gan', 'shi', 'mei', 'yue', 'jing', 'guo', 'xia', 'shu', 'ke', 'shi', 'dou', 'yao', 'qin', 'kou', 'jiao', 'dai', '24', 'kou', 'jiao', 'huan', 'ji', 'deng', 'ji', 'shu', 'xing', 'qi', 'jian', 'de', 'an', 'zhuang', 'gong', 'zuo']复制代码

3. THULAC

THULAC(THU Lexical Analyzer for Chinese)由清华大学天然语言处理与社会人文计算实验室研制推出的一套中文词法分析工具包,GitHub 连接:github.com/thunlp/THUL…,具备中文分词和词性标注功能。THULAC具备以下几个特色:

  • 能力强。利用集成的目前世界上规模最大的人工分词和词性标注中文语料库(约含5800万字)训练而成,模型标注能力强大。
  • 准确率高。该工具包在标准数据集Chinese Treebank(CTB5)上分词的F1值可达97.3%,词性标注的F1值可达到92.9%,与该数据集上最好方法效果至关。
  • 速度较快。同时进行分词和词性标注速度为300KB/s,每秒可处理约15万字。只进行分词速度可达到1.3MB/s。

咱们用一个实例看一下分词效果:

123456import thulac string = '这个把手该换了,我不喜欢日本和服,别把手放在个人肩膀上,工信处女干事每个月通过下属科室都要亲口交代24口交换机等技术性器件的安装工做't = thulac.thulac()result = t.cut(string)print(result)复制代码

运行结果:

1
[['这个', 'r'], ['把手', 'n'], ['该', 'v'], ['换', 'v'], ['了', 'u'], [',', 'w'], ['我', 'r'], ['不', 'd'], ['喜欢', 'v'], ['日本', 'ns'], ['和服', 'n'], [',', 'w'], ['别把手', 'n'], ['放', 'v'], ['在', 'p'], ['我', 'r'], ['的', 'u'], ['肩膀', 'n'], ['上', 'f'], [',', 'w'], ['工信处', 'n'], ['女', 'a'], ['干事', 'n'], ['每个月', 'r'], ['通过', 'p'], ['下属', 'v'], ['科室', 'n'], ['都', 'd'], ['要', 'v'], ['亲口', 'd'], ['交代', 'v'], ['24', 'm'], ['口', 'q'], ['交换机', 'n'], ['等', 'u'], ['技术性', 'n'], ['器件', 'n'], ['的', 'u'], ['安装', 'v'], ['工做', 'v']]

4. NLPIR

NLPIR 分词系统,前身为2000年发布的 ICTCLAS 词法分析系统,GitHub 连接:github.com/NLPIR-team/…,是由北京理工大学张华平博士研发的中文分词系统,通过十余年的不断完善,拥有丰富的功能和强大的性能。NLPIR是一整套对原始文本集进行处理和加工的软件,提供了中间件处理效果的可视化展现,也能够做为小规模数据的处理加工工具。主要功能包括:中文分词,词性标注,命名实体识别,用户词典、新词发现与关键词提取等功能。另外对于分词功能,它有 Python 实现的版本,GitHub 连接:github.com/tsroten/pyn…

使用方法以下:

123456import pynlpir pynlpir.open()string = '这个把手该换了,我不喜欢日本和服,别把手放在个人肩膀上,工信处女干事每个月通过下属科室都要亲口交代24口交换机等技术性器件的安装工做'result = pynlpir.segment(string)print(result)
复制代码

运行结果以下:

1[('这个', 'pronoun'), ('把', 'preposition'), ('手', 'noun'), ('该', 'pronoun'), ('换', 'verb'), ('了', 'modal particle'), (',', 'punctuation mark'), ('我', 'pronoun'), ('不', 'adverb'), ('喜欢', 'verb'), ('日本', 'noun'), ('和', 'conjunction'), ('服', 'verb'), (',', 'punctuation mark'), ('别', 'adverb'), ('把', 'preposition'), ('手', 'noun'), ('放', 'verb'), ('在', 'preposition'), ('我', 'pronoun'), ('的', 'particle'), ('肩膀', 'noun'), ('上', 'noun of locality'), (',', 'punctuation mark'), ('工', 'noun'), ('信', 'noun'), ('处女', 'noun'), ('干事', 'noun'), ('每个月', 'pronoun'), ('通过', 'preposition'), ('下属', 'verb'), ('科室', 'noun'), ('都', 'adverb'), ('要', 'verb'), ('亲口', 'adverb'), ('交代', 'verb'), ('24', 'numeral'), ('口', 'classifier'), ('交换机', 'noun'), ('等', 'particle'), ('技术性', 'noun'), ('器件', 'noun'), ('的', 'particle'), ('安装', 'verb'), ('工做', 'verb')]复制代码

这里 把手 和 和服 也被分开了。

5. NLTK

NLTK,Natural Language Toolkit,是一个天然语言处理的包工具,各类多种 NLP 处理相关功能,GitHub 连接:github.com/nltk/nltk

可是 NLTK 对于中文分词是不支持的,示例以下:

12345from nltk import word_tokenize string = '这个把手该换了,我不喜欢日本和服,别把手放在个人肩膀上,工信处女干事每个月通过下属科室都要亲口交代24口交换机等技术性器件的安装工做'result = word_tokenize(string)print(result)复制代码

结果:

1['这个把手该换了,我不喜欢日本和服,别把手放在个人肩膀上,工信处女干事每个月通过下属科室都要亲口交代24口交换机等技术性器件的安装工做']复制代码

若是要用中文分词的话,可使用 FoolNLTK,它使用 Bi-LSTM 训练而成,包含分词、词性标注、实体识别等功能,同时支持自定义词典,能够训练本身的模型,能够进行批量处理。

使用方法以下:

12345import fool string = '这个把手该换了,我不喜欢日本和服,别把手放在个人肩膀上,工信处女干事每个月通过下属科室都要亲口交代24口交换机等技术性器件的安装工做'result = fool.cut(string)print(result)复制代码

运行结果:

1[['这个', '把手', '该', '换', '了', ',', '我', '不', '喜欢', '日本', '和服', ',', '别', '把', '手', '放', '在', '我', '的', '肩膀', '上', ',', '工信处', '女', '干事', '每个月', '通过', '下属', '科室', '都', '要', '亲', '口', '交代', '24', '口', '交换机', '等', '技术性', '器件', '的', '安装', '工做']]复制代码

能够看到这个分词效果仍是不错的。

另外还能够进行词性标注,实体识别:

1234result = fool.pos_cut(string)print(result)_, ners = fool.analysis(string)print(ners)复制代码

运行结果:

12[[('这个', 'r'), ('把手', 'n'), ('该', 'r'), ('换', 'v'), ('了', 'y'), (',', 'wd'), ('我', 'r'), ('不', 'd'), ('喜欢', 'vi'), ('日本', 'ns'), ('和服', 'n'), (',', 'wd'), ('别', 'd'), ('把', 'pba'), ('手', 'n'), ('放', 'v'), ('在', 'p'), ('我', 'r'), ('的', 'ude'), ('肩膀', 'n'), ('上', 'f'), (',', 'wd'), ('工信处', 'ns'), ('女', 'b'), ('干事', 'n'), ('每个月', 'r'), ('通过', 'p'), ('下属', 'v'), ('科室', 'n'), ('都', 'd'), ('要', 'v'), ('亲', 'a'), ('口', 'n'), ('交代', 'v'), ('24', 'm'), ('口', 'q'), ('交换机', 'n'), ('等', 'udeng'), ('技术性', 'n'), ('器件', 'n'), ('的', 'ude'), ('安装', 'n'), ('工做', 'n')]][[(12, 15, 'location', '日本')]]复制代码

6. LTP

语言技术平台(Language Technology Platform,LTP)是哈工大社会计算与信息检索研究中心历时十年开发的一整套中文语言处理系统。LTP制定了基于XML的语言处理结果表示,并在此基础上提供了一整套自底向上的丰富并且高效的中文语言处理模块(包括词法、句法、语义等6项中文处理核心技术),以及基于动态连接库(Dynamic Link Library, DLL)的应用程序接口、可视化工具,而且可以以网络服务(Web Service)的形式进行使用。

LTP 有 Python 版本,GitHub地址:github.com/HIT-SCIR/py…,另外运行的时候须要下载模型,模型还比较大,下载地址:ltp.ai/download.ht…

示例代码以下:

12345678from pyltp import Segmentor string = '这个把手该换了,我不喜欢日本和服,别把手放在个人肩膀上,工信处女干事每个月通过下属科室都要亲口交代24口交换机等技术性器件的安装工做'segmentor = Segmentor()segmentor.load('./cws.model')result = list(segmentor.segment(string))segmentor.release()print(result)复制代码

运行结果:

1
41 这个/把手/该/换/了/,/我/不/喜欢/日本/和服/,/别/把/手/放在/我/的/肩膀/上/,/工信/处女/干事/每个月/通过/下属/科室/都/要/亲口/交代/24/口/交换机/等/技术性/器件/的/安装/工做

能够发现 工信处、女干事 没有正确分开。

以上即是一些分词库的基本使用,我的比较推荐的有 jieba、THULAC、FoolNLTK。

参考来源


本资源首发于崔庆才的我的博客静觅: Python3网络爬虫开发实战教程 | 静觅

如想了解更多爬虫资讯,请关注个人我的微信公众号:进击的Coder

weixin.qq.com/r/5zsjOyvEZ… (二维码自动识别)

相关文章
相关标签/搜索