欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【NLP】中文处理前提--jieba详解

程序员文章站 2022-06-12 13:46:29
...

介绍

\quad\quad在自然语言处理中,中文处理技术比西文处理技术要落后很大一段距离,许多西文的处理方法中文不能直接采用,就是因为中文必需有分词这道工序。

\quad\quad当我们进行自然语言处理的时候,大部分情况下,词汇是我们对句子和文章理解的基础,因此需要一个工具去把完整的文本中分解成粒度更细的词。

中文分词是其他中文处理的基础

Python3 jieba库的安装

  • 直接命令行输入:pip install jieba
  • 百度PyPI,搜索下载jieba包,放在命令行启动目录下,输入pip install (+ jieba包的包名全称)

jieba主要功能

1. jieba分词的特点

支持三种分词模式:

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

支持繁体分词

支持自定义词典

MIT 授权协议

2. 分词函数

\quad\quadjieba.cut 以及 jieba.cut_for_search 返回的结构都是一个可迭代的 generator,可以使用 for 循环来获得分词后得到的每一个词语(unicode)
支持三种分词模式:

jieba.cut(将包含中文字符的整个句子分成单独分词)

语法:

jieba.cut(sentence, cut_all=False, HMM=True)

参数说明:

  • sentence:需要分词的句子
  • cut_all:参数用来控制是否采用全模式
  • HMM:参数用来控制是否使用 HMM 模型

实例:

import jieba
# 分词
# 全模式
cut1 = jieba.cut("云南省昆明市昆明理工大学是个美丽的学校,学校在呈贡区", cut_all=True)
print("全模式: "+" / ".join(cut1))
# 精确模式
cut2 = jieba.cut("云南省昆明市昆明理工大学是个美丽的学校,学校在呈贡区", cut_all=False)
print("精确模式: "+" / ".join(cut2))
# 默认模式--精确模式
cut3 = jieba.cut("云南省昆明市昆明理工大学是个美丽的学校,学校在呈贡区" )
print("默认模式: "+" / ".join(cut3))

运行结果:

全模式: 云南 / 云南省 / 昆明 / 昆明市 / 昆明 / 明理 / 理工 / 理工大 / 理工大学 / 工大 / 大学 / 是 / 个 / 美丽 / 的 / 学校 /  /  / 学校 / 在 / 呈贡 / 区
精确模式: 云南省 / 昆明市 / 昆明 / 理工大学 / 是 / 个 / 美丽 / 的 / 学校 / , / 学校 / 在 / 呈贡 / 区
默认模式: 云南省 / 昆明市 / 昆明 / 理工大学 / 是 / 个 / 美丽 / 的 / 学校 / , / 学校 / 在 / 呈贡 / 区

jieba.cut_for_search(搜索引擎模式)

语法:

jieba.cut_for_search(sentence, HMM=True)

参数说明:

  • sentence:需要分词的句子
  • HMM:参数用来控制是否使用 HMM 模型

实例:

# 搜索引擎模式
cut4 = jieba.cut_for_search("云南省昆明市昆明理工大学是个美丽的学校,学校在呈贡区" )
print("搜索引擎模式: "+" / ".join(cut4))

运行结果:

搜索引擎模式: 云南 / 云南省 / 昆明 / 昆明市 / 昆明 / 理工 / 工大 / 大学 / 理工大 / 理工大学 / 是 / 个 / 美丽 / 的 / 学校 / , / 学校 / 在 / 呈贡 / 区

jieba.lcut以及jieba.lcut_for_search直接返回 list

实例:

cut5 = jieba.lcut("云南省昆明市昆明理工大学是个美丽的学校,学校在呈贡区" )
print(type(cut5))
print("默认模式: "+" / ".join(cut5))
# 搜索引擎模式
cut6 = jieba.lcut_for_search("云南省昆明市昆明理工大学是个美丽的学校,学校在呈贡区" )
print(type(cut6))
print("搜索引擎模式: "+" / ".join(cut6))

运行结果:

<class 'list'>
默认模式: 云南省 / 昆明市 / 昆明 / 理工大学 / 是 / 个 / 美丽 / 的 / 学校 / , / 学校 / 在 / 呈贡 / 区
<class 'list'>
搜索引擎模式: 云南 / 云南省 / 昆明 / 昆明市 / 昆明 / 理工 / 工大 / 大学 / 理工大 / 理工大学 / 是 / 个 / 美丽 / 的 / 学校 / , / 学校 / 在 / 呈贡 / 区

3. 添加用户自定义词典

\quad\quad很多时候我们需要针对自己的场景进行分词,会有一些领域内的专有词汇。开发者可以指定自己自定义的词典,以便包含 jieba 词库里没有的词。虽然 jieba 有新词识别能力,但是自行添加新词可以保证更高的正确率。

用法:

  • 1.可以用jieba.load_userdict(file_name)加载用户字典,其中file_name 为文件类对象或自定义词典的路径
  • 2.少量的词汇可以自己用下面方法手动添加:
  • \quad\quadadd_word(word, freq=None, tag=None)del_word(word)在程序中动态修改词典
  • \quad\quadsuggest_freq(segment, tune=True) 可调节单个词语的词频,使其能(或不能)被分出来。

