中科院的ICTCLAS,哈工大的ltp,东北大学的NIU Parser是学术界著名的分词器,我曾浅显读过一些ICTCLAS的代码,然而并不那么好读。jieba分词是python写成的一个算是工业界的分词开源库,其github地址为:
jieba分词虽然效果上不如ICTCLAS和ltp,但是胜在python编写,代码清晰,扩展性好,对jieba有改进的想法可以很容易的自己写代码进行魔改。毕竟这样说好像自己就有能力改进jieba分词一样_(:з」∠)_
网上诸多关于jieba分词的分析,多已过时,曾经分析jieba分词采用trie树的数据结构云云的文章都已经过时,现在的jieba分词已经放弃trie树,采用前缀数组字典的方式存储词典。
本文分析的jieba分词基于2015年7月
左右的代码进行,日后jieba若更新,看缘分更新这一系列文章_(:з」∠)_
jieba分词对已收录词和未收录词都有相应的算法进行处理,其处理的思路很简单,当然,过于简单的算法也是制约其召回率的原因之一。
其主要的处理思路如下:
从内存的词典中构建该句子的DAG(有向无环图)
对于词典中未收录词,使用HMM模型的viterbi算法尝试分词处理
已收录词和未收录词全部分词完毕后,使用dp寻找DAG的最大概率路径
jieba分词默认的模型使用了一些语料来做训练集,在 中,作者说
来源主要有两个,一个是网上能下载到的1998人民日报的切分语料还有一个msr的切分语料。另一个是我自己收集的一些txt小说,用ictclas把他们切分(可能有一定误差)。 然后用python脚本统计词频。
jieba分词的默认语料库选择看起来满随意的_(:з」∠)_,作者也吐槽高质量的语料库不好找,所以如果需要在生产环境使用jieba分词,尽量自己寻找一些高质量的语料库来做训练集。
语料库中所有的词语被用来做两件事情:
对词语的频率进行统计,作为登录词使用
对单字在词语中的出现位置进行统计,使用BMES模型进行统计,供后面套HMM模型Viterbi算法使用,这个后面说。
统计后的结果保存在dict.txt中,摘录其部分结构如下:
其中,第一列是中文词语
,第二列是词频
,第三列是词性,jieba分词现在的版本除了分词也提供词性标注等其他功能,这个不在本文讨论范围内,可以忽略第三列。jieba分词所有的统计来源,就是这个语料库产生的两个模型文件。
jieba分词为了快速地索引词典以加快分词性能,使用了前缀数组的方式构造了一个dict用于存储词典。
在旧版本的jieba分词中,jieba采用trie树的数据结构来存储,其实对于python来说,使用trie树显得非常多余,我将对新老版本的字典加载分别进行分析。
trie树又叫字典树,是一种常见的数据结构,用于在一个字符串列表中进行快速的字符串匹配。其核心思想是将拥有公共前缀的单词归一到一棵树下以减少查询的时间复杂度,其主要缺点是占用内存太大了。
trie树按如下方法构造:
trie树的根节点是空,不代表任何含义
其他每个节点只有一个字符,词典中所有词的第一个字的集合作为第一层叶子节点,以字符α开头的单词挂在以α为根节点的子树下,所有以α开头的单词的第二个字的集合作为α子树下的第一层叶子节点,以此类推
从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串
从根结点开始一次搜索;
取得要查找关键词的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索;
在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索。
在某个结点处,关键词的所有字母已被取出,则读取附在该结点上的信息,即完成查找。其他操作类似处理.
如查询at,可以找到路径root-a-t
的路径,对于单词av,从root找到a后,在a的叶子节点下面不能找到v结点,则查找失败。
二叉查找树的查找时间复杂度为O(lgn),比起二叉查找树,trie树的查找和结点数量无关,因此更加适合词汇量大的情况。
但是trie树对空间的消耗是很大的,是一个典型的空间换时间的数据结构。
旧版本jieba分词中关于trie树的生成代码如下:
代码很简单,遍历每行文件,对于每个单词的每个字母,在trie树(trie和p变量)中查找是否存在,如果存在,则挂到下面,如果不存在,就建立新子树。
jieba分词采用python 的dict来存储树,这也是python对树的数据结构的通用做法。
我写了一个函数来直观输出其生成的trie树,代码如下:
使用上面列举出的dict.txt的部分词典作为样例,输出结果如下
本来jieba采用trie树的出发点是可以的,利用空间换取时间,加快分词的查找速度,加速全切分操作。但是问题在于python的dict原生使用哈希表实现,在dict中获取单词是近乎O(1)的时间复杂度,所以使用trie树,其实是一种避重就轻的做法。
于是2014年某位同学的PR修正了这一情况。
在2014年的某次PR中( ),提交者将trie树改成前缀数组,大大地减少了内存的使用,加快了查找的速度。
现在jieba分词对于词典的操作,改为了一层word:freq的结构,存于lfreq中,其具体操作如下:
对于每个收录词,如果其在lfreq中,则词频累积,如果不在则加入lfreq
对于该收录词的所有前缀进行上一步操作,如单词'cat',则对c, ca, cat分别进行第一步操作。除了单词本身的所有前缀词频初始为0.
很朴素的做法,然而充分利用了python的dict类型,效率提高了不少。
Jieba是一个中文分词组件,可用于中文句子/词性分割、词性标注、未登录词识别,支持用户词典等功能。该组件的分词精度达到了97%以上。
1)基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG);
2)采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合;
3)对于未登录词,采用了基于汉字成词能力的HMM模型,使用了Viterbi算法。
jieba.cut方法接受两个输入参数: 1) 第一个参数为需要分词的字符串 2)cut_all参数用来控制是否采用全模式;jieba.cut_for_search 方法接受两个参数:需要分词的字符串;是否使用 HMM 模型。该方法适合用于搜索引擎构建倒排索引的分词,粒度比较细。
待分词的字符串可以是 unicode 或 UTF-8 字符串、GBK 字符串。注意:不建议直接输入 GBK 字符串,可能无法预料地错误解码成 UTF-8。
词典格式和dict.txt一样,一个词占一行;每一行分三部分,一部分为词语,另一部分为词频(可省略),最后为词性(可省略),用空格隔开。
词频可省略,使用计算出的能保证分出该词的词频。
更改分词器的 tmp_dir 和 cache_file 属性,可指定缓存文件位置,用于受限的文件系统。
4)关键词提取(基于 TextRank 算法的关键词提取)
将待抽取关键词的文本进行分词;
以固定窗口大小(默认为5,通过span属性调整),词之间的共现关系,构建图;
计算图中节点的PageRank,注意是无向带权图。
标注句子分词后每个词的词性,采用和 ictclas 兼容的标记法。
在自然语言处理过程中,为了能更好地处理句子,往往需要把句子拆开分成一个一个的词语,这样能更好的分析句子的特性,这个过程叫就叫做分词。由于中文句子不像英文那样天然自带分隔,并且存在各种各样的词组,从而使中文分词具有一定的难度。
不过,中文分词并不追求完美,而是通过关键字识别技术,抽取句子中最关键的部分,从而达到理解句子的目的。
Jupyter Notebook是一个交互式的笔记本工具,重点有两点
- “交互式” 让你随时随时运行并暂存结果,
- “笔记本” 记录你的研究过程
想象一下,在这之前你是如何使用Python的?
有了JN之后,你可以:
jieba模块安装请参见官方说明
jieba 是一个python实现的中文分词组件,在中文分词界非常出名,支持简、繁体中文,高级用户还可以加入自定义词典以提高分词的准确率。
另外它还自带有关键词摘取算法。
pandas 是基于NumPy 的大数据处理工具,基本数据结构有(二维表)DataFrame,(一维数组)Series。
本次实验中,我们主要使用pandas的DataFrame,加载、保存csv数据源,处理数组进行去重、统计。
实验数据为百度随意打开的新闻,请读者自行按下表格式准备
第一行将代码标记为utf-8编码,避免出现处理非ascii字符时的错误
载入需要用到的模块,as是给模块取个别名,输入的时候不用输那么长的单词。
嗯,反正你别问我为什么不给jieba取别名
默认情况下,pd显示的文本长度为50,超出部分显示为省略号,我们修改一下,以方便观察数据(文章内容)
读取我们的实验数据,将所有列设置为string,编码指定utf-8,第一行为列头
我们直接在下一个Cell中输入变量rows
,观察载入的结果
对于普通分词,我们需要将停用词载入到一个数组中,在分词后逐一比较关键词是否为停用词
对于TF-IDF,我们只需要告诉组件停用词库,它将自己载入词库并使用它
接下来我们就要对所有文章进行分词了,先声明一个数组,用于保存分词后的关键字,此数组每行保存一个关键字对象。
关键字对象有两个属性:
# 保存全局分词,用于词频统计
#TextRank 关键词抽取,只获取固定词性 #停用词判断,如果当前的关键词不在停用词库中才进行记录 #TextRank 关键词抽取,只获取固定词性
观察分词后的关键字,发现全是utf-8编码后的文字,暂时不管,我们先将这个数组转换为DataFrame对象,调用groupby方法和sum方法进行统计汇总。
# 将结果数组转为df序列
#TextRank 关键词抽取,只获取固定词性
本次实验,我们学习了如何使用jieba模块进行中文分词与关键字提取,结果各有千秋:
总之,我们应根据我们的目标去选择适当的分词方法。
Python大数据:商品评论的情感倾向分析
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。