Python中文分词工具

2020/09/27 09:32

分词工具

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

1. jieba

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

支持三种分词模式:

精确模式,试图将句子最精确地切开,适合文本分析。

全模式,将句子中所有的可能成词的词语都扫描出来,速度非常快,但是不能解决歧义。

搜索引擎模式:在精确模式的基础上,对长词再次切分,提高召回率,适用于搜索引擎分词。

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

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

基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG)

采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合

对于未登录词,采用了基于汉字成词能力的 HMM 模型,使用了 Viterbi 算法

精确模式分词

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

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

结果:

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

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

全模式分词

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

result = jieba.lcut(string, cut_all=True)
print(len(result), '/'.join(result))

结果如下:

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

搜索引擎模式分词

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

result = jieba.lcut_for_search(string)
print(len(result), '/'.join(result))

结果如下:

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

另外可以加入自定义词典,如我们想把 日本和服 作为一个整体,可以把它添加到词典中,代码如下:

jieba.add_word('日本和服')
result = jieba.lcut(string)
print(len(result), '/'.join(result))

结果如下:

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

可以看到切分结果中,日本和服 四个字就作为一个整体出现在结果中了,分词数量比精确模式少了一个。

词性标注

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

words = pseg.lcut(string)
print(list(map(lambda x: list(x), words)))

运行结果:

[['这个', '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']]

关于词性的说明可以参考:https://gist.github.com/luw2007/6016931。

2. SnowNLP

SnowNLP: Simplified Chinese Text Processing,可以方便的处理中文文本内容,是受到了 TextBlob 的启发而写的,由于现在大部分的自然语言处理库基本都是针对英文的,于是写了一个方便处理中文的类库,并且和 TextBlob 不同的是,这里没有用 NLTK,所有的算法都是自己实现的,并且自带了一些训练好的字典。GitHub地址:https://github.com/isnowfy/snownlp。

分词

这里的分词是基于 Character-Based Generative Model 来实现的,论文地址:http://aclweb.org/anthology//Y/Y09/Y09-2047.pdf,我们还是以上面的例子说明,相关使用说明如下:

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

运行结果:

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

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

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

我们简单看一个实例:

print('Tags:', list(s.tags))
print('Sentiments:', s.sentiments)
print('Pinyin:', s.pinyin)

运行结果:

Tags: [('这个', '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.015678817603646866
Pinyin: ['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 链接:https://github.com/thunlp/THULAC-Python,具有中文分词和词性标注功能。THULAC具有如下几个特点:

能力强。利用集成的目前世界上规模最大的人工分词和词性标注中文语料库(约含5800万字)训练而成,模型标注能力强大。

准确率高。该工具包在标准数据集Chinese Treebank(CTB5)上分词的F1值可达97.3%,词性标注的F1值可达到92.9%,与该数据集上最好方法效果相当。

速度较快。同时进行分词和词性标注速度为300KB/s,每秒可处理约15万字。只进行分词速度可达到1.3MB/s。

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

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

运行结果:

[['这个', '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 链接:https://github.com/NLPIR-team/NLPIR,是由北京理工大学张华平博士研发的中文分词系统,经过十余年的不断完善,拥有丰富的功能和强大的性能。NLPIR是一整套对原始文本集进行处理和加工的软件,提供了中间件处理效果的可视化展示,也可以作为小规模数据的处理加工工具。主要功能包括:中文分词,词性标注,命名实体识别,用户词典、新词发现与关键词提取等功能。另外对于分词功能,它有 Python 实现的版本,GitHub 链接:https://github.com/tsroten/pynlpir。

使用方法如下:

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

运行结果如下:

[('这个', '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 链接:https://github.com/nltk/nltk。

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

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

结果:

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

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

使用方法如下:

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

运行结果:

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

可以看到这个分词效果还是不错的。

另外还可以进行词性标注,实体识别:

result = fool.pos_cut(string)
print(result)
_, ners = fool.analysis(string)
print(ners)

运行结果:

[[('这个', '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地址:https://github.com/HIT-SCIR/pyltp,另外运行的时候需要下载模型,模型还比较大,下载地址:http://ltp.ai/download.html。

示例代码如下:

from pyltp import Segmentor

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

运行结果:

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

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

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

免费直播

    精选课程 更多

    注册电脑版

    版权所有 2003-2020 广州环球青藤科技发展有限公司