vlambda博客
学习文章列表

NLP预备:jieba 中文分词入门(上)

NLP预备:jieba 中文分词入门(上)

因为对NLP(自然语言处理)来说,分词是非常重要的重要的工作,所以我希望通过本文对于jieba模块的基本语法和使用方式通过实例进行细介绍。

简介

分词有下面几种方法:

  1. 基于词典:基于字典、词库匹配的分词方法;(字符串匹配、机械分词法)
  2. 基于统计:基于词频度统计的分词方法;
  3. 基于规则:基于知识理解的分词方法。

那么为什么要使用 jieba 来对中文进行分词呢?中文分词和英文分词有很大区别么?

  • jieba 支持 3 种分词模式:
  • 精确模式,试图将句子最精确地切开,适合文本分析;

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

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

  • 支持繁体分词
  • 支持自定义词典

中文分词特点

  1. 词是最小的能够独立活动的有意义的语言成分

  2. 汉语是以字位单位,词与词之间没有空格之类的标志指示词的边界

  3. 分词问题为中文文本处理的基础性工作,准确有效的分词结果会极其有助于后续的文本分析

中文分词的难点

  1. 分词规范,词的定义还不明确

  2. 歧义切分问题,交集型切分问题,多义组合型切分歧义等 入学的和还没入学的 => 入学/的/和/还没/入学/的

  3. 未登录词问题有两种解释:一是已有的词表中没有收录的词,二是已有的训练语料中未曾出现过的词,第二种含义中未登录词又称OOV(Out of Vocabulary)。对于大规模真实文本来说,未登录词对于分词的精度的影响远超歧义切分。一些网络新词,自造词一般都属于这些词。

安装

Anaconda cmd中键入 pip install jieba即可

或者使用清华镜像,代码如下:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple jieba

小试牛刀

# 引用jieba所有模块
from jieba import *

content = '工信处女干事每月经过下属科室都要亲口交代24口交换机等技术性器件的安装工作'

cut与lcut

# 1. 使用cut分词,返回一个迭代器,可使用 for 循环来获得分词后得到的每一个词语(unicode)

sep1 = cut(content,cut_all=False)
print("【精确模式】:" + "/".join(sep1))  

sep2 = cut(content,cut_all=True)
print("【全模式】:" + "/".join(sep2))   

【精确模式】:工信处/女干事/每月/经过/下属/科室/都/要/亲口/交代/24/口/交换机/等/技术性/器件/的/安装/工作

【全模式】:工信处/处女/女干事/干事/每月/月经/经过/下属/科室/都/要/亲口/口交/交代/24/口交/交换/交换机/换机/等/技术/技术性/性器/器件/的/安装/安装工/装工/工作

emmmm,通过改变参数cut_all的布林值可以改变分词的方式,全模式会把句子中所有的词组进行解析,不会考虑顺序问题,比如这里的工信处/女干事被分解为了工信处/处女/女干事/干事

# 2. 使用lcut分词直接返回列表

sep3 = lcut(content,cut_all=False)
print("【精确模式】:" , sep3)  

sep4 = lcut(content,cut_all=True)
print("【全模式】:" , sep4) 

【精确模式】:['工信处', '女干事', '每月', '经过', '下属', '科室', '都', '要', '亲口', '交代', '24', '口', '交换机', '等', '技术性', '器件', '的', '安装', '工作']

【全模式】:['工信处', '处女', '女干事', '干事', '每月', '月经', '经过', '下属', '科室', '都', '要', '亲口', '口交', '交代', '24', '口交', '交换', '交换机', '换机', '等', '技术', '技术性', '性器', '器件', '的', '安装', '安装工', '装工', '工作']

搜索引擎模式

sep5 = cut_for_search(content)
print("【搜索引擎模式--generator】:"''.join(sep5))

sep6 = lcut_for_search(content)
print("【返回列表】:" ,sep6)

【搜索引擎模式--generator】:工信处/干事/女干事/每月/经过/下属/科室/都/要/亲口/交代/24/口/交换/换机/交换机/等/技术/技术性/器件/的/安装/工作

【返回列表】:['工信处', '干事', '女干事', '每月', '经过', '下属', '科室', '都', '要', '亲口', '交代', '24', '口', '交换', '换机', '交换机', '等', '技术', '技术性', '器件', '的', '安装', '工作']

HMM模型

即隐马尔可夫模型(Hidden Markov Model, HMM),隐马尔科夫模型是关于时序的概率模型,描述由一个隐藏的马尔科夫链随机生成不可观测的状态随机序列,再由各个状态生成观测随机序列的过程。模型 HMM的典型模型是一个五元组: StatusSet: 状态值集合 ObservedSet: 观察值集合 TransProbMatrix: 转移概率矩阵 EmitProbMatrix: 发射概率矩阵 InitStatus: 初始状态分布。详情请见我的个人网站上关于HMM的详细讲解。

