中文分词

作者: 我为峰2014 | 来源:发表于2018-01-11 16:15 被阅读177次

    【转】https://zhuanlan.zhihu.com/p/22047433?iam=6e4e2b01ef856ed9c067d5f1560f9d56&utm_source=qq&utm_medium=social

    一个中文文本从形式上看是由汉字(包括标点符号等)组成的一个字符串。由字可组成词,由词可组成句子,进而由一些句子组成段、节、章、篇。可见,如果需要处理一篇中文语料,从中正确的识别出词是一件非常基础而重要的工作。

    1、中文分词概述

    显而易见,中文以字为基本书写单位,词语之间没有明显的区分标记。中文分词就是由机器在词与词之间加上标记进行区分。例如:

    输入: 我是学生。

    输出: 我/是/学生/。

    1.1 中文分词的关键问题

    中文分词的关键问题为:切分歧义消解和未登录词识别

    1.2 歧义切分定义

    歧义切分的表示可以由下示例:

    输入待切分句子:提高人民生活水平

    可以切分输出 :提高/人民/生活/水平

    或者切分输出:提/高人/民生/活水/平

    明显第二个输出为歧义切分

    1.3未登录词定义

    常见的未登录词有实体名词、专有名词与新词

    实体名词包括有:

    中国人名:李素丽 老张 李四 王二麻子

    中国地名:定福庄 白沟 三义庙 韩村 河马甸

    翻译人名:乔治•布什 叶利钦 包法利夫人 酒井法子

    翻译地名:阿尔卑斯山 新奥尔良 约克郡

    机构名 :方正公司 联想集团 国际卫生组织 外贸部

    商标字号:非常可乐 乐凯 波导 杉杉 同仁堂

    专业术语和新词语

    专业术语:万维网 主机板 模态 逻辑 贝叶斯算法

    缩略语 :三个代表 五讲四美 打假 扫黄打非 计生办

    新词语 :卡拉OK 波波族 美刀 港刀

    未登录词没有明确边界,缺少英语中的分隔符、大小写、词的形态、冠词等语法信息,识别比较困难。

    因此通常每一类未登录词都要构造专门的识别算法。

    2、分词主要技术方法

    2.1 基于词典的分词

    词典中一般存储着:词、词频、词性等信息,可以通过统计标注好的熟语料和常用词典得到。

    基于词典分词方法首先需要对句子进行原子切分,即找出句子中可能蕴含组成的所有词,然后构成词图。还是之前例子,输入:

    提高人民生活水平

    输出所有包括的词:

    提 —提高

    高 —高人

    人 —人民

    民 —民生

    生—生活

    活—活水

    水 —水平

    则可以构成词图如下:

    词图.jpg

    上述工作主要重点是词典存储于并快速匹配,多采用双数组Tie树的方法生成词典树,用自动机匹配词串。

    2.2词典分词的歧义消解问题

    歧义消解可以转换为对于上述在词图上寻找统计意义上的最佳路径。常用一元、二元模型进行。

    基于一元模型进行评价:

    统计词表中每个词的词频,并将其转化为路径代价C=-log(f/N)切分路径的代价为路径上所有词的代价之和寻求代价最小的路径。上述例子就是根据词典中<提高><高人><人民><民生><生活><活水><水平><平>这几个词的词频f,认为词频越高的路径代价越小,找出最短的路径。

    基于二元模型进行评价:

    相对于一元模型,二元模型还需要一个词转移统计词典,例如记录了<提高>衔接<人民>的次数,词转移统计词典实质上是一个稀疏矩阵。基于二元模型进行评价需要在一元模型的基础上增加转移路径代价。词典中转移次数多的衔接认为该衔接转移路径代价小。计算方法可以用Viterbi算法。

    2.3词典分词的未登陆词问题

    简单来说,可以将未登陆词的识别转换成序列标注问题即打标签,然后用HMM或其它统计学习方法求解。例如中国人名识别可以表示为(姓+名)的形式,例如对于一个人名:金三胖 可以正确标注序列为:金/姓 三胖/名,则人名可以识别出来。具体可参见张华平相关论文《基于层叠隐马尔可夫模型的中文命名实体识别》、《基于角色标注的中国人名自动识别研究》、《基于角色标注的中文机构名识别》。

    2.4基于字的分词

    基于字的分词可以平衡的看待词表词和未登录词的识别问题。

    汉语中词都是有字组成的,可以将分词视为字的序列标注问题。例如对于“占”这个字可以有以下词位标注:

    • 词首B 占领

    • 词尾E 抢占

    • 词中M 独占鳌头

    • 单字词S 已占全国

    基于字的分词实现很简单,例如对于句子

    上海/计划/到/本/世纪/末/实现/人均/国内/生产/总值/五千美元/。

    可以有如下词位序列标注:

    上/B海/E计/B划/E到/S本/S世/B纪/E末/S实/B现/E人/B均/E国/B内/E生/B产/E总/B值/E五/B千/M美/M元/E。/S

    根据标注BMES实现了分词。

    转换成序列标注问题后常用算法有HMM (隐马模型)、MEMM(最大熵隐马模型)、CRF等。下面简单比较一下:

    隐马模型一个最大的缺点就是由于其输出独立性假设,导致其不能考虑上下文的特征,限制了特征的选择。

    最大熵隐马模型则解决了隐马的问题,可以任意选择特征,但由于其在每一节点都要进行归一化,所以只能找到局部的最优值,同时也带来了标记偏见的问题,即凡是训练语料中未出现的情况全都忽略掉。

    条件随机场则很好的解决了这一问题,他并不在每一个节点进行归一化,而是所有特征进行全局归一化,因此可以求得全局的最优值。

    2.5 主要分词技术评价

    • 基于词典的分词优点:

    速度快,效率高,易修改,灵活性强。

    • 基于词典的分词缺点:

    主要依赖词典和规则库,对于歧义词和未登录词的识别能力较低。

    • 基于字的分词的优点:

    对于歧义词和未登录词的识别能力较好。

    • 基于字的分词的缺点:

    (1)模型体积大占内存。例如一个可供生产环境用的CRF模型至少使用前中后3个字符的组合做特征模板,在一两百兆的语料上训练,模型体积至少上百兆。

    (2)速度慢。相较于基于词语的BiGram分词器,一个拖速度的地方是特征函数的查询次数多、速度慢,另一个弱点则是概率图的节点更多(4倍文本长度个节点,4是BMES标签的个数)。

    (3)不易修改。有时候用户对分词结果不满意,却无法方便地修正它。包括CRF在内的其他模型都需要重新训练,或者修改代码。而基于词语的NGram词典和词频词典可以轻松修改。


    在自然语言处理过程中,为了能更好地处理句子,往往需要把句子拆开分成一个一个的词语,这样能更好的分析句子的特性,这个过程叫做——分词.

    Github上已经有造好的轮子了,用别人的吧,而且,假如自己造的轮子在短时间内也没有别人的好用,废话少说,我们看看jieba中文分词。

    结巴分词支持三种分词模式:

    1. 精确模式,试图将句子最精确地切开,适合文本分析;

    2. 全模式,把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义;

    3. 搜索引擎模式,在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。

    算法:

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

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

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

    (这应该是分词的原理,以后挑个好日子,坐下来,好好地去梳理下)

    主要方法:

    • 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 为默认分词器,所有全局分词相关函数都是该分词器的映射。例如:

    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))
    
    输出:
    Building prefix dict from the default dictionary ...
    Dumping model to file cache C:\Users\lenovo\AppData\Local\Temp\jieba.cache
    Loading model cost 5.787 seconds.
    Prefix dict has been built succesfully.
    Full Mode: 我/ 来到/ 北京/ 清华/ 清华大学/ 华大/ 大学
    Default Mode: 我/ 来到/ 北京/ 清华大学
    他, 来到, 了, 网易, 杭研, 大厦
    小明, 硕士, 毕业, 于, 中国, 科学, 学院, 科学院, 中国科学院, 计算, 计算所, ,, 后, 在, 日本, 京都, 大学, 日本京都大学, 深造
    

    添加自定义词典(如果觉得jieba自己的词典不够,你还可以自己添加)。

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

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

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

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

    调整词典

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

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

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

    关键词提取

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

    • 基于 TextRank 算法的关键词抽取。

    词性标注

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

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

    并行分词

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

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

    Tokenize

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

    当然,你要是还想更加深入的了解,推荐《NLP汉语自然语言处理》

    书籍简介

    这本书是一本研究汉语自然语言处理方面的基础性,综合性书籍,涉及NLP的语言理论,算法和工程的方方面面,内容复杂。

    本书包括NLP的语言理论部分,算法部分,案例部分,涉及汉语的发展历史,传统的句法理论,认知语言理论。需要指出的是系统的介绍认知语言学和算法设计相结合的中文NLP书籍,并从认识语言学的视角重新认识和分析了NLP的句法和语义相结合的数据结构。

    分词

    中文NLP比外文要难,难再第一步就是要将文本进行切词。我们知道中文常用字也就3500左右,但是单字往往意义不多,对理解句子的意思帮助不大。而且中文词之间没有空格等标识符,这增加了NLP的难度。

    NLP第一步,就是从分词开始,目前市面上有ICTCLASS,jieba,HanNLP等,了解其分词算法原理,对更好的学习编程,使用编程语言处理文本数据有好处。

    既然,我们掌握了基本的分词技术,那就来制作一个词云吧

    用到的工具

    1. 原始数据:txt格式,可以用爬虫爬点网页数据做原始数据。为简单就先用txt练手好了。

    2. 提取关键词:jieba分词、停用词表

    3. 在线词云生成工具:TAGUL

    简单分析一下

    生成词云最关键的问题是中文分词,统计分析各个词的权重(权重较高的字体显示较大)。这些问题jieba分词已经帮我们解决了。我们只需要

    import jieba.analyse
    

    使用

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

    方法即可,当然只是提取关键词还是不够的,因为有些没有意义的常用词诸如“我的”、“或者”、“一个”等词,会出现在结果里面,还需要一个“停用词表”来帮我们过滤结果。

    我们的目标是提取关键词,并得到“关键词+制表符+权重”的文本,这里关键词和权重用制表符隔开是为了在用在线工具的时候,能顺利导入权重的值,决定词的大小(size)。

    步骤:

    1. 安装jieba pip install jieba

    2. 准备好txt文件和停用词表(网上可以下载到,txt格式即可)

    3. 编写代码

    代码

    import jieba.analyse
    ​
    path = '你的txt文件路径'
    file_in = open(path, 'r',encoding='utf-8',errors='ignore')
    content = file_in.read()
    ​
    try:
     jieba.analyse.set_stop_words('你的停用词表路径')
     tags = jieba.analyse.extract_tags(content, topK=100, withWeight=True)
     for v, n in tags:
     #权重是小数,为了凑整,乘了一万
     print( v + '\t' + str(int(n * 10000)))
    ​
    finally:
     file_in.close()
    

    打开TAGUL,开始制作词云,把结果贴进import words里

    TAGUL的教程https://www.zhihu.com/question/35976761/answer/67023767?from=profile_answer_card

    相关文章

      网友评论

      本文标题:中文分词

      本文链接:https://www.haomeiwen.com/subject/wactoxtx.html