热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

中文分词工具探析(二):Jieba

【开源中文分词工具探析】系列:开源中文分词工具探析(一):ICTCLAS(NLPIR)开源中文分词工具探析(二

【开源中文分词工具探析】系列:

  1. 开源中文分词工具探析(一):ICTCLAS (NLPIR)
  2. 开源中文分词工具探析(二):Jieba
  3. 开源中文分词工具探析(三):Ansj
  4. 开源中文分词工具探析(四):THULAC
  5. 开源中文分词工具探析(五):FNLP
  6. 开源中文分词工具探析(六):Stanford CoreNLP
  7. 开源中文分词工具探析(七):LTP

1. 前言

Jieba是由fxsjy大神开源的一款中文分词工具,一款属于工业界的分词工具——模型易用简单、代码清晰可读,推荐有志学习NLP或Python的读一下源码。与采用分词模型Bigram + HMM 的ICTCLAS 相类似,Jieba采用的是Unigram + HMM。Unigram假设每个词相互独立,则分词组合的联合概率:

\begin{equation}
P(c_1^n) = P(w_1^m) = \prod_i P(w_{i})
\label{eq:unigram}
\end{equation}

在Unigram分词后用HMM做未登录词识别,以修正分词结果。

2. 分解

以下源码分析基于jieba-0.36版本。

分词模式

Jieba支持的三种分词模式:全模式、精确模式、搜索引擎模式。分词函数jieba.cut()中有两个模式调节参数cut_allHMM,分别表示是否采用全模式(若否,则为精确模式)、是否使用HMM。这两个参数的组合对应于如下分词模式:

  • cut_all=True, HMM=_对应于全模式,即所有在词典中出现的词都会被切分出来,实现函数为__cut_all;
  • cut_all=False, HMM=False对应于精确模式且不使用HMM;按Unigram语法模型找出联合概率最大的分词组合,实现函数为__cut_DAG;
  • cut_all=False, HMM=True对应于精确模式且使用HMM;在联合概率最大的分词组合的基础上,HMM识别未登录词,实现函数为__cut_DAG_NO_HMM

另一个分词函数jieba.cut_for_search()对应于搜索引擎模式,对长词进行更细粒度的切分:

def cut_for_search(sentence, HMM=True):"""Finer segmentation for search engines."""words = cut(sentence, HMM=HMM)for w in words:if len(w) > 2:for i in xrange(len(w) - 1):gram2 = w[i:i + 2]if FREQ.get(gram2):yield gram2if len(w) > 3:for i in xrange(len(w) - 2):gram3 = w[i:i + 3]if FREQ.get(gram3):yield gram3yield w

从上面的代码中,可以看出:对于长度大于2的词,依次循环滚动取出在前缀词典中的二元子词;对于长度大于3的词,依次循环滚动取出在前缀词典中的三元子词。至于前缀词典是什么,且看下一小节。

词典检索

为了检索词典中的词时,一般采取的思路是构建Trie树——利用了字符串的公共前缀,以缩短查询时间。作者当时也是这样做的,用了两个dict,trie dict用于保存trie树,lfreq dict用于存储词 -> 词频:

def gen_trie(f_name): lfreq = {} trie = {} ltotal = 0.0 with open(f_name, 'rb') as f: lineno = 0 for line in f.read().rstrip().decode('utf-8').split('\n'): lineno += 1 try: word,freq,_ = line.split(' ') freq = float(freq) lfreq[word] = freq ltotal+=freq p = trie for c in word: if c not in p: p[c] ={} p = p[c] p['']='' #ending flag except ValueError, e: logger.debug('%s at line %s %s' % (f_name, lineno, line)) raise ValueError, e return trie, lfreq, ltotal

何不将前缀信息也放到lfreq中呢?Pull request 187中便有人提出来并实现了,还给lfreq取了个好听的名字“前缀字典”。

分词DAG

一个句子所有的分词组合构成了有向无环图(Directed Acyclic Graph, DAG)\(G=(V,E)\),一个词对应与DAG中的的一条边\(e \in E\),边的起点为词的初始字符,边的结点为词的结束字符。jieba.get_DAG()函数实现切分句子得到DAG:

sentence = "印度报业托拉斯"
dag = jieba.get_DAG(sentence)
# {0: [0, 1, 6], 1: [1], 2: [2, 3], 3: [3], 4: [4, 5, 6], 5: [5, 6], 6: [6]}

DAG是用dict表示的,key为边的起点,value为边的终点集合,比如:上述例子中4 -> 6表示词“托拉斯”。

求解Unigram模型

对于Unigram模型下的联合概率\eqref{eq:unigram}求对数:

\[ \begin{aligned} \arg \max \prod_i P(w_i) & = \arg \max \log \prod_i P(w_i)\\ & = \arg \max \sum_i \log P(w_i) \end{aligned} \]

将词频的log值作为图\(G\)边的权值,从图论的角度出发,将最大概率问题变成了最大路径问题;是不是与ICTCLAS的处理思路有异曲同工之妙。在上面的DAG中,节点0表示源节点,节点m-1表示尾节点;则\(V=\{0, \cdots , m-1 \}\),且DAG满足如下性质:

\[ v > u, \quad \forall \ (u,v) \in E \]

即DAG顶点的序号的顺序与图流向是一致的。Jieba用动态规划(DP)来求解最大路径问题,假设用\(d_i\)标记源节点到节点i的最大路径的值,则有

\[ d_i = \max_{(j,i) \in E} \ \{ d_j+w(j,i) \} \]

其中,\(w(j,i)\)表示词\(c_j^i\)的词频log值,\(w(i,i)\)表示字符\(c_i\)独立成词的词频log值。在求解上述式子时,需要知道所有节点i的前驱节点j;然后DAG中只有后继结点list。在这里,作者巧妙地用到了一个trick——从尾节点m-1往前推算的最优解等价于从源节点0往后推算的。那么,用\(r_i\)标记节点i到尾节点的最大路径的值,则

\[ r_i = \max_{(i,j) \in E} \ \{ r_j+w(i,j) \} \]

def calc(sentence, DAG, route):N = len(sentence)route[N] = (0, 0)logtotal = log(total)for idx in xrange(N - 1, -1, -1):# r[i] = max { log P(c_{i}^{x}) + r(x)}route[idx] = max((log(FREQ.get(sentence[idx:x + 1]) or 1) -logtotal + route[x + 1][0], x) for x in DAG[idx])

关于HMM识别未登录词,可看我之前写的一篇《【中文分词】隐马尔可夫模型HMM》. 至此,Jieba完成了一个非常漂亮实用的分词模型。



推荐阅读
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • Python爬虫中使用正则表达式的方法和注意事项
    本文介绍了在Python爬虫中使用正则表达式的方法和注意事项。首先解释了爬虫的四个主要步骤,并强调了正则表达式在数据处理中的重要性。然后详细介绍了正则表达式的概念和用法,包括检索、替换和过滤文本的功能。同时提到了re模块是Python内置的用于处理正则表达式的模块,并给出了使用正则表达式时需要注意的特殊字符转义和原始字符串的用法。通过本文的学习,读者可以掌握在Python爬虫中使用正则表达式的技巧和方法。 ... [详细]
  • 本文介绍了在iOS开发中使用UITextField实现字符限制的方法,包括利用代理方法和使用BNTextField-Limit库的实现策略。通过这些方法,开发者可以方便地限制UITextField的字符个数和输入规则。 ... [详细]
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • iOS超签签名服务器搭建及其优劣势
    本文介绍了搭建iOS超签签名服务器的原因和优势,包括不掉签、用户可以直接安装不需要信任、体验好等。同时也提到了超签的劣势,即一个证书只能安装100个,成本较高。文章还详细介绍了超签的实现原理,包括用户请求服务器安装mobileconfig文件、服务器调用苹果接口添加udid等步骤。最后,还提到了生成mobileconfig文件和导出AppleWorldwideDeveloperRelationsCertificationAuthority证书的方法。 ... [详细]
author-avatar
敏佳的晴__丶天
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有