https://zg104.github.io/HMM

在 jieba 中,对于未登录到词库的词,使用了基于汉字成词能力的 HMM 模型和 Viterbi 算法,其大致原理是:

采用四个隐含状态,分别表示为单字成词,词组的开头,词组的中间,词组的结尾。通过标注好的分词训练集,可以得到 HMM 的各个参数,采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合(Viterbi算法),得到分词结果。

# 未启用 HMM
seg_list = cut("小明去到了网易杭研大厦", HMM=False) #默认精确模式和启用 HMM
print("【未启用 HMM】:" + "/ ".join(seg_list)) 

# 启用 HMM识别新词
seg_list = cut("小明去到了网易杭研大厦"#默认精确模式和启用 HMM
print("【识别新词】:" + "/ ".join(seg_list))  

【未启用 HMM】:小/ 明/ 去/ 到/ 了/ 网易/ 杭/ 研/ 大厦

【识别新词】:小明/ 去/ 到/ 了/ 网易/ 杭研/ 大厦

繁体字分词

from jieba import *

content = '境界讓死亡充滿韻味;死亡讓人生歸于純淨'
sep1 = cut(content,cut_all=False)
print("【精确模式】:" + "/".join(sep1))  

sep2 = cut(content,cut_all=True)
print("【全模式】:" + "/".join(sep2))   


sep3 = lcut(content,cut_all=False)
print("【精确模式】:" ,sep3)  

sep4 = lcut(content,cut_all=True)
print("【全模式】:" ,sep4) 

sep5 = cut_for_search(content)
print("【搜索引擎模式--generator】:"'/'.join(sep5))

sep6 = lcut_for_search(content)
print("【返回列表】:" ,sep6)
【精确模式】:境界/讓/死亡/充滿/韻味/;/死亡/讓/人生/歸于/純淨
【全模式】:境界/讓/死亡/充/滿/韻/味/;/死亡/讓/人生/歸/于/純/淨
【精确模式】: ['境界''讓''死亡''充滿''韻味'';''死亡''讓''人生''歸于''純淨']
【全模式】: ['境界''讓''死亡''充''滿''韻''味'';''死亡''讓''人生''歸''于''純''淨']
【搜索引擎模式--generator】:境界/讓/死亡/充滿/韻味/;/死亡/讓/人生/歸于/純淨
【返回列表】: ['境界''讓''死亡''充滿''韻味'';''死亡''讓''人生''歸于''純淨']

自定义字典

  1. 使用 jieba.load_userdict(file_name) 即可载入词典。

可以直接在目录下添加自定义字典,jieba 能够准确识别词典中出现的词汇,提升整体的识别准确率。

每行三部分:词语、词频(可省略)、词性(可省略),用空格隔开,顺序不能颠倒

词典存为 userdict.txt

云计算 5 n
李小福 2 nr
easy_install 3 eng
好用 300
韩玉鉴赏 3 nz
八一双鹿 3 nz
from jieba import *

# 示例文本
sample_text = "李小福是韩玉鉴赏也是云计算方面的专家"

# 未加载词典
print("【未加载词典】:" + '/ '.join(cut(sample_text)))
# 载入词典
load_userdict("./user_dict.txt")
# 加载词典后
print("【加载词典后】:" + '/ '.join(cut(sample_text)))
【未加载词典】:李小福/ 是/ 韩玉/ 鉴赏/ 也/ 是/ 云/ 计算/ 方面/ 的/ 专家
【加载词典后】:李小福/ 是/ 韩玉鉴赏/ 也/ 是/ 云计算/ 方面/ 的/ 专家
  1. 使用 add_word(word, freq=None, tag=None)del_word(word) 可在程序中动态修改词典。

使用 suggest_freq(segment, tune=True) 可调节单个词语的词频,使其能(或不能)被分出来。

import jieba

jieba.add_word('李焕英'#增加自定义词语
jieba.add_word('刺杀小说家', freq=42, tag='nz'#设置词频和词性 
jieba.del_word('好用'#删除自定义词语 

# 调节词频前
print("【调节词频前】:" + '/'.join(jieba.cut('唐人街探案里面李焕英刺杀小说家。', HMM=False)))
# 调节词频
jieba.suggest_freq(('刺杀''小说家'), True)
jieba.add_word('唐人街探案'#增加自定义词语
# 调节词频后
print("【调节词频后】:" + '/'.join(jieba.cut('唐人街探案里面李焕英刺杀小说家。', HMM=False)))
【调节词频前】:唐人街/探案/里面/李焕英/刺杀小说家/。
【调节词频后】:唐人街探案/里面/李焕英/刺杀/小说家/。

关键词提取

TF-IDF

基于TF-IDF的关键词提取,TF-IDF(Term frequency–inverse document frequency)方法通过计算单文本词频(Term Frequency, TF)和逆文本频率指数(Inverse Document Frequency, IDF)得到词语权重,按照权重排序,输出关键字。

简单来说,一个词语在一篇文章中出现次数越多,同时在所有文档中出现次数越少,越能够代表该文章

通过 jieba.analyse.extract_tags 方法可以基于 TF-IDF 算法进行关键词提取,该方法共有 4 个参数:

  • sentence:为待提取的文本
  • topK:为返回几个 TF/IDF 权重最大的关键词,默认值为 20
  • withWeight:是否一并返回关键词权重值,默认值为 False
  • allowPOS:仅包括指定词性的词,默认值为空
import jieba
import jieba.analyse

sentence = "将结合巩固深化“不忘初心、牢记使命”主题教育成果,\
在全体党员中开展党史学习教育。这次学习教育贯穿2021年全年,\
总的要求是学史明理、学史增信、学史崇德、学史力行,\
教育引导党员干部学党史、悟思想、办实事、开新局。"


keywords = jieba.analyse.extract_tags(sentence, topK=20, withWeight=True, allowPOS=('n''nr''ns'))

for i, item in enumerate(keywords,0):
    print(i+1, item[0], item[1])
1 学史 2.812886471270588
2 党史 1.3248965085176472
3 初心 0.7769135571411765
4 教育引导 0.695366830017647
5 力行 0.6510273122294118
6 办实事 0.6307425777411764
7 党员干部 0.5788373318488235
8 牢记 0.5473857530494117
9 党员 0.4579285603817647
10 全体 0.41728519362235295
11 成果 0.3948835581094117
12 主题 0.3647283793270588
13 思想 0.3286800558329412

TextRank

通过 jieba.analyse.textrank 方法可以使用基于 TextRank 算法的关键词提取,其与 'jieba.analyse.extract_tags' 有一样的参数,但前者默认过滤词性(allowPOS=('ns', 'n', 'vn', 'v'))。

  1. TextRank首先对每个句子进行分词和词性标注处理;

  2. 过滤掉除指定词性外的其他单词,过滤掉出现在停用词表的单词,过滤掉长度小于2的单词;

  3. 将剩下的单词中循环选择一个单词,将其与其后面4个单词分别组合成4条边。

    例如:'鉴于/中方/宣布/对欧/制裁/措施/,/欧洲议会/决定/取消/《/中欧/全面/投资/协定/》/的/审议/会议/。'

    对于鉴于这个单词,就有(鉴于, 中方)、(鉴于, 宣布)、(鉴于, 对欧)、(鉴于, 制裁)4条边,且每条边权值为1,当这条边在之后再次出现时,权值再在基础上加1.

  4. 构建候选关键词图 ,通过上方的关键词集,采用共现关系构造两点之间的边,两个节点之间边仅在对应词汇长度为 K 的窗口中出现,K 表示窗口大小;

  5. 套用TextRank的公式,迭代传播各节点的权值,直至收敛。

  6. 对结果中的Rank值进行倒序排序,筛选出排名较前的关键词。

import jieba
import jieba.analyse

sentence = "将结合巩固深化“不忘初心、牢记使命”主题教育成果,\
在全体党员中开展党史学习教育。这次学习教育贯穿2021年全年,\
总的要求是学史明理、学史增信、学史崇德、学史力行,教育引导党员干部学党史、悟思想、办实事、开新局。"


for i, item in enumerate(jieba.analyse.textrank(sentence, withWeight=True),0):
    print('%s %s %s' % (i+1, item[0], item[1]))
1 学史 1.0
2 教育 0.9044185307028669
3 学习 0.6137976317315587
4 党史 0.6017452684334677
5 使命 0.41219773459681996
6 结合 0.4016759800590353
7 巩固 0.3988612023602106
8 成果 0.3839564475813888
9 全体 0.3698801632706404
10 思想 0.36986713670315446
11 党员 0.36791346021473825
12 开展 0.3648669309980439
13 牢记 0.3454272585692637
14 主题 0.32296525572392104
15 教育引导 0.3162817317904539
16 党员干部 0.3127099860891685
17 力行 0.3095942602384653
18 开新 0.28514236997165693
19 办实事 0.28414904211146463
20 增信 0.23183734749718268

那么这期的内容就到这里了,下一篇会继续进行语料、词性、并行化以及搜索模式的相关讲解,敬请期待。