词典格式:

  • 词典是txt文件,一个词占一行;
  • 每一行分三部分:词语、词频(可省略)、词性(可省略),用空格隔开,顺序不可颠倒;
  • file_name若为路径或二进制方式打开的文件,则文件必须为 UTF-8 编码。

注:

  • 词典构建方式:一般都是基于jieba分词之后的效果进行人工干预的

例如:dict.txt

云南省 nt
昆明市 nt
昆明理工大学 2 nt
是个
美丽的 a
学校
在
呈贡区

实例1:

import jieba

cut1 = jieba.cut("云南省昆明市昆明理工大学是个美丽的学校,学校在呈贡区" )
print("加入词典前: "+" / ".join(cut1))

jieba.load_userdict('dict.txt')

cut2 = jieba.cut("云南省昆明市昆明理工大学是个美丽的学校,学校在呈贡区" )
print("加入词典后: "+" / ".join(cut2))

运行结果:

加入词典前: 云南省 / 昆明市 / 昆明 / 理工大学 / 是 / 个 / 美丽 / 的 / 学校 / , / 学校 / 在 / 呈贡 / 区
加入词典后: 云南省 / 昆明市 / 昆明理工大学 / 是个 / 美丽的 / 学校 / , / 学校 / 在 / 呈贡区

实例2:

import jiieba

print('/'.join(jieba.cut('如果放到旧字典中将出错。', HMM=False)))

jieba.suggest_freq(('中', '将'), True)

print('/'.join(jieba.cut('如果放到旧字典中将出错。', HMM=False)))

运行结果:

如果/放到/旧/字典/中将/出错/。
如果/放到/旧/字典/中/将/出错/。

实例3:

import jieba

cut1 = jieba.cut("云南省昆明市昆明理工大学是个美丽的学校,学校在呈贡区" )
print("动态修改词典前: "+" / ".join(cut1))

jieba.add_word('昆明理工大学')
jieba.add_word('呈贡区')
jieba.del_word('昆明市')

cut2 = jieba.cut("云南省昆明市昆明理工大学是个美丽的学校,学校在呈贡区" )
print("动态修改词典后: "+" / ".join(cut2))

运行结果:

动态修改词典前: 云南省 / 昆明市 / 昆明 / 理工大学 / 是 / 个 / 美丽 / 的 / 学校 / , / 学校 / 在 / 呈贡 / 区
动态修改词典后: 云南省 / 昆明 / 市 / 昆明理工大学 / 是 / 个 / 美丽 / 的 / 学校 / , / 学校 / 在 / 呈贡区

实例4:

import jieba
testlist = [
('今天天气不错', ('今天', '天气')),
('如果放到post中将出错。', ('中', '将')),
('我们中出了一个叛徒', ('中', '出')),
]

for sent, seg in testlist:
    print('/'.join(jieba.cut(sent, HMM=False)))
    word = ''.join(seg)
    print('%s 调节单个词语的词频前的词频: %s, 调节单个词语的词频后的词频: %s' % (word, jieba.get_FREQ(word), jieba.suggest_freq(seg, True)))
    print('/'.join(jieba.cut(sent, HMM=False)))
    print("-"*40)

运行结果:

今天天气/不错
今天天气 调节单个词语的词频前的词频: 3, 调节单个词语的词频后的词频: 0
今天/天气/不错
----------------------------------------
如果/放到/post/中将/出错/。
中将 调节单个词语的词频前的词频: 763, 调节单个词语的词频后的词频: 494
如果/放到/post/中/将/出错/。
----------------------------------------
我们/中/出/了/一个/叛徒
中出 调节单个词语的词频前的词频: 3, 调节单个词语的词频后的词频: 3
我们/中/出/了/一个/叛徒
----------------------------------------

4. 关键词提取

import jieba.analyse

(1)基于 TF-IDF 算法的关键词抽取

语法:

jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())

参数说明:

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

实例1:

import jieba.analyse as analyse
lines = open('NBA.txt', encoding='utf-8').read()
print("  ".join(analyse.extract_tags(lines, topK=20, withWeight=False, allowPOS=())))

运行结果:

韦少  杜兰特  全明星  全明星赛  MVP  威少  正赛  科尔  投篮  勇士  球员  斯布鲁克  更衣柜  NBA  三连庄  张卫平  西部  指导  雷霆  明星队

实例2:

import jieba.analyse as analyse
lines1 = open('西游记.txt',encoding='gb18030').read()
print("  ".join(analyse.extract_tags(lines1, topK=20, withWeight=False, allowPOS=())))
lines2 = open('西游记语录.txt',encoding='gb18030').read()
print("  ".join(analyse.extract_tags(lines2, topK=20, withWeight=False, allowPOS=())))

运行结果:

行者  八戒  师父  三藏  大圣  唐僧  沙僧  菩萨  妖精  和尚  那怪  甚么  那里  长老  呆子  怎么  徒弟  不知  老孙  悟空
行者  师父  八戒  三藏  菩萨  和尚  甚么  唐僧  妖精  怎么  老孙  徒弟  那里  大圣  沙僧  大王  悟空  我们  不知  不曾

注:字符集可能出现问题,自己试试
关于TF-IDF 算法可在网上找资源

补充:

  • 关键词提取所使用逆向文件频率(IDF)文本语料库可以切换成自定义语料库的路径

用法: jieba.analyse.set_idf_path(file_name) # file_name为自定义语料库的路径

  • 关键词提取所使用停止词(Stop Words)文本语料库可以切换成自定义语料库的路径

用法: jieba.analyse.set_stop_words(file_name) # file_name为自定义语料库的路径

(2)基于 TextRank 算法的关键词抽取

语法:

jieba.analyse.textrank(sentence, topK=20, withWeight=False, allowPOS=('ns', 'n', 'vn', 'v'))

参数说明:同上

基本思想:

  • 将待抽取关键词的文本进行分词
  • 以固定窗口大小(默认为5,通过span属性调整),词之间的共现关系,构建图
  • 计算图中节点的PageRank,注意是无向带权图

实例:

import jieba.analyse as analyse
lines = open('NBA.txt', encoding='utf-8').read()
print("  ".join(analyse.textrank(lines, topK=20, withWeight=False, allowPOS=('ns', 'n', 'vn', 'v'))))
print("  ".join(analyse.textrank(lines, topK=20, withWeight=False, allowPOS=('ns', 'n'))))

lines1 = open('西游记.txt',encoding='gb18030').read()
print("  ".join(analyse.textrank(lines1, topK=20, withWeight=False, allowPOS=('ns', 'n', 'vn', 'v'))))

lines2 = open('西游记语录.txt',encoding='gb18030').read()
print("  ".join(analyse.textrank(lines2, topK=20, withWeight=False, allowPOS=('ns', 'n', 'vn', 'v'))))

运行结果:

全明星赛  勇士  正赛  指导  对方  投篮  球员  没有  出现  时间  威少  认为  看来  结果  相隔  助攻  现场  三连庄  介绍  嘉宾
勇士  正赛  全明星赛  指导  投篮  玩命  时间  对方  现场  结果  球员  嘉宾  时候  全队  主持人  照片  全程  目标  快船队  肥皂剧

行者  师父  八戒  三藏  大圣  菩萨  不知  只见  妖精  长老  国王  呆子  徒弟  却说  悟空  小妖  不见  不能  不得  出来

师父  行者  八戒  不知  三藏  菩萨  妖精  大圣  徒弟  弟子  不得  长老  贫僧  悟空  出来  取经  国王  兄弟  不能  陛下

注:
TextRank 算法比TF-IDF 算法的运行时间长,对于NBA.txt个人觉得TF-IDF 算法好点,西游记的两个差不多

5. 词性标注

import jieba.posseg as pseg

语法:

jieba.posseg.POSTokenizer(tokenizer=None)

新建自定义分词器,tokenizer 参数可指定内部使用的 jieba.Tokenizer 分词器。jieba.posseg.dt 为默认词性标注分词器。
标注句子分词后每个词的词性,采用和 ictclas 兼容的标记法。

实例:

import jieba.posseg as pseg
words = pseg.cut("我爱自然语言处理")
for word, flag in words:
    print('%s %s' % (word, flag))

运行结果:

我 r
爱 v
自然语言 l
处理 v

6. 其他

另外jieba还支持,并行分词

原理:将目标文本按行分隔后,把各行文本分配到多个 Python 进程并行分词,然后归并结果,从而获得分词速度的可观提升 基于 python 自带的 multiprocessing 模块,目前暂不支持 Windows

用法:

  • jieba.enable_parallel(4) # 开启并行分词模式,参数为并行进程数
  • jieba.disable_parallel() # 关闭并行分词模式

Tokenize:返回词语在原文的起止位置

实例:

import jieba
print("这是默认模式的tokenize")
result = jieba.tokenize(u'自然语言处理非常有用')
for tk in result:
    print("%s\t\t start: %d \t\t end:%d" % (tk[0],tk[1],tk[2]))

print("这是搜索模式的tokenize")
result = jieba.tokenize(u'自然语言处理非常有用', mode='search')
for tk in result:
    print("%s\t\t start: %d \t\t end:%d" % (tk[0],tk[1],tk[2]))

运行结果:

这是默认模式的tokenize
自然语言		 start: 0 		 end:4
处理		 start: 4 		 end:6
非常		 start: 6 		 end:8
有用		 start: 8 		 end:10
这是搜索模式的tokenize
自然		 start: 0 		 end:2
语言		 start: 2 		 end:4
自然语言		 start: 0 		 end:4
处理		 start: 4 		 end:6
非常		 start: 6 		 end:8
有用		 start: 8 		 end:10

写在最后

此博客内容来自,jieba官方Github,链接,详细内容见Github。

相关标签: NLP