本系列文章主要结合Python语言实现知识图谱构建相关工程,具有一定创新性和实用性,非常希望各位博友交流讨论,相互促进成长。前面两篇文章详细讲解了哈工大Pyltp工具,包括中文分词、词性标注、实体识别、依存句法分析和语义角色标注等。但是其中文分词效果不是很理想,如“贵州财经大学”总是切分成“贵州”、“财经”和“大学”,这是因为词典中这些词的权重较高。这篇文章主要介绍最经典的自然语言处理工具之一——Jieba,包括中文分词、添加自定义词典及词性标注等内容。
知识图谱系列文章:
[知识图谱实战篇] 一.数据抓取之Python3抓取JSON格式的电影实体
[知识图谱实战篇] 二.Json+Seaborn可视化展示电影实体
[知识图谱实战篇] 三.Python提取JSON数据、HTML+D3构建基本可视化布局
[知识图谱实战篇] 四.HTML+D3+CSS绘制关系图谱
[知识图谱实战篇] 五.HTML+D3添加鼠标响应事件显示相关节点及边
[知识图谱实战篇] 六.HTML+D3实现点击节点显示相关属性及属性值
[知识图谱实战篇] 七.HTML+D3实现关系图谱搜索功能
[知识图谱实战篇] 八.HTML+D3绘制时间轴线及显示实体
环境下载地址:https://download.csdn.net/download/eastmount/11226539
原文地址:
[Python知识图谱] 一.哈工大pyltp安装及中文分句、中文分词、导入词典基本用法
[Python知识图谱] 二.哈工大pyltp词性标注、命名实体识别、依存句法分析和语义角色标注
参考前文:
[python] 使用Jieba工具中文分词及文本聚类概念 - eastmount
杨秀璋. Python网络数据爬取及分析从入门到精通(分析篇). 北京:北京航空航天大学出版社[M]. 2018
在数据分析和数据挖掘中,通常需要经历前期准备、数据爬取、数据预处理、数据分析、数据可视化、评估分析等步骤,而数据分析之前的工作几乎要花费数据工程师近一半的工作时间,其中的数据预处理也将直接影响后续模型分析的好坏。
数据预处理(Data Preprocessing)是指在进行数据分析之前,对数据进行的一些初步处理,包括缺失值填写、噪声处理、不一致数据修正、中文分词等,其目标是得到更标准、高质量的数据,纠正错误异常数据,从而提升分析的结果。
下图是中文文本预处理的基本步骤,包括中文分词、词性标注、数据清洗、特征提取(向量空间模型存储)、权重计算(TF-IDF)等
“结巴”(Jieba)工具是最常用的中文文本分词和处理的工具之一,它能实现中文分词、词性标注、关键词抽取、获取词语位置等功能。其在Github网站上的介绍及下载地址为:https://github.com/fxsjy/jieba
作者推荐大家使用PIP工具来安装Jieba中文分词包,安装语句如下:
pip install jieba
调用命令“pip install jieba”安装jieba中文分词包如下图所示。
安装过程中的会显示安装配置相关包和文件的百分比,直到出现“Successfully installed jieba-0.37”命令,表示安装成功。同时,在安装过程中会遇到各种问题,大家一定要学会独立搜索答案解决这些问题,才能提升您独立解决问题的能力。
Jieba工具具有有以下特点:
Jieba工具主要使用的算法包括:(1)通过基于前缀词典实现高效的词图扫描,构建句子中汉字所有可能生成词情况的有向无环图;(2)采用动态规划查找最大概率路径,寻找基于词频的最大切分组合;(3)对于未登录词,采用基于汉字成词能力的HMM模型结合Viterbi算法。
由于中文词语之间是紧密联系的,一个汉语句子是由一串前后连续的汉字组成,词与词之间没有明显的分界标志,所以需要通过一定的分词技术把句子分割成空格连接的词序列,这就是所谓的中文分词技术。
中文分词(Chinese Word Segmentation)指将汉字序列切分成一个个单独的词或词串序列,它能够在没有词边界的中文字符串中建立分隔标志,通常采用空格分隔。中文分词是数据分析预处理、数据挖掘、文本挖掘、搜索引擎、知识图谱、自然语言处理等领域中非常基础的知识点,只有经过中文分词后的语料才能转换为数学向量的形式,继续进行后面的分析。同时,由于中文数据集涉及到语义、歧义等知识,划分难度较大,比英文复杂很多。
下面举个简单示例,对句子“我是程序员”进行分词操作。
输入:我是程序员
输出1:我\是\程\序\员
输出2:我是\是程\程序\序员
输出3:我\是\程序员
这里分别采用了三种方法介绍中文分词。“我\是\程\序\员”采用的是一元分词法,将中文字符串分隔为单个汉字;“我是\是程\程序\序员”采用二元分词法,将中文汉字两两分隔;“我\是\程序员”是比较复杂但更实用的分词方法,它根据中文语义来进行分词的,其分词结果更准确。
中文分词方法有很多,常见的包括基于字符串匹配的分词方法、基于统计的分词方法和基于语义的分词方法等。这里介绍比较经典的基于字符串匹配的分词方法。
基于字符串匹配的分词方法又称为基于字典的分词方法,它按照一定策略将待分析的中文字符串与机器词典中的词条进行匹配,若在词典中找到某个字符串,则匹配成功,并识别出对应的词语。该方法的匹配原则包括最大匹配法(MM)、逆向最大匹配法(RMM)、逐词遍历法、最佳匹配法(OM)、并行分词法等。
正向最大匹配法的步骤如下,假设自动分词词典中的最长词条所含汉字的个数为n。
例如,现在存在一个句子“北京理工大学生前来应聘”,使用正向最大匹配方法进行中文分词的过程如下所示。
首先读者看一段简单的结巴分词代码,主要调用两个函数实现。
#encoding=utf-8
import jieba
text = "小杨毕业于北京理工大学,从事Python人工智能相关工作。"
#全模式
data = jieba.cut(text,cut_all=True)
print(type(data))
print(u"[全模式]: ", "/".join(data))
#精确模式
data = jieba.cut(text,cut_all=False)
print(u"[精确模式]: ", "/".join(data))
#默认是精确模式
data = jieba.cut(text)
print(u"[默认模式]: ", "/".join(data))
#搜索引擎模式
data = jieba.cut_for_search(text)
print(u"[搜索引擎模式]: ", "/".join(data))
#返回列表
seg_list = jieba.lcut(text, cut_all=False)
print("[返回列表]: {0}".format(seg_list))
输出结果如下所示。
最终的分词结果比较理想,其中精确模式输出的“小/杨/毕业/于/北京理工大学/,/从事/Python/人工智能/相关/工作/。”比较精准。下面简单叙述结巴中文分词的三种分词模式。
全模式
该模式将语料中所有可以组合成词的词语都构建出来,其优点是速度非常快,缺点是不能解决歧义问题,并且分词结果不太准确。其分词结果为“小/杨/毕业/于/北京/北京理工/北京理工大学/理工/理工大/理工大学/工大/大学///从事/Python/人工/人工智能/智能/相关/工作//”。
精确模式
该模式利用其算法将句子最精确地分隔开,适合文本分析,通常采用这种模式进行中文分词。其分词结果为“小/杨/毕业/于/北京理工大学/,/从事/Python/人工智能/相关/工作/。”,其中“北京理工大学”、“人工智能”这些完整的名词被精准识别,但也有部分词未被识别,后续导入词典可以实现专有词汇识别。
搜索引擎模式
该模式是在精确模式基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。其结果为“小/杨/毕业/于/北京/理工/工大/大学/理工大/北京理工大学/,/从事/Python/人工/智能/人工智能/相关/工作/。”。
隐马尔可夫模型(Hidden Markov Model, HMM)是一种基于概率的统计分析模型,用来描述一个系统隐性状态的转移和隐性状态的表现概率。到目前为止,HMM模型被认为是解决大多数自然语言处理问题最为快速、有效的方法之一。它成功解决了语义识别、机器翻译等问题。
在Jieba工具中,对于未登录到词库的词,使用了基于汉字成词能力的 HMM 模型和 Viterbi 算法,其大致原理是采用四个隐含状态,分别表示为单字成词、词组的开头、词组的中间和词组的结尾。通过标注好的分词训练集,可以得到 HMM的各个参数,然后使用 Viterbi 算法来解释测试集,得到分词结果。
#encoding=utf-8
import jieba
text = "他来到了网易杭研大厦工作,我继续去北理读研。"
#精确模式
data = jieba.cut(text, cut_all=False, HMM=False)
print(u"[精确模式]: ", "/".join(data))
#精确模式+HMM
data = jieba.cut(text, cut_all=False, HMM=True)
print(u"[精确模式]: ", "/".join(data))
输出结果如下图所示,未启用HMM模型时,它无法识别“杭研”、“北理”词语,将其拆分成了“杭”、“研”和“北”、“理”,而启用HMM模型时,它有效识别了新词“杭研”、“北理”。
Jieba工具支持中文繁体字的识别,将前面示例转换为繁体字,即“小楊畢業於北京理工大學,從事Python人工智能相關工作。”,调用Jieba分词的代码如下所示。
#encoding=utf-8
import jieba
text = "小楊畢業於北京理工大學,從事Python人工智能相關工作。"
#全模式
data = jieba.cut(text, cut_all=True)
print(type(data))
print(u"[全模式]: ", "/".join(data))
#精确模式
data = jieba.cut(text, cut_all=False)
print(u"[精确模式]: ", "/".join(data))
#搜索引擎模式
data = jieba.cut_for_search(text)
print(u"[搜索引擎模式]: ", "/".join(data))
输出结果如下所示:
[全模式]: 小/楊/畢/業/於/北京/北京理工/理工/理工大/工大/學///從/事/Python/人工/人工智能/智能/相/關/工作//
[精确模式]: 小/楊/畢業/於/北京理工/大學/,/從事/Python/人工智能/相關/工作/。
[搜索引擎模式]: 小/楊/畢業/於/北京/理工/北京理工/大學/,/從事/Python/人工/智能/人工智能/相關/工作/。
在进行中文分词过程中,通常会遇到一些专用词语无法精准的切分,比如“乾清宫”会被分割为“乾”、“清宫”,“黄果树瀑布”会被分割为“黄果树”、“瀑布”,“云计算”会被分割为“云”、“计算”,“贵州财经大学”会被分割为“贵州”、“财经大学”等。虽然Jieba工具有新词识别能力,但也无法识别出所有Jieba词库里没有的词语,但它为开发者提供了添加自定义词典功能,从而保证更好的分词正确率。其函数原型如下:
word freq word_type
其中,word为对应的词语,freq为词频(可省略),word_type为词性(可省了),中间用空格隔开,顺序不可以改变。注意,文件必须为UTF-8编码。
下面举例讲解,第一个代码是未导入自定义词典的中文分词。
#encoding=utf-8
import jieba
text = "小杨在贵州财经大学工作,擅长大数据、云计算,喜欢乾清宫、黄果树瀑布等景区。"
#精确模式
data = jieba.cut(text, cut_all=False)
print(u"[原始文本]: ", text)
print(u"[精确模式]: ", " ".join(data))
输出结果未将“贵州财经大学”、“大数据”、“云计算”、“乾清宫”、“黄果树瀑布”等词汇正确分割。
接着导入自定义词典,其本地词典命名为“dict.txt”,如图所示,包括设置“贵州财经大学”的词性为机构名词“nt”,“大数据”、“云计算”的词性为名词“n”,也有省略词性和词频的“乾清宫”。
完整代码如下:
#encoding=utf-8
import jieba
text = "杨秀璋在贵州财经大学工作,擅长大数据、云计算,喜欢乾清宫、黄果树瀑布等景区。"
#导入自定义词典
jieba.load_userdict("dict.txt")
#精确模式
data = jieba.cut(text, cut_all=False)
print(u"[原始文本]: ", text)
print(u"[精确模式]: ", " ".join(data))
此时的输出结果有效地提取了“贵州财经大学”、“云计算”、“乾清宫”。但也有两个未识别出的词语,“黄果树瀑布”不在词典中,故被拆分成了“黄果树”和“瀑布”,“大数据”虽然在词典中,却仍然拆分成了“大”和“数据”。
在Jieba工具中,可以在程序中动态修改词典,通过add_word(word, freq=None, tag=None)函数添加新词语,通过del_word(word)函数删除自定义词语。
#encoding=utf-8
import jieba
text = "小杨在贵州财经大学工作,擅长大数据、云计算,喜欢乾清宫、黄果树瀑布等景区。"
#导入自定义词典
jieba.load_userdict("dict.txt")
#添加自定义词语
jieba.add_word("小杨")
jieba.add_word("黄果树瀑布")
jieba.add_word("自然语言处理", freq=10, tag="nz")
#删除自定义词语
jieba.del_word("北理工")
#精确模式
data = jieba.cut(text, cut_all=False)
print(u"[原始文本]: ", text, "\n")
print(u"[精确模式]: ", " ".join(data))
该代码增加了新词语“小杨”、“黄果树瀑布”和“自然语言处理”,删除了“北理工”,其运行结果如下所示,它有效地将“小杨”和“黄果树瀑布”进行了精准识别。
此时,读者可能会有一个疑问,为什么“大数据”被拆分成了“大”和“数据”呢?这是因为Jieba词库中“大”和“数据”的重要程度更高,我们可以使用suggest_freq(segment, tune=True)函数调节单个词语的词频,使其被分割出来。
代码如下所示:
#encoding=utf-8
import jieba
text = "小杨在贵州财经大学工作,擅长大数据、云计算,喜欢乾清宫、黄果树瀑布等景区。"
#导入自定义词典
jieba.load_userdict("dict.txt")
#添加自定义词语
jieba.add_word("小杨")
jieba.add_word("黄果树瀑布")
jieba.add_word("自然语言处理", freq=10, tag="nz")
#删除自定义词语
jieba.del_word("北理工")
#调节词频
jieba.suggest_freq('大数据', True)
#精确模式
data = jieba.cut(text, cut_all=False)
print(u"[原始文本]: ", text, "\n")
print(u"[精确模式]: ", " ".join(data))
最终的输出结果为“小杨 在 贵州财经大学 工作 , 擅长 大数据 、 云计算 , 喜欢 乾清宫 、 黄果树瀑布 等 景区 。”
终于将“小杨”、“贵州财经大学”、“大数据”、“云计算”、“乾清宫”、“黄果树瀑布”等专有词语识别出来。同时,如果自定义词典存在很多专用名词,并且需要设置它们的高权重,可以使用下面的代码循环设置每一个词语的词频。
#循环设置词频重要程度
fp = open("dict.txt", 'r', encoding='utf8')
for line in fp:
line = line.strip()
jieba.suggest_freq(line, True)
#第二种方法
[jieba.suggest_freq(line.strip(), True) for line in open("dict.txt",'r',encoding='utf8')]
词性标注(Part-Of-Speech Tagging, POS Tagging)也被称为语法标注(Grammatical Tagging)或词类消疑(Word-category Disambiguation),是将语料库内单词的词性按其含义和上下文内容进行标记的文本数据处理技术。通过词性标注处理,可以将分词得到的词序列中每个单词标注一个正确的词性。
在Jieba工具中,调用jieba.posseg.POSTokenizer(tokenizer=None)函数新建自定义分词器。tokenizer参数可指定内部使用的jieba.Tokenizer分词器,jieba.posseg.dt为默认词性标注分词器。Jieba工具采用和Ictclas 兼容的标记法,标注句子分词后每个词的词性通过循环输出。表4-1为Jieba工具的各个词性及含义。
官方文档给出的示例如下所示,通过“import jieba.posseg as pseg”语句导入扩展包,接着循环输出word(词语)和flag(词性)值。
#encoding=utf-8
import jieba.posseg as pseg
#词性标注
words = pseg.cut("我爱北京天安门")
for word, flag in words:
print('%s %s' % (word, flag))
输出结果如图所示,其中“我”表示代词,对应“r”;“爱”对应动词,对应“v”,“北京”和“天安门”对应地点名词,对应“ns”。
上面小节的示例对应的词性标注代码如下所示。
#encoding=utf-8
import jieba
import jieba.posseg
import jieba.analyse
text = "小杨在贵州财经大学工作,擅长大数据、云计算,喜欢乾清宫、黄果树瀑布等景区。"
#导入自定义词典
jieba.load_userdict("dict.txt")
#添加自定义词语
jieba.add_word("小杨")
jieba.add_word("黄果树瀑布")
#调节词频
jieba.suggest_freq('大数据', True)
#精确模式
data = jieba.cut(text, cut_all=False)
print(u"[原始文本]: ", text, "\n")
print(u"[精确模式]: ", " ".join(data), "\n")
#词性标注
sentence_seged = jieba.posseg.cut(text)
outstr = ''
for x in sentence_seged:
outstr += "{}/{} ".format(x.word, x.flag)
print(u'[词性标注]:', outstr)
输出结果如图所示。
希望这篇基础性文章对你有所帮助,如果有错误或不足之处,还请海涵。下一篇将详细讲解Jieba工具实现关键词抽取、事件抽取和命名实体识别等例子。望喜欢~同时,后续分享更多的是网络安全方面的文章了,从零开始很难,但秀璋会一路走下去的,加油。
故人应在千里外,
不寄梅花远信来。
武汉第一周学习结束,寄了第一封家书给女神,接下来这几年,应该会写上200来封吧,很期待,也很漫长,但我俩的故事将继续书写。
今天早上做了我来这的第一次PPT汇报,是关于网络安全和数据挖掘、人工智能的融合,也听了学弟们的汇报,真的学到好多,也记录了无数未知的词汇,接下来要学的更多。这一周给我最深刻的印象就是:学弟学妹们怎么这么刻苦?早上去得很早,中午不回去午休,晚上还继续敲代码,而且本科大三的学弟们也很多,在没有老师的情况下,小组自发组织PPT汇报探讨,仿佛我是那个最“偷懒”的学生,我猜:肯定是外面太热,他们都想蹭空调!
真的很感激这次来之不易的学习机会,感谢所有的老师、师兄师姐、师弟师妹,更感激家人朋友和女神。也谢谢CSDN认识的博友请我吃饭,武大测绘本硕博连读让我甚是佩服,真的通过CSDN认识了很多朋友,大家分散五湖四海,共同进步。
未来的路还很长,优秀的人真的太多,我们只有做好自己,不忘初心,享受生活,砥砺前行。明天周末继续奋斗,晚安娜,记得收信
(By:杨秀璋 2019-07-28 周日下午5点写于武大 https://blog.csdn.net/Eastmount )