精华内容
下载资源
问答
  • Python中文分词模块结巴分词算法过程的理解和分析 结巴分词是国内程序员用python开发的一个中文分词模块, 源码已托管在github, 地址在: https://github.com/fxsjy/jieba] 作者的文档写的不是很全, 只写了...

    本文是从我的github上转过来的

    对Python中文分词模块结巴分词算法过程的理解和分析

    结巴分词是国内程序员用python开发的一个中文分词模块, 源码已托管在github, 地址在: https://github.com/fxsjy/jieba]

    作者的文档写的不是很全, 只写了怎么用, 有一些细节的文档没有写.

    以下是作者说明文件中提到的结巴分词用到的算法:

    • 基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG) - 采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合 - 对于未登录词,采用了基于汉字成词能力的HMM模型,使用了Viterbi算法 因为最近有点兴趣想了解中文分词, 所以看了大量的资料, 对上面的三条有了一点点理解, 不再是两眼一抹黑了.转载请注明: 本文来自Django梦之队, http://ddtcms.com/blog/archive/2013/2/4/69/jieba-fenci-suanfa-lijie/

    先推荐大家看 http://www.52nlp.cn/] (我爱自然语言处理)的一系列关于概率、中文分词、HMM隐马尔科夫模型的文章, 然后再回头看看结巴分词的代码。

    然后推荐大家看看《解密搜索引擎技术实战:Lucene&Java精华版》,如果看不到, 可以看看这里的在线版, 虽然很短, 但是基本的思想都说明白了, 地址: http://book.51cto.com/art/201106/269050.htm] (4.6 概率语言模型的分词方法)

    看了这本书的第4章, 或者看了那个在线的那个章节的前后部分, 基本上可以说, 结巴分词, 在很大的程度上类似于书中说的例子。(上面的链接,是作者算法的第2条, 动态规划查找最大概率路径),当然, 结巴分词使用了HMM模型对未登录词进行识别(上面的第3条)

    至于第1条, 作者的trie树,可以看这篇文章对python中如何保存trie树结构的词典进行深刻理解:http://iregex.org/blog/trie-in-python.html] Trie in Python 这篇写的很好, 主要分析 Trie 实现原理,并给出 Python 的实现,还和正则联系到一起了。

    上面列出的三个链接, 里面讲到的知识, 基本上将结巴分词的算法都讲到了。所以有兴趣的人, 一定要仔细看我上面给的三个链接。

    下面, 结合自己看结巴分词的代码, 讲讲我自己看过资料和代码后的理解。

    先从作者的三条说起。

    第一条:基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG)

    这个看上面的trie树的python实现, 结巴分词自带了一个叫做dict.txt的词典, 里面有2万多条词, 包含了词条出现的次数(这个次数是于作者自己基于人民日报语料等资源训练得出来的)和词性. 这个第一条的trie树结构的词图扫描, 说的就是把这2万多条词语, 放到一个trie树中, 而trie树是有名的前缀树, 也就是说一个词语的前面几个字一样, 就表示他们具有相同的前缀, 就可以使用trie树来存储, 具有查找速度快的优势.

    聪明的人可能会想到把 dict.txt中所有的词汇全部删掉, 然后再试试结巴能不能分词, 结果会发现, 结巴依然能够分词, 不过分出来的词, 大部分的长度为2.这个就是第三条, 基于HMM来预测分词了.

    接着说DAG有向无环图, 就是后一句的 生成句子中汉字所有可能成词情况所构成的有向无环图, 这个是说的, 给定一个句子, 要你分词, 也就是给定一个 待分词的句子, 对这个句子进行生成有向无环图. 如果对有向无环图理解不了可以百度或者google搜索, 也可以看这篇 http://book.51cto.com/art/201106/269048.htm] 比较形象的用图来表示了一个待分词句子的切分情况.

    作者是怎么切分的呢? 1. 根据dict.txt生成trie树, 2, 对待分词句子, 根据dict.txt生成的trie树, 生成DAG, 实际上通俗的说, 就是对待分词句子, 根据给定的词典进行查词典操作, 生成几种可能的句子切分. dag是啥玩意?记录了啥呢? 作者的源码中记录的是句子中某个词的开始位置, 从0到n-1(n为句子的长度), 每个开始位置作为字典的键, value是个list, 其中保存了可能的词语的结束位置(通过查字典得到词, 开始位置+词语的长度得到结束位置)

    例如:{0:[1,2,3]} 这样一个简单的DAG, 就是表示0位置开始, 在1,2,3位置都是词, 就是说0~1, 0~2,0~3这三个起始位置之间的字符, 在dict.txt中是词语.

    第二条:采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合

    关于动态规划查找最大概率路径, 这个在一些大学课程中讲的很多了, 不熟悉的或者忘记了的翻翻百度就行了. 上面给的那个在线书籍的链接中也说的很明白了, 我这里就说说作者的代码:

    作者的代码中讲字典在生成trie树的同时, 也把每个词的出现次数转换为了频率. 关于频率和概率, 这里在啰嗦几句: 按照定义, 频率其实也是一个0~1之间的小数, 是 事件出现的次数/实验中的总次数, 因此在试验次数足够大的情况下, 频率约等于概率, 或者说频率的极限就是概率. 不过通常人们混淆的是频率和次数, 经常把频率等同于事件出现的次数, 比如这里就是某个词语出现的次数, 所以, 频率在引起混淆的时候, 对中国人来说, 还是先理解为出现次数, 然后理解发现有问题, 就理解为出现次数/总数这个比率吧.

    动态规划中, 先查找待分词句子中已经切分好的词语, 对该词语查找该词语出现的频率(次数/总数), 如果没有该词(既然是基于词典查找, 应该是有的), 就把词典中出现频率最小的那个词语的频率作为该词的频率, 也就是说P(某词语)=FREQ.get('某词语',min_freq), 然后根据动态规划查找最大概率路径的方法, 对句子从右往左反向计算最大概率(一些教科书上可能是从左往右, 这里反向是因为汉语句子的重心经常落在后面, 就是落在右边, 因为通常情况下形容词太多, 后面的才是主干, 因此, 从右往左计算, 正确率要高于从左往右计算, 这个类似于逆向最大匹配), P(NodeN)=1.0, P(NodeN-1)=P(NodeN)*Max(P(倒数第一个词))...依次类推, 最后得到最大概率路径, 得到最大概率的切分组合.

    第三条, 对于未登录词,采用了基于汉字成词能力的HMM模型,使用了Viterbi算法

    未登录词, 作者说的是什么意思? 其实就是词典 dict.txt 中没有记录的词. 上面说了, 把dict.txt中的所有词语都删除了, 结巴分词一样可以分词, 就是说的这个.

    怎么做到的? 这个就基于作者采用的HMM模型了, 中文词汇按照BEMS四个状态来标记, B是开始begin位置, E是end, 是结束位置, M是middle, 是中间位置, S是singgle, 单独成词的位置, 没有前, 也没有后. 也就是说, 他采用了状态为(B,E,M,S)这四种状态来标记中文词语, 比如北京可以标注为 BE, 即 北/B 京/E, 表示北是开始位置, 京是结束位置, 中华民族可以标注为BMME, 就是开始, 中间, 中间, 结束.

    经过作者对大量语料的训练, 得到了finalseg目录下的三个文件(来自结巴项目的issues):

    要统计的主要有三个概率表:

    prob_trans.py
    
    1)位置转换概率,即B(开头),M(中间),E(结尾),S(独立成词)四种状态的转移概率;
    
    {'B': {'E': 0.8518218565181658, 'M': 0.14817814348183422},
    
    'E': {'B': 0.5544853051164425, 'S': 0.44551469488355755},
    
    'M': {'E': 0.7164487459986911, 'M': 0.2835512540013088},
    
    'S': {'B': 0.48617017333894563, 'S': 0.5138298266610544}}
    
    
    P(E|B) = 0.851, P(M|B) = 0.149,说明当我们处于一个词的开头时,下一个字是结尾的概率
    
    要远高于下一个字是中间字的概率,符合我们的直觉,因为二个字的词比多个字的词更常见。
    
    
    
    prob_emit.py
    
    2)位置到单字的发射概率,比如P("和"|M)表示一个词的中间出现”和"这个字的概率;
    
    prob_start.py
    
    3) 词语以某种状态开头的概率,其实只有两种,要么是B,要么是S。这个就是起始向量, 就是HMM系统的最初模型状态
    

    实际上, BEMS之间的转换有点类似于2元模型, 就是2个词之间的转移 二元模型考虑一个单词后出现另外一个单词的概率,是N元模型中的一种。 例如:一般来说,"中国"之后出现"北京"的概率大于"中国"之后出现"北海"的概率,也就是:中国北京 比 中国北海出现的概率大些, 更有可能是一个中文词语.

    不过, 作者这里应该不是用的2元分词模型的, 这里的BEMS只提供了单个汉字之间的转换, 发射概率, 并没有提供粒度更大的, 基于词语的发射和转移概率, 当然, 也有可能我理解的不够深入.

    给定一个 待分词的句子, 就是观察序列, 对HMM(BEMS)四种状态的模型来说, 就是为了找到一个最佳的BEMS序列, 这个就需要使用viterbi算法来得到这个最佳的隐藏状态序列, 具体的python版的viterbi算法请看维基百科:http://zh.wikipedia.org/wiki/%E7%BB%B4%E7%89%B9%E6%AF%94%E7%AE%97%E6%B3%95 维特比算法

    通过作者之前训练得到的概率表和viterbi算法, 就可以得到一个概率最大的BEMS序列, 按照B打头, E结尾的方式, 对待分词的句子重新组合, 就得到了分词结果. 比如 对待分词的句子 '全世界都在学中国话' 得到一个BEMS序列 [S,B,E,S,S,S,B,E,S] 这个序列只是举例, 不一定正确, 通过把连续的BE凑合到一起得到一个词, 单独的S放单, 就得到一个分词结果了: 上面的BE位置和句子中单个汉字的位置一一对应, 得到全/S 世界/BE 都/S 在/S 学/S 中国/BE 话/S 从而将句子切分为词语.

    以上, 就是作者这三条介绍的全部理解和分析, 对于其中任何术语不理解, 请使用搜索引擎.

    结巴分词的过程:

    1. 加载字典, 生成trie树

    2. 给定待分词的句子, 使用正则获取连续的 中文字符和英文字符, 切分成 短语列表, 对每个短语使用DAG(查字典)和动态规划, 得到最大概率路径, 对DAG中那些没有在字典中查到的字, 组合成一个新的片段短语, 使用HMM模型进行分词, 也就是作者说的识别新词, 即识别字典外的新词.

    3. 使用python的yield 语法生成一个词语生成器, 逐词语返回. 当然, 我认为直接返回list, 效果也差不到哪里去.

    另外谈谈结巴分词的不足和局限:

    1 在中文分词的时候, 字典起到的作用貌似不大, 因为基于单字的HMM(BEMS)模型貌似就可以分词了, 不管正确率如何, 总算能分了.字典起到的作用在后面说.说作用不大, 是因为没有字典也能分词. 另外, 生成了DAG之后, 又用动态规划, 觉得浪费步骤.小概率连乘下限可能溢出已修正, 就不多说了.

    1. 中文分词加载dict.txt这个字典后, 占用的内存为140多M, 觉得占用内存过多. 专业化的词典生成, 还不方便. 怎么训练自己的专用概率表, 就没有提供工具, 如果提供了训练自己的HMM模型工具, 估计更好.

    2. 没有那个字典的话, Trie和DAG都不起作用, 仅靠HMM模型的viterbi算法起作用, 因此看出词典的作用就是用来矫正HMM模型的分词结果, 但是HMM分词的结果生成方式是把B开始E结束的序列, 组合成一个词, 因此, 这种判断方法不一定正确, 比如BES能不能算作一个词的序列我觉得值得考虑.

    3. HMM是不是真的能够识别新词呢? 我认为是肯定的, 但是是要打折扣的. 这个跟作者训练的词库有关系, 新词的字出现的概率在一段时间内会井喷, 但在长期的语言现象中, 应该还是平稳的, 除非这个词从一出现就很流行, 而且会流行很长的时间.因此HMM识别新词的功能在时效性上是不足的, 他只能识别2个字的词, 对于3个字的新词, 估计就能力有限了. 这个有待于BEMS序列组合成词的算法的改变和新词获取算法的改变, 才能得到改善.

    4. 引入二元分词的判断, 可能对词典的依赖会降低一点, 现在的词典的使用就是为了弥补HMM在识别多字词方面能力欠佳的问题, 所以词典中保存的是3 ,4 个字的词语.

    5. 词性标注的问题, 在分词的时候, 不能同时识别词性, 因为分词的时候没有处理词性, 也就是说分词的时候, 没有语义分析的.词性标注的部分, 是使用另外的posseg模块进行的.还有一个问题是新词的词性可能没法识别, 同样这个是说那些3, 4字词.

    6. 对专有名词比如人名 地名 机构名 的识别, 不能说好.

    7. 文档太少了, 关于词性标注, 得到的结果没有一点分析, 词性来源于哪里都没有说明. 不利于大家一起改进.句法分析, 语义分析都是没有的.

    8. 词性标注应该也是基于BEMS标注进行的. 不知道是不是可以独立出来.就是说基于语义来标示词性或者基于词语在句子中的位置来做推断进行标注词性.

    9. 分词过程中, 不能获得这个句子中出现的词的次数信息, 或者说出现频率高的词, 不能用于抽取文章的关键词.

    第12次修改, 全文完, 欢迎拍砖.转载请注明来自Django梦之队, http://ddtcms.com/blog/archive/2013/2/4/69/jieba-fenci-suanfa-lijie/

    展开全文
  • 我的python环境是Anaconda3安装的,由于项目需要用到分词,使用jieba分词库,在此总结一下安装方法。安装说明=======代码对 Python 2/3 均兼容* 全自动安装:`easy_install jieba` 或者 `pip install jieba` / `pip3...

    我的python环境是Anaconda3安装的,由于项目需要用到分词,使用jieba分词库,在此总结一下安装方法。

    安装说明

    =======

    代码对 Python 2/3 均兼容

    * 全自动安装:`easy_install jieba` 或者 `pip install jieba` / `pip3 install jieba`

    * 半自动安装:先下载 http://pypi.python.org/pypi/jieba/ ,解压后运行 `python setup.py install`

    * 手动安装:将 jieba 目录放置于当前目录或者 site-packages 目录

    * 通过 `import jieba` 来引用

    我使用了第二种方法。

    首先上githup下载jieba分词库

    然后加压到任意目录

    打开cmd命令行窗口并切换到jieba目录下

    运行python setup.py install完成安装

    在项目中使用import jieba使用jieba分词库

    ==================================================================================================

    以下内容来自readme文件

    算法

    ========

    * 基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG)

    * 采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合

    * 对于未登录词,采用了基于汉字成词能力的 HMM 模型,使用了 Viterbi 算法

    主要功能

    =======

    1. 分词

    --------

    * `jieba.cut` 方法接受三个输入参数: 需要分词的字符串;cut_all 参数用来控制是否采用全模式;HMM 参数用来控制是否使用 HMM 模型

    * `jieba.cut_for_search` 方法接受两个参数:需要分词的字符串;是否使用 HMM 模型。该方法适合用于搜索引擎构建倒排索引的分词,粒度比较细

    * 待分词的字符串可以是 unicode 或 UTF-8 字符串、GBK 字符串。注意:不建议直接输入 GBK 字符串,可能无法预料地错误解码成 UTF-8

    * `jieba.cut` 以及 `jieba.cut_for_search` 返回的结构都是一个可迭代的 generator,可以使用 for 循环来获得分词后得到的每一个词语(unicode),或者用

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

    * `jieba.Tokenizer(dictionary=DEFAULT_DICT)` 新建自定义分词器,可用于同时使用不同词典。`jieba.dt` 为默认分词器,所有全局分词相关函数都是该分词器的映射。

    代码示例

    ```python

    #encoding=utf-8

    importjieba

    seg_list= jieba.cut("我来到北京清华大学", cut_all=True)print("Full Mode:" + "/".join(seg_list)) #全模式

    seg_list= jieba.cut("我来到北京清华大学", cut_all=False)print("Default Mode:" + "/".join(seg_list)) #精确模式

    seg_list= jieba.cut("他来到了网易杭研大厦") #默认是精确模式

    print(",".join(seg_list))

    seg_list= jieba.cut_for_search("小明硕士毕业于中国科学院计算所,后在日本京都大学深造") #搜索引擎模式

    print(",".join(seg_list))

    ```

    输出:

    【全模式】: 我/ 来到/ 北京/ 清华/ 清华大学/ 华大/ 大学

    【精确模式】: 我/ 来到/ 北京/ 清华大学

    【新词识别】:他, 来到, 了, 网易, 杭研, 大厦 (此处,“杭研”并没有在词典中,但是也被Viterbi算法识别出来了)

    【搜索引擎模式】: 小明, 硕士, 毕业, 于, 中国, 科学, 学院, 科学院, 中国科学院, 计算, 计算所, 后, 在, 日本, 京都, 大学, 日本京都大学, 深造

    2. 添加自定义词典

    ----------------

    ### 载入词典

    * 开发者可以指定自己自定义的词典,以便包含 jieba 词库里没有的词。虽然 jieba 有新词识别能力,但是自行添加新词可以保证更高的正确率

    * 用法: jieba.load_userdict(file_name) # file_name 为文件类对象或自定义词典的路径

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

    * 词频省略时使用自动计算的能保证分出该词的词频。

    **例如:**

    ```

    创新办 3 i

    云计算 5

    凱特琳 nz

    台中

    ```

    * 更改分词器(默认为 `jieba.dt`)的 `tmp_dir` 和 `cache_file` 属性,可分别指定缓存文件所在的文件夹及其文件名,用于受限的文件系统。

    * 范例:

    * 自定义词典:https://github.com/fxsjy/jieba/blob/master/test/userdict.txt

    * 用法示例:https://github.com/fxsjy/jieba/blob/master/test/test_userdict.py

    * 之前: 李小福 / 是 / 创新 / 办 / 主任 / 也 / 是 / 云 / 计算 / 方面 / 的 / 专家 /

    * 加载自定义词库后: 李小福 / 是 / 创新办 / 主任 / 也 / 是 / 云计算 / 方面 / 的 / 专家 /

    ### 调整词典

    * 使用 `add_word(word, freq=None, tag=None)` 和 `del_word(word)` 可在程序中动态修改词典。

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

    * 注意:自动计算的词频在使用 HMM 新词发现功能时可能无效。

    代码示例:

    ```pycon

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

    如果/放到/post/中将/出错/。

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

    494

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

    如果/放到/post/中/将/出错/。

    >>> print('/'.join(jieba.cut('「台中」正确应该不会被切开', HMM=False)))

    「/台/中/」/正确/应该/不会/被/切开

    >>> jieba.suggest_freq('台中', True)

    69

    >>> print('/'.join(jieba.cut('「台中」正确应该不会被切开', HMM=False)))

    「/台中/」/正确/应该/不会/被/切开

    ```

    * "通过用户自定义词典来增强歧义纠错能力" --- https://github.com/fxsjy/jieba/issues/14

    3. 关键词提取

    -------------

    ### 基于 TF-IDF 算法的关键词抽取

    `import jieba.analyse`

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

    * sentence 为待提取的文本

    * topK 为返回几个 TF/IDF 权重最大的关键词,默认值为 20

    * withWeight 为是否一并返回关键词权重值,默认值为 False

    * allowPOS 仅包括指定词性的词,默认值为空,即不筛选

    * jieba.analyse.TFIDF(idf_path=None) 新建 TFIDF 实例,idf_path 为 IDF 频率文件

    代码示例 (关键词提取)

    https://github.com/fxsjy/jieba/blob/master/test/extract_tags.py

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

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

    * 自定义语料库示例:https://github.com/fxsjy/jieba/blob/master/extra_dict/idf.txt.big

    * 用法示例:https://github.com/fxsjy/jieba/blob/master/test/extract_tags_idfpath.py

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

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

    * 自定义语料库示例:https://github.com/fxsjy/jieba/blob/master/extra_dict/stop_words.txt

    * 用法示例:https://github.com/fxsjy/jieba/blob/master/test/extract_tags_stop_words.py

    关键词一并返回关键词权重值示例

    * 用法示例:https://github.com/fxsjy/jieba/blob/master/test/extract_tags_with_weight.py

    ### 基于 TextRank 算法的关键词抽取

    * jieba.analyse.textrank(sentence, topK=20, withWeight=False, allowPOS=('ns', 'n', 'vn', 'v')) 直接使用,接口相同,注意默认过滤词性。

    * jieba.analyse.TextRank() 新建自定义 TextRank 实例

    算法论文: [TextRank: Bringing Order into Texts](http://web.eecs.umich.edu/~mihalcea/papers/mihalcea.emnlp04.pdf)

    #### 基本思想:

    1. 将待抽取关键词的文本进行分词

    2. 以固定窗口大小(默认为5,通过span属性调整),词之间的共现关系,构建图

    3. 计算图中节点的PageRank,注意是无向带权图

    #### 使用示例:

    见 [test/demo.py](https://github.com/fxsjy/jieba/blob/master/test/demo.py)

    4. 词性标注

    -----------

    * `jieba.posseg.POSTokenizer(tokenizer=None)` 新建自定义分词器,`tokenizer` 参数可指定内部使用的 `jieba.Tokenizer` 分词器。`jieba.posseg.dt` 为默认词性标注分词器。

    * 标注句子分词后每个词的词性,采用和 ictclas 兼容的标记法。

    * 用法示例

    ```pycon

    >>> import jieba.posseg as pseg

    >>> words = pseg.cut("我爱北京天安门")

    >>> for word, flag in words:

    ... print('%s %s' % (word, flag))

    ...

    我 r

    爱 v

    北京 ns

    天安门 ns

    ```

    5. 并行分词

    -----------

    * 原理:将目标文本按行分隔后,把各行文本分配到多个 Python 进程并行分词,然后归并结果,从而获得分词速度的可观提升

    * 基于 python 自带的 multiprocessing 模块,目前暂不支持 Windows

    * 用法:

    * `jieba.enable_parallel(4)` # 开启并行分词模式,参数为并行进程数

    * `jieba.disable_parallel()` # 关闭并行分词模式

    * 例子:https://github.com/fxsjy/jieba/blob/master/test/parallel/test_file.py

    * 实验结果:在 4 核 3.4GHz Linux 机器上,对金庸全集进行精确分词,获得了 1MB/s 的速度,是单进程版的 3.3 倍。

    * **注意**:并行分词仅支持默认分词器 `jieba.dt` 和 `jieba.posseg.dt`。

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

    ----------------------------------

    * 注意,输入参数只接受 unicode

    * 默认模式

    ```python

    result = jieba.tokenize(u'永和服装饰品有限公司')

    for tk in result:

    print("word %s start: %d end:%d" % (tk[0],tk[1],tk[2]))

    ```

    ```

    word 永和 start: 0 end:2

    word 服装 start: 2 end:4

    word 饰品 start: 4 end:6

    word 有限公司 start: 6 end:10

    ```

    * 搜索模式

    ```python

    result = jieba.tokenize(u'永和服装饰品有限公司', mode='search')

    for tk in result:

    print("word %s start: %d end:%d" % (tk[0],tk[1],tk[2]))

    ```

    ```

    word 永和 start: 0 end:2

    word 服装 start: 2 end:4

    word 饰品 start: 4 end:6

    word 有限 start: 6 end:8

    word 公司 start: 8 end:10

    word 有限公司 start: 6 end:10

    ```

    7. ChineseAnalyzer for Whoosh 搜索引擎

    --------------------------------------------

    * 引用: `from jieba.analyse import ChineseAnalyzer`

    * 用法示例:https://github.com/fxsjy/jieba/blob/master/test/test_whoosh.py

    8. 命令行分词

    -------------------

    使用示例:`python -m jieba news.txt > cut_result.txt`

    命令行选项(翻译):

    使用: python -m jieba [options] filename

    结巴命令行界面。

    固定参数:

    filename 输入文件

    可选参数:

    -h, --help 显示此帮助信息并退出

    -d [DELIM], --delimiter [DELIM]

    使用 DELIM 分隔词语,而不是用默认的' / '。

    若不指定 DELIM,则使用一个空格分隔。

    -p [DELIM], --pos [DELIM]

    启用词性标注;如果指定 DELIM,词语和词性之间

    用它分隔,否则用 _ 分隔

    -D DICT, --dict DICT 使用 DICT 代替默认词典

    -u USER_DICT, --user-dict USER_DICT

    使用 USER_DICT 作为附加词典,与默认词典或自定义词典配合使用

    -a, --cut-all 全模式分词(不支持词性标注)

    -n, --no-hmm 不使用隐含马尔可夫模型

    -q, --quiet 不输出载入信息到 STDERR

    -V, --version 显示版本信息并退出

    如果没有指定文件名,则使用标准输入。

    `--help` 选项输出:

    $> python -m jieba --help

    Jieba command line interface.

    positional arguments:

    filename input file

    optional arguments:

    -h, --help show this help message and exit

    -d [DELIM], --delimiter [DELIM]

    use DELIM instead of ' / ' for word delimiter; or a

    space if it is used without DELIM

    -p [DELIM], --pos [DELIM]

    enable POS tagging; if DELIM is specified, use DELIM

    instead of '_' for POS delimiter

    -D DICT, --dict DICT use DICT as dictionary

    -u USER_DICT, --user-dict USER_DICT

    use USER_DICT together with the default dictionary or

    DICT (if specified)

    -a, --cut-all full pattern cutting (ignored with POS tagging)

    -n, --no-hmm don't use the Hidden Markov Model

    -q, --quiet don't print loading messages to stderr

    -V, --version show program's version number and exit

    If no filename specified, use STDIN instead.

    延迟加载机制

    ------------

    jieba 采用延迟加载,`import jieba` 和 `jieba.Tokenizer()` 不会立即触发词典的加载,一旦有必要才开始加载词典构建前缀字典。如果你想手工初始 jieba,也可以手动初始化。

    import jieba

    jieba.initialize() # 手动初始化(可选)

    在 0.28 之前的版本是不能指定主词典的路径的,有了延迟加载机制后,你可以改变主词典的路径:

    jieba.set_dictionary('data/dict.txt.big')

    例子: https://github.com/fxsjy/jieba/blob/master/test/test_change_dictpath.py

    其他词典

    ========

    1. 占用内存较小的词典文件

    https://github.com/fxsjy/jieba/raw/master/extra_dict/dict.txt.small

    2. 支持繁体分词更好的词典文件

    https://github.com/fxsjy/jieba/raw/master/extra_dict/dict.txt.big

    下载你所需要的词典,然后覆盖 jieba/dict.txt 即可;或者用 `jieba.set_dictionary('data/dict.txt.big')`

    其他语言实现

    ==========

    结巴分词 Java 版本

    ----------------

    作者:piaolingxue

    地址:https://github.com/huaban/jieba-analysis

    结巴分词 C++ 版本

    ----------------

    作者:yanyiwu

    地址:https://github.com/yanyiwu/cppjieba

    结巴分词 Node.js 版本

    ----------------

    作者:yanyiwu

    地址:https://github.com/yanyiwu/nodejieba

    结巴分词 Erlang 版本

    ----------------

    作者:falood

    地址:https://github.com/falood/exjieba

    结巴分词 R 版本

    ----------------

    作者:qinwf

    地址:https://github.com/qinwf/jiebaR

    结巴分词 iOS 版本

    ----------------

    作者:yanyiwu

    地址:https://github.com/yanyiwu/iosjieba

    结巴分词 PHP 版本

    ----------------

    作者:fukuball

    地址:https://github.com/fukuball/jieba-php

    结巴分词 .NET(C#) 版本

    ----------------

    作者:anderscui

    地址:https://github.com/anderscui/jieba.NET/

    结巴分词 Go 版本

    ----------------

    + 作者: wangbin 地址: https://github.com/wangbin/jiebago

    + 作者: yanyiwu 地址: https://github.com/yanyiwu/gojieba

    系统集成

    ========

    1. Solr: https://github.com/sing1ee/jieba-solr

    分词速度

    =========

    * 1.5 MB / Second in Full Mode

    * 400 KB / Second in Default Mode

    * 测试环境: Intel(R) Core(TM) i7-2600 CPU @ 3.4GHz;《围城》.txt

    常见问题

    =========

    ## 1. 模型的数据是如何生成的?

    详见: https://github.com/fxsjy/jieba/issues/7

    ## 2. “台中”总是被切成“台 中”?(以及类似情况)

    P(台中) < P(台)×P(中),“台中”词频不够导致其成词概率较低

    解决方法:强制调高词频

    `jieba.add_word('台中')` 或者 `jieba.suggest_freq('台中', True)`

    ## 3. “今天天气 不错”应该被切成“今天 天气 不错”?(以及类似情况)

    解决方法:强制调低词频

    `jieba.suggest_freq(('今天', '天气'), True)`

    或者直接删除该词 `jieba.del_word('今天天气')`

    ## 4. 切出了词典中没有的词语,效果不理想?

    解决方法:关闭新词发现

    `jieba.cut('丰田太省了', HMM=False)`

    `jieba.cut('我们中出了一个叛徒', HMM=False)`

    **更多问题请点击**:https://github.com/fxsjy/jieba/issues?sort=updated&state=closed

    修订历史

    ==========

    https://github.com/fxsjy/jieba/blob/master/Changelog

    --------------------

    jieba

    ========

    "Jieba" (Chinese for "to stutter") Chinese text segmentation: built to be the best Python Chinese word segmentation module.

    Features

    ========

    * Support three types of segmentation mode:

    1. Accurate Mode attempts to cut the sentence into the most accurate segmentations, which is suitable for text analysis.

    2. Full Mode gets all the possible words from the sentence. Fast but not accurate.

    3. Search Engine Mode, based on the Accurate Mode, attempts to cut long words into several short words, which can raise the recall rate. Suitable for search engines.

    * Supports Traditional Chinese

    * Supports customized dictionaries

    * MIT License

    Online demo

    =========

    http://jiebademo.ap01.aws.af.cm/

    (Powered by Appfog)

    Usage

    ========

    * Fully automatic installation: `easy_install jieba` or `pip install jieba`

    * Semi-automatic installation: Download http://pypi.python.org/pypi/jieba/ , run `python setup.py install` after extracting.

    * Manual installation: place the `jieba` directory in the current directory or python `site-packages` directory.

    * `import jieba`.

    Algorithm

    ========

    * Based on a prefix dictionary structure to achieve efficient word graph scanning. Build a directed acyclic graph (DAG) for all possible word combinations.

    * Use dynamic programming to find the most probable combination based on the word frequency.

    * For unknown words, a HMM-based model is used with the Viterbi algorithm.

    Main Functions

    ==============

    1. Cut

    --------

    * The `jieba.cut` function accepts three input parameters: the first parameter is the string to be cut; the second parameter is `cut_all`, controlling the cut mode; the third parameter is to control whether to use the Hidden Markov Model.

    * `jieba.cut_for_search` accepts two parameter: the string to be cut; whether to use the Hidden Markov Model. This will cut the sentence into short words suitable for search engines.

    * The input string can be an unicode/str object, or a str/bytes object which is encoded in UTF-8 or GBK. Note that using GBK encoding is not recommended because it may be unexpectly decoded as UTF-8.

    * `jieba.cut` and `jieba.cut_for_search` returns an generator, from which you can use a `for` loop to get the segmentation result (in unicode).

    * `jieba.lcut` and `jieba.lcut_for_search` returns a list.

    * `jieba.Tokenizer(dictionary=DEFAULT_DICT)` creates a new customized Tokenizer, which enables you to use different dictionaries at the same time. `jieba.dt` is the default Tokenizer, to which almost all global functions are mapped.

    **Code example: segmentation**

    ```python

    #encoding=utf-8

    import jieba

    seg_list = jieba.cut("我来到北京清华大学", cut_all=True)

    print("Full Mode: " + "/ ".join(seg_list)) # 全模式

    seg_list = jieba.cut("我来到北京清华大学", cut_all=False)

    print("Default Mode: " + "/ ".join(seg_list)) # 默认模式

    seg_list = jieba.cut("他来到了网易杭研大厦")

    print(", ".join(seg_list))

    seg_list = jieba.cut_for_search("小明硕士毕业于中国科学院计算所,后在日本京都大学深造") # 搜索引擎模式

    print(", ".join(seg_list))

    ```

    Output:

    [Full Mode]: 我/ 来到/ 北京/ 清华/ 清华大学/ 华大/ 大学

    [Accurate Mode]: 我/ 来到/ 北京/ 清华大学

    [Unknown Words Recognize] 他, 来到, 了, 网易, 杭研, 大厦 (In this case, "杭研" is not in the dictionary, but is identified by the Viterbi algorithm)

    [Search Engine Mode]: 小明, 硕士, 毕业, 于, 中国, 科学, 学院, 科学院, 中国科学院, 计算, 计算所, 后, 在, 日本, 京都, 大学, 日本京都大学, 深造

    2. Add a custom dictionary

    ----------------------------

    ### Load dictionary

    * Developers can specify their own custom dictionary to be included in the jieba default dictionary. Jieba is able to identify new words, but you can add your own new words can ensure a higher accuracy.

    * Usage: `jieba.load_userdict(file_name)` # file_name is a file-like object or the path of the custom dictionary

    * The dictionary format is the same as that of `dict.txt`: one word per line; each line is divided into three parts separated by a space: word, word frequency, POS tag. If `file_name` is a path or a file opened in binary mode, the dictionary must be UTF-8 encoded.

    * The word frequency and POS tag can be omitted respectively. The word frequency will be filled with a suitable value if omitted.

    **For example:**

    ```

    创新办 3 i

    云计算 5

    凱特琳 nz

    台中

    ```

    * Change a Tokenizer's `tmp_dir` and `cache_file` to specify the path of the cache file, for using on a restricted file system.

    * Example:

    云计算 5

    李小福 2

    创新办 3

    [Before]: 李小福 / 是 / 创新 / 办 / 主任 / 也 / 是 / 云 / 计算 / 方面 / 的 / 专家 /

    [After]: 李小福 / 是 / 创新办 / 主任 / 也 / 是 / 云计算 / 方面 / 的 / 专家 /

    ### Modify dictionary

    * Use `add_word(word, freq=None, tag=None)` and `del_word(word)` to modify the dictionary dynamically in programs.

    * Use `suggest_freq(segment, tune=True)` to adjust the frequency of a single word so that it can (or cannot) be segmented.

    * Note that HMM may affect the final result.

    Example:

    ```pycon

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

    如果/放到/post/中将/出错/。

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

    494

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

    如果/放到/post/中/将/出错/。

    >>> print('/'.join(jieba.cut('「台中」正确应该不会被切开', HMM=False)))

    「/台/中/」/正确/应该/不会/被/切开

    >>> jieba.suggest_freq('台中', True)

    69

    >>> print('/'.join(jieba.cut('「台中」正确应该不会被切开', HMM=False)))

    「/台中/」/正确/应该/不会/被/切开

    ```

    3. Keyword Extraction

    -----------------------

    `import jieba.analyse`

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

    * `sentence`: the text to be extracted

    * `topK`: return how many keywords with the highest TF/IDF weights. The default value is 20

    * `withWeight`: whether return TF/IDF weights with the keywords. The default value is False

    * `allowPOS`: filter words with which POSs are included. Empty for no filtering.

    * `jieba.analyse.TFIDF(idf_path=None)` creates a new TFIDF instance, `idf_path` specifies IDF file path.

    Example (keyword extraction)

    https://github.com/fxsjy/jieba/blob/master/test/extract_tags.py

    Developers can specify their own custom IDF corpus in jieba keyword extraction

    * Usage: `jieba.analyse.set_idf_path(file_name) # file_name is the path for the custom corpus`

    * Custom Corpus Sample:https://github.com/fxsjy/jieba/blob/master/extra_dict/idf.txt.big

    * Sample Code:https://github.com/fxsjy/jieba/blob/master/test/extract_tags_idfpath.py

    Developers can specify their own custom stop words corpus in jieba keyword extraction

    * Usage: `jieba.analyse.set_stop_words(file_name) # file_name is the path for the custom corpus`

    * Custom Corpus Sample:https://github.com/fxsjy/jieba/blob/master/extra_dict/stop_words.txt

    * Sample Code:https://github.com/fxsjy/jieba/blob/master/test/extract_tags_stop_words.py

    There's also a [TextRank](http://web.eecs.umich.edu/~mihalcea/papers/mihalcea.emnlp04.pdf) implementation available.

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

    Note that it filters POS by default.

    `jieba.analyse.TextRank()` creates a new TextRank instance.

    4. Part of Speech Tagging

    -------------------------

    * `jieba.posseg.POSTokenizer(tokenizer=None)` creates a new customized Tokenizer. `tokenizer` specifies the jieba.Tokenizer to internally use. `jieba.posseg.dt` is the default POSTokenizer.

    * Tags the POS of each word after segmentation, using labels compatible with ictclas.

    * Example:

    ```pycon

    >>> import jieba.posseg as pseg

    >>> words = pseg.cut("我爱北京天安门")

    >>> for w in words:

    ... print('%s %s' % (w.word, w.flag))

    ...

    我 r

    爱 v

    北京 ns

    天安门 ns

    ```

    5. Parallel Processing

    ----------------------

    * Principle: Split target text by line, assign the lines into multiple Python processes, and then merge the results, which is considerably faster.

    * Based on the multiprocessing module of Python.

    * Usage:

    * `jieba.enable_parallel(4)` # Enable parallel processing. The parameter is the number of processes.

    * `jieba.disable_parallel()` # Disable parallel processing.

    * Example:

    https://github.com/fxsjy/jieba/blob/master/test/parallel/test_file.py

    * Result: On a four-core 3.4GHz Linux machine, do accurate word segmentation on Complete Works of Jin Yong, and the speed reaches 1MB/s, which is 3.3 times faster than the single-process version.

    * **Note** that parallel processing supports only default tokenizers, `jieba.dt` and `jieba.posseg.dt`.

    6. Tokenize: return words with position

    ----------------------------------------

    * The input must be unicode

    * Default mode

    ```python

    result = jieba.tokenize(u'永和服装饰品有限公司')

    for tk in result:

    print("word %s start: %d end:%d" % (tk[0],tk[1],tk[2]))

    ```

    ```

    word 永和 start: 0 end:2

    word 服装 start: 2 end:4

    word 饰品 start: 4 end:6

    word 有限公司 start: 6 end:10

    ```

    * Search mode

    ```python

    result = jieba.tokenize(u'永和服装饰品有限公司',mode='search')

    for tk in result:

    print("word %s start: %d end:%d" % (tk[0],tk[1],tk[2]))

    ```

    ```

    word 永和 start: 0 end:2

    word 服装 start: 2 end:4

    word 饰品 start: 4 end:6

    word 有限 start: 6 end:8

    word 公司 start: 8 end:10

    word 有限公司 start: 6 end:10

    ```

    7. ChineseAnalyzer for Whoosh

    -------------------------------

    * `from jieba.analyse import ChineseAnalyzer`

    * Example: https://github.com/fxsjy/jieba/blob/master/test/test_whoosh.py

    8. Command Line Interface

    --------------------------------

    $> python -m jieba --help

    Jieba command line interface.

    positional arguments:

    filename input file

    optional arguments:

    -h, --help show this help message and exit

    -d [DELIM], --delimiter [DELIM]

    use DELIM instead of ' / ' for word delimiter; or a

    space if it is used without DELIM

    -p [DELIM], --pos [DELIM]

    enable POS tagging; if DELIM is specified, use DELIM

    instead of '_' for POS delimiter

    -D DICT, --dict DICT use DICT as dictionary

    -u USER_DICT, --user-dict USER_DICT

    use USER_DICT together with the default dictionary or

    DICT (if specified)

    -a, --cut-all full pattern cutting (ignored with POS tagging)

    -n, --no-hmm don't use the Hidden Markov Model

    -q, --quiet don't print loading messages to stderr

    -V, --version show program's version number and exit

    If no filename specified, use STDIN instead.

    Initialization

    ---------------

    By default, Jieba don't build the prefix dictionary unless it's necessary. This takes 1-3 seconds, after which it is not initialized again. If you want to initialize Jieba manually, you can call:

    import jieba

    jieba.initialize() # (optional)

    You can also specify the dictionary (not supported before version 0.28) :

    jieba.set_dictionary('data/dict.txt.big')

    Using Other Dictionaries

    ===========================

    It is possible to use your own dictionary with Jieba, and there are also two dictionaries ready for download:

    1. A smaller dictionary for a smaller memory footprint:

    https://github.com/fxsjy/jieba/raw/master/extra_dict/dict.txt.small

    2. There is also a bigger dictionary that has better support for traditional Chinese (繁體):

    https://github.com/fxsjy/jieba/raw/master/extra_dict/dict.txt.big

    By default, an in-between dictionary is used, called `dict.txt` and included in the distribution.

    In either case, download the file you want, and then call `jieba.set_dictionary('data/dict.txt.big')` or just replace the existing `dict.txt`.

    Segmentation speed

    =========

    * 1.5 MB / Second in Full Mode

    * 400 KB / Second in Default Mode

    * Test Env: Intel(R) Core(TM) i7-2600 CPU @ 3.4GHz;《围城》.txt

    展开全文
  • 转载来自Django梦之队, ... 结巴分词是国内程序员用python开发的一个中文分词模块, 源码已托管在github, 地址在: https://github.com/fxsjy/jieba 作者的文档写的不是很全, 只写了怎么用, 有一些细节的文

    转载来自Django梦之队, http://ddtcms.com/blog/archive/2013/2/4/69/jieba-fenci-suanfa-lijie/

    结巴分词是国内程序员用python开发的一个中文分词模块, 源码已托管在github, 地址在: https://github.com/fxsjy/jieba

    作者的文档写的不是很全, 只写了怎么用, 有一些细节的文档没有写.

    以下是作者说明文件中提到的结巴分词用到的算法:

    基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG)
    采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合
    对于未登录词,采用了基于汉字成词能力的HMM模型,使用了Viterbi算法
    因为最近有点兴趣想了解中文分词, 所以看了大量的资料, 对上面的三条有了一点点理解, 不再是两眼一抹黑了.转载请注明: 本文来自Django梦之队, http://ddtcms.com/blog/archive/2013/2/4/69/jieba-fenci-suanfa-lijie/

    先推荐大家看 http://www.52nlp.cn/ (我爱自然语言处理)的一系列关于概率、中文分词、HMM隐马尔科夫模型的文章, 然后再回头看看结巴分词的代码。

    然后推荐大家看看《解密搜索引擎技术实战:Lucene&Java精华版》,如果看不到, 可以看看这里的在线版, 虽然很短, 但是基本的思想都说明白了, 地址: http://book.51cto.com/art/201106/269050.htm (4.6 概率语言模型的分词方法)

    看了这本书的第4章, 或者看了那个在线的那个章节的前后部分, 基本上可以说, 结巴分词, 在很大的程度上类似于书中说的例子。(上面的链接,是作者算法的第2条, 动态规划查找最大概率路径),当然, 结巴分词使用了HMM模型对未登录词进行识别(上面的第3条)

    至于第1条, 作者的trie树,可以看这篇文章对python中如何保存trie树结构的词典进行深刻理解:http://iregex.org/blog/trie-in-python.html Trie in Python 这篇写的很好, 主要分析 Trie 实现原理,并给出 Python 的实现,还和正则联系到一起了。

    上面列出的三个链接, 里面讲到的知识, 基本上将结巴分词的算法都讲到了。所以有兴趣的人, 一定要仔细看我上面给的三个链接。

    下面, 结合自己看结巴分词的代码, 讲讲我自己看过资料和代码后的理解。

    先从作者的三条说起。

    第一条:基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG)

    这个看上面的trie树的python实现, 结巴分词自带了一个叫做dict.txt的词典, 里面有2万多条词, 包含了词条出现的次数(这个次数是于作者自己基于人民日报语料等资源训练得出来的)和词性. 这个第一条的trie树结构的词图扫描, 说的就是把这2万多条词语, 放到一个trie树中, 而trie树是有名的前缀树, 也就是说一个词语的前面几个字一样, 就表示他们具有相同的前缀, 就可以使用trie树来存储, 具有查找速度快的优势.

    聪明的人可能会想到把 dict.txt中所有的词汇全部删掉, 然后再试试结巴能不能分词, 结果会发现, 结巴依然能够分词, 不过分出来的词, 大部分的长度为2.这个就是第三条, 基于HMM来预测分词了.

    接着说DAG有向无环图, 就是后一句的 生成句子中汉字所有可能成词情况所构成的有向无环图, 这个是说的, 给定一个句子, 要你分词, 也就是给定一个 待分词的句子, 对这个句子进行生成有向无环图. 如果对有向无环图理解不了可以百度或者google搜索, 也可以看这篇 http://book.51cto.com/art/201106/269048.htm 比较形象的用图来表示了一个待分词句子的切分情况.

    作者是怎么切分的呢? 1. 根据dict.txt生成trie树, 2, 对待分词句子, 根据dict.txt生成的trie树, 生成DAG, 实际上通俗的说, 就是对待分词句子, 根据给定的词典进行查词典操作, 生成几种可能的句子切分. dag是啥玩意?记录了啥呢? 作者的源码中记录的是句子中某个词的开始位置, 从0到n-1(n为句子的长度), 每个开始位置作为字典的键, value是个list, 其中保存了可能的词语的结束位置(通过查字典得到词, 开始位置+词语的长度得到结束位置)

    例如:{0:[1,2,3]} 这样一个简单的DAG, 就是表示0位置开始, 在1,2,3位置都是词, 就是说0~1, 0~2,0~3这三个起始位置之间的字符, 在dict.txt中是词语.

    第二条:采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合

    关于动态规划查找最大概率路径, 这个在一些大学课程中讲的很多了, 不熟悉的或者忘记了的翻翻百度就行了. 上面给的那个在线书籍的链接中也说的很明白了, 我这里就说说作者的代码:

    作者的代码中讲字典在生成trie树的同时, 也把每个词的出现次数转换为了频率. 关于频率和概率, 这里在啰嗦几句: 按照定义, 频率其实也是一个0~1之间的小数, 是 事件出现的次数/实验中的总次数, 因此在试验次数足够大的情况下, 频率约等于概率, 或者说频率的极限就是概率. 不过通常人们混淆的是频率和次数, 经常把频率等同于事件出现的次数, 比如这里就是某个词语出现的次数, 所以, 频率在引起混淆的时候, 对中国人来说, 还是先理解为出现次数, 然后理解发现有问题, 就理解为出现次数/总数这个比率吧.

    动态规划中, 先查找待分词句子中已经切分好的词语, 对该词语查找该词语出现的频率(次数/总数), 如果没有该词(既然是基于词典查找, 应该是有的), 就把词典中出现频率最小的那个词语的频率作为该词的频率, 也就是说P(某词语)=FREQ.get(‘某词语’,min_freq), 然后根据动态规划查找最大概率路径的方法, 对句子从右往左反向计算最大概率(一些教科书上可能是从左往右, 这里反向是因为汉语句子的重心经常落在后面, 就是落在右边, 因为通常情况下形容词太多, 后面的才是主干, 因此, 从右往左计算, 正确率要高于从左往右计算, 这个类似于逆向最大匹配), P(NodeN)=1.0, P(NodeN-1)=P(NodeN)*Max(P(倒数第一个词))…依次类推, 最后得到最大概率路径, 得到最大概率的切分组合.

    第三条, 对于未登录词,采用了基于汉字成词能力的HMM模型,使用了Viterbi算法

    未登录词, 作者说的是什么意思? 其实就是词典 dict.txt 中没有记录的词. 上面说了, 把dict.txt中的所有词语都删除了, 结巴分词一样可以分词, 就是说的这个.

    怎么做到的? 这个就基于作者采用的HMM模型了, 中文词汇按照BEMS四个状态来标记, B是开始begin位置, E是end, 是结束位置, M是middle, 是中间位置, S是singgle, 单独成词的位置, 没有前, 也没有后. 也就是说, 他采用了状态为(B,E,M,S)这四种状态来标记中文词语, 比如北京可以标注为 BE, 即 北/B 京/E, 表示北是开始位置, 京是结束位置, 中华民族可以标注为BMME, 就是开始, 中间, 中间, 结束.

    经过作者对大量语料的训练, 得到了finalseg目录下的三个文件(来自结巴项目的issues):

    要统计的主要有三个概率表:

    prob_trans.py
    1)位置转换概率,即B(开头),M(中间),E(结尾),S(独立成词)四种状态的转移概率;
    {‘B’: {‘E’: 0.8518218565181658, ‘M’: 0.14817814348183422},
    ‘E’: {‘B’: 0.5544853051164425, ‘S’: 0.44551469488355755},
    ‘M’: {‘E’: 0.7164487459986911, ‘M’: 0.2835512540013088},
    ‘S’: {‘B’: 0.48617017333894563, ‘S’: 0.5138298266610544}}

    P(E|B) = 0.851, P(M|B) = 0.149,说明当我们处于一个词的开头时,下一个字是结尾的概率
    要远高于下一个字是中间字的概率,符合我们的直觉,因为二个字的词比多个字的词更常见。

    prob_emit.py
    2)位置到单字的发射概率,比如P(“和”|M)表示一个词的中间出现”和”这个字的概率;
    prob_start.py
    3) 词语以某种状态开头的概率,其实只有两种,要么是B,要么是S。这个就是起始向量, 就是HMM系统的最初模型状态
    实际上, BEMS之间的转换有点类似于2元模型, 就是2个词之间的转移
    二元模型考虑一个单词后出现另外一个单词的概率,是N元模型中的一种。
    例如:一般来说,”中国”之后出现”北京”的概率大于”中国”之后出现”北海”的概率,也就是:中国北京 比 中国北海出现的概率大些, 更有可能是一个中文词语.

    不过, 作者这里应该不是用的2元分词模型的, 这里的BEMS只提供了单个汉字之间的转换, 发射概率, 并没有提供粒度更大的, 基于词语的发射和转移概率, 当然, 也有可能我理解的不够深入.

    给定一个 待分词的句子, 就是观察序列, 对HMM(BEMS)四种状态的模型来说, 就是为了找到一个最佳的BEMS序列, 这个就需要使用viterbi算法来得到这个最佳的隐藏状态序列, 具体的python版的viterbi算法请看维基百科:http://zh.wikipedia.org/wiki/%E7%BB%B4%E7%89%B9%E6%AF%94%E7%AE%97%E6%B3%95 维特比算法

    通过作者之前训练得到的概率表和viterbi算法, 就可以得到一个概率最大的BEMS序列, 按照B打头, E结尾的方式, 对待分词的句子重新组合, 就得到了分词结果. 比如 对待分词的句子 ‘全世界都在学中国话’ 得到一个BEMS序列 [S,B,E,S,S,S,B,E,S] 这个序列只是举例, 不一定正确, 通过把连续的BE凑合到一起得到一个词, 单独的S放单, 就得到一个分词结果了: 上面的BE位置和句子中单个汉字的位置一一对应, 得到全/S 世界/BE 都/S 在/S 学/S 中国/BE 话/S 从而将句子切分为词语.

    以上, 就是作者这三条介绍的全部理解和分析, 对于其中任何术语不理解, 请使用搜索引擎.

    结巴分词的过程:

    1. 加载字典, 生成trie树

    2. 给定待分词的句子, 使用正则获取连续的 中文字符和英文字符, 切分成 短语列表, 对每个短语使用DAG(查字典)和动态规划, 得到最大概率路径, 对DAG中那些没有在字典中查到的字, 组合成一个新的片段短语, 使用HMM模型进行分词, 也就是作者说的识别新词, 即识别字典外的新词.

    3. 使用python的yield 语法生成一个词语生成器, 逐词语返回. 当然, 我认为直接返回list, 效果也差不到哪里去.

    另外谈谈结巴分词的不足和局限:

    1 在中文分词的时候, 字典起到的作用貌似不大, 因为基于单字的HMM(BEMS)模型貌似就可以分词了, 不管正确率如何, 总算能分了.字典起到的作用在后面说.说作用不大, 是因为没有字典也能分词. 另外, 生成了DAG之后, 又用动态规划, 觉得浪费步骤.小概率连乘下限可能溢出已修正, 就不多说了.

    2. 中文分词加载dict.txt这个字典后, 占用的内存为140多M, 觉得占用内存过多. 专业化的词典生成, 还不方便. 怎么训练自己的专用概率表, 就没有提供工具, 如果提供了训练自己的HMM模型工具, 估计更好.

    3. 没有那个字典的话, Trie和DAG都不起作用, 仅靠HMM模型的viterbi算法起作用, 因此看出词典的作用就是用来矫正HMM模型的分词结果, 但是HMM分词的结果生成方式是把B开始E结束的序列, 组合成一个词, 因此, 这种判断方法不一定正确, 比如BES能不能算作一个词的序列我觉得值得考虑.

    4. HMM是不是真的能够识别新词呢? 我认为是肯定的, 但是是要打折扣的. 这个跟作者训练的词库有关系, 新词的字出现的概率在一段时间内会井喷, 但在长期的语言现象中, 应该还是平稳的, 除非这个词从一出现就很流行, 而且会流行很长的时间.因此HMM识别新词的功能在时效性上是不足的, 他只能识别2个字的词, 对于3个字的新词, 估计就能力有限了. 这个有待于BEMS序列组合成词的算法的改变和新词获取算法的改变, 才能得到改善.

    5. 引入二元分词的判断, 可能对词典的依赖会降低一点, 现在的词典的使用就是为了弥补HMM在识别多字词方面能力欠佳的问题, 所以词典中保存的是3 ,4 个字的词语.

    6. 词性标注的问题, 在分词的时候, 不能同时识别词性, 因为分词的时候没有处理词性, 也就是说分词的时候, 没有语义分析的.词性标注的部分, 是使用另外的posseg模块进行的.还有一个问题是新词的词性可能没法识别, 同样这个是说那些3, 4字词.

    7. 对专有名词比如人名 地名 机构名 的识别, 不能说好.

    8. 文档太少了, 关于词性标注, 得到的结果没有一点分析, 词性来源于哪里都没有说明. 不利于大家一起改进.句法分析, 语义分析都是没有的.

    9. 词性标注应该也是基于BEMS标注进行的. 不知道是不是可以独立出来.就是说基于语义来标示词性或者基于词语在句子中的位置来做推断进行标注词性.

    10. 分词过程中, 不能获得这个句子中出现的词的次数信息, 或者说出现频率高的词, 不能用于抽取文章的关键词.


    展开全文
  • 那你得先学会如何做中文文本分词。跟着我们的教程,一步步用Python来动手实践吧。需求在《如何用Python做词云》一文中,我们介绍了英文文本的词云制作方法。大家玩儿得可还高兴?文中提过,选择英文文本作为示例,是...

    打算绘制中文词云图?那你得先学会如何做中文文本分词。跟着我们的教程,一步步用Python来动手实践吧。

    721190534061

    需求

    在《如何用Python做词云》一文中,我们介绍了英文文本的词云制作方法。大家玩儿得可还高兴?

    文中提过,选择英文文本作为示例,是因为处理起来最简单。但是很快就有读者尝试用中文文本做词云了。按照前文的方法,你成功了吗?

    估计是不成功的。因为这里面缺了一个重要的步骤。

    观察你的英文文本。你会发现英文单词之间采用空格作为强制分隔符。

    例如:

    Yes Minister is a satirical British sitcom written by Sir Antony Jay and Jonathan Lynn that was first transmitted by BBC Television between 1980 and 1984, split over three seven-episode series.

    但是,中文的文本就没有这种空格区隔了。为了做词云,我们首先需要知道中文文本里面都有哪些“词”。

    你可能觉得这根本不是问题——我一眼就能看出词和词之间的边界!

    对,你当然可以。你可以人工处理1句、100句,甚至是10000句话。但是如果给你100万句话呢?

    这就是人工处理和电脑自动化处理的最显著区别——规模。

    别那么急着放弃啊,你可以用电脑来帮忙。

    你的问题应该是:如何用电脑把中文文本正确拆分为一个个的单词呢?

    这种工作,专业术语叫做分词。

    在介绍分词工具及其安装之前,请确认你已经阅读过《如何用Python做词云》一文,并且按照其中的步骤做了相关的准备工作,然后再继续依照本文的介绍一步步实践。

    分词

    中文分词的工具有很多种。有的免费,有的收费。有的在你的笔记本电脑里就能安装使用,有的却需要联网做云计算。

    今天给大家介绍的,是如何利用Python,在你的笔记本电脑上,免费做中文分词。

    我们采用的工具,名称很有特点,叫做“ 结巴分词 ”。

    为什么叫这么奇怪的名字?

    读完本文,你自己应该就能想明白了。

    我们先来安装这款分词工具。回到你的“终端”或者“命令提示符”下。

    721190534061

    进入你之前建立好的demo文件夹。

    输入以下命令:

    pip install jieba

    好了,现在你电脑里的Python已经知道该如何给中文分词了。

    数据

    在《如何用Python做词云》一文中,我们使用了英剧”Yes, minister“的维基百科介绍文本。这次我们又从维基百科上找到了这部英剧对应的中文页面。翻译名称叫做《是,大臣》。

    721190534061

    将网页正文拷贝下来之后,存入文本文件yes-minister-cn.txt,并且将这个文件移动到我们的工作目录demo下面。

    好了,我们有了用于分析的中文文本数据了。

    先别忙着编程序。正式输入代码之前,我们还需要做一件事情,就是下载一份中文字体文件。

    请到 这个网址 下载simsun.ttf。

    下载后,将这个ttf字体文件也移动到demo目录下,跟文本文件放在一起。

    代码

    在命令行下,执行:

    jupyter notebook

    浏览器会自动开启,并且显示如下界面。

    721190534061

    这里还有上一次词云制作时咱们的劳动成果。此时目录下多了一个文本文件,是"Yes, Minister"的中文介绍信息。

    打开这个文件,浏览一下内容。

    721190534061

    我们确认中文文本内容已经正确存储。

    回到Jupyter笔记本的主页面。点击New按钮,新建一个笔记本(Notebook)。在Notebooks里面,请选择Python 2选项。

    721190534061

    系统会提示我们输入Notebook的名称。为了和上次的英文词云制作笔记本区别,就叫它wordcloud-cn好了。

    721190534061

    我们在网页里唯一的代码文本框里,输入以下3条语句。输入后,按Shift+Enter键执行。

    filename = "yes-minister-cn.txt"

    with open(filename) as f:

    mytext = f.read()

    然后我们尝试显示mytext的内容。输入以下语句之后,还是得按Shift+Enter键执行。

    print(mytext)

    显示的结果如下图所示。

    721190534061

    既然中文文本内容读取没有问题,我们就开始分词吧。输入以下两行语句:

    import jieba

    mytext = " ".join(jieba.cut(mytext))

    系统会提示一些信息,那是结巴分词第一次启用的时候需要做的准备工作。忽略就可以了。

    721190534061

    分词的结果如何?我们来看看。输入:

    print(mytext)

    你就可以看到下图所示的分词结果了。

    721190534061

    单词之间已经不再紧紧相连,而是用空格做了区隔,就如同英文单词间的自然划分一样。

    你是不是迫不及待要用分词后的中文文本作词云了?

    可以,输入以下语句:

    from wordcloud import WordCloud

    wordcloud = WordCloud().generate(mytext)

    %pylab inline

    import matplotlib.pyplot as plt

    plt.imshow(wordcloud, interpolation='bilinear')

    plt.axis("off"

    激动地期待着中文词云的出现?

    可惜,你看到的词云是这个样子的。

    721190534061

    你是不是非常愤怒,觉得这次又掉坑里了?

    别着急,出现这样的结果,并不是分词或者词云绘制工具有问题,更不是因为咱们的教程步骤有误,只是因为字体缺失。词云绘制工具wordcloud默认使用的字体是英文的,不包含中文编码,所以才会方框一片。解决的办法,就是把你之前下载的simsun.ttf,作为指定输出字体。

    输入以下语句:

    from wordcloud import WordCloud

    wordcloud = WordCloud(font_path="simsun.ttf").generate(mytext)

    %pylab inline

    import matplotlib.pyplot as plt

    plt.imshow(wordcloud, interpolation='bilinear')

    plt.axis("off")

    这次你看到的输出图形就变成了这个样子:

    721190534061

    这样一来,我们就通过中文词云的制作过程,体会到了中文分词的必要性了。

    这里给你留个思考题,对比一下此次生成的中文词云,和上次做出的英文词云:

    721190534061

    这两个词云对应的文本都来自维基百科,描述的是同样一部剧,它们有什么异同?从这种对比中,你可以发现维基百科中英文介绍内容之间,有哪些有趣的规律?

    讨论

    掌握了本方法后,你自己做出了一张什么样的中文词云图?除了做词云以外,你还知道中文分词的哪些其他应用场景?欢迎留言,分享给大家。我们共同交流讨论。

    喜欢请点赞。还可以微信关注和置顶我的公众号“玉树芝兰”(nkwangshuyi)。

    如果你对数据科学感兴趣,不妨阅读我的系列教程索引贴《如何高效入门数据科学?》,里面还有更多的有趣问题及解法。

    展开全文
  • python之中文分词

    2021-01-06 18:16:56
    1)分词文件怎么写 2)jieba.cut()参数说明 5、搜索引擎模式 1、安装和使用jieba 直接用命令:pip3 install jieba就可以了,如图所示表示成功。 2、分词练习 import jieba if __name__ == '__main__': seg_gu=...
  • 1.解析文档中包含的shell命令。 2.整条命令解析。 3.有没有常用shell命令组成的txt包 4.求助 5.目前只能解析出英文,包含了多余的信息,怎么去除?
  • # -*- coding:UTF-8 -*- import urllib2 import re import jieba import jieba.analyse import sys reload(sys) sys.setdefaultencoding('utf-8') ... 这个是我到分词的程序,就是不会导入到excel中啊
  • 前两天一直在写爬虫,也是一直有心写个简单的搜索引擎吧,写出来肯定是没有Web界面的,本人不知道怎么地,对Web的代码一直有抵触心理。 搜索引擎嘛,我想要写出来必须要懂五个部分: 1、基础的多线程爬虫 2...
  • So,词云这个如此方便的可视化利器,怎么可以放过。 (CSDN 排版让人满意真的好难) 本文将基于爬虫得到的《三国演义》全文,借助jieba、wordcloud库进行分词并绘制词云; 词云类型由易到繁分为三类:普通型,特定...
  • 分词 | 概率最大中文分词python实现

    千次阅读 2018-10-22 16:21:09
    首先解释一下累计概率怎么计算:假如待分词的句子为“对外经济技术合作与交流不断扩大。”,候选词可能有“对”、“对外”、“外”、“经济”等。对于每个词的累计概率,等于它原来的概率乘上累计概率最大的左邻词的...
  • 在NLP中,数据清洗与分词往往是很多工作开始的第一步,大多数工作中只有中文语料数据需要进行分词,现有的分词工具也已经有了很多了,这里就不再多介绍了。英文语料由于其本身存在空格符所以无需跟中文语料同样处理...
  • 参考:https://blog.csdn.net/songzhilian22/article/details/49636725GitHub:https://github.com/likeyiyy/chinese_text_cluster---------------------------------------------------------------------参考:...
  • Python 中有个比较著名的分词库是结巴分词,从易用性来说对用户是非常友好的,但是准确度不怎么好。 这几天发现另外一个库,pkuseg-python,简单易用,跟现有开源工具相比提高了分词的准确率。 于是我想起...
  • python怎么提取关键词

    2019-03-20 23:32:49
    ``` import re ...用“jieba”好像是分词,不知道怎么才能匹配文章中指定的关键词,求大佬们指点指点 <br /> ## 目的:用“listk”里面的属性匹配“gg”文章看看有没有,有就保存到一个列表里
  • jieba库作为python中的第三方库,在平时是非常实用的,例如一些网站就是利用jieba库的中文分词搜索关键词进行工作。一、安装环境window + python二、安装方式在电脑命令符(cmd)中直接写进下面的语句:pip install ...
  • jieba库,它是Python中一个重要的第三方中文分词函数库。1.jieba的下载由于jieba是一个第三方函数库,所以需要另外下载。电脑搜索“cmd”打开“命令提示符”,然后输入“pip install jieba”,稍微等等就下载成功。...
  • 在NLP中,数据清洗与分词往往是很多工作开始的第一步,大多数工作中只有中文语料数据需要进行分词,现有的分词工具也已经有了很多了,这里就不再多介绍了。英文语料由于其本身存在空格符所以无需跟中文语料同样处理...
  • 怎么使用python中的jieba对csv 文件(文件有点大)内容分词后导入TXT中
  • 想要把一大段中文文本中所有的标点符号删除掉,然后分词制作语料库使用,大神们有没有办法呢?或者哪位大神有中文语料库给个链接好不好?我想做新闻的文本相似度分析,提取关键词的时候需要语料库。 谢谢大神们~~~~...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 127
精华内容 50
关键字:

python怎么分词

python 订阅