自然语言处理的首要任务是分词,将一段文本分割成独立的词语。

中文分词介绍

已经归纳的三种分词如下:
规则分词、统计分词、混合分词

  • 规则分词:
    通过设立人工词库,按照一定方式进行切分匹配。

正向最大匹配法(Maximum Match Method MM法)的基本思路,假定分词词典中最最长词为 i 个汉字字符,则首先切分待处理文档的前 i 个字符作为匹配子串,在分词词典中查找。如果找到则表示匹配成功,匹配子串作为一个词切分出来。如果在字典中找不到这个词,则匹配失败,然后将匹配字段中的最后一个字去掉对剩下的子串重新匹配。按照这个方法直到匹配成功。
逆向最大匹配算法(Reverse Maximum Match Method, RMM法):其算法描述和MM法基本一致,唯一的不同在于RMM法是从文本的后面开始匹配。
双向最大匹配法 (Bi-directction method):是将MM法和RMM法得到的结果进行比较,然后按照最大匹配原则,选取词数切分最少的作为结果。

  • 统计分词
    把每个词看做由单个字组成的,如果相连的两个字在不同的文本中出现词数越多,那么这两个词大概率是一个词,当出现的概率高于设定的阈值时我们认为这个”字组“可能会构成一个词。

基于统计的分词一般有两部分内容:

  • 建立统计语言模型
  • 对句子进行单词划分,对划分结果进行概率统计,获得概率最大分词方式。

Jieba中文分词工具

Jieba分词结合了基于规则和基于统计这两类方法实现中文分词。通过前缀词典构建可能的有向无环图,通过在该图中的多条分词路径找到最优路线,也就确定了具体分词。对于未记录在词典的词,其使用HMM模型,采用Viterbi算法进行推导(表示我也不知道这个是什么意思)。

Jieba提供三种分词模式:

  • 精确分词
    试图将句子最精确的分开,适合文文本分析。
  • 全模式分词
    把句子中所有可以成词的词语都扫描出来,速度快,但存在歧义。
  • 搜索引擎模式分词
    在精确模式的基础上,对长词再切分,提高召回率,适用于搜索引擎分词。

下面是简单的基于Jieba的三种中文分词示例。注意Python打印有中文的list会输出十六进制编码字符,需要特殊处理。

  • 首先是搭建环境
    开发环境配置安装中文分词框架

sudo pip install jieba

  • 安装uniout用于解决直接打印包含中文的list
    sudo pip install uniout

Jieba分词示例

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File  : jieba_1.py
# @Author: evenvi
# @Date  : 19-4-28
# @Desc  :

import jieba
import uniout # 中文显示

sent = '我要开发一个智能中文报告舆情分析系统'

seg_list = jieba.cut(sent, cut_all=True)
print('全局模式', '/'.join(seg_list))

seg_list = jieba.cut(sent, cut_all=False)
print('精确模式', '/'.join(seg_list))

seg_list = jieba.cut(sent)
print('默认精确模式', '/'.join(seg_list))

seg_list = jieba.cut_for_search(sent)
print('搜索引擎模式', '/'.join(seg_list))

JIeba中文分词实战 - 分析2019年政府工作报告,提取高频词Top10

高频词一般指出现频率较高且有用的词语,其一定程度上代表了文章所要表达的主要意思。通常可以作为热点、舆论焦点。
高频词提取就是自然语言处理中的TF(Term Frequency)策略。其主要的干扰项如下:

  • 标点符号:一般标点符号无任何价值,需要剔除
  • 停用词:像“的“ ”是“ ”了“无意义也要剔除

分析2019年政府工作报告前十的高频词语
报告原文 政府工作报告 http://www.gov.cn/premier/2019-03/16/content_5374314.htm
将文本复制下来存入文件 "2019gov.txt"

下面是具体的代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File  : jieba_gov_report.py
# @Author: evenvi
# @Date  : 19-4-28
# @Desc  : 使用Jieba对2019政府工作报告分词
import codecs
import uniout # 中文显示


# 读取待分词文本数据
def get_content(path, encoding='gbk'):
    with codecs.open(path, 'r', encoding=encoding
            , errors='ignore') as f:
        content = ''
        for l in f:
            l = l.strip()
            content += l
        return content

# 定义高频词函数
def get_TF(words, topK=10):
    tf_dic = {}
    for w in words:
        tf_dic[w] = tf_dic.get(w, 0) + 1
    return sorted(tf_dic.items(), key=lambda x:x[1], reverse=True)[:topK]

def main():
    import jieba

    reportContent = get_content('./data/reports/2019gov.txt', encoding='utf-8')

    split_words = list(jieba.cut(reportContent))
    print('样本之一:'+ reportContent.encode('utf-8') + '\r\n')
    print('样本分词效果:' + '/'.join(split_words).encode('utf-8')+ '\r\n')
    print('样本的topK(10)词语' + str(get_TF(split_words))+ '\r\n')

if __name__ == '__main__':
    main()

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File  : jieba_gov_report.py
# @Author: evenvi
# @Date  : 19-4-28
# @Desc  : 使用Jieba对2019政府工作报告分词
import codecs
import uniout # 中文显示


# 读取待分词文本数据
def get_content(path, encoding='gbk'):
    with codecs.open(path, 'r', encoding=encoding
            , errors='ignore') as f:
        content = ''
        for l in f:
            l = l.strip()
            content += l
        return content

# 定义高频词函数
def get_TF(words, topK=10):
    tf_dic = {}
    for w in words:
        tf_dic[w] = tf_dic.get(w, 0) + 1
    return sorted(tf_dic.items(), key=lambda x:x[1], reverse=True)[:topK]

def main():
    import jieba

    reportContent = get_content('./data/reports/2019gov.txt', encoding='utf-8')

    split_words = list(jieba.cut(reportContent))
    print('样本之一:'+ reportContent.encode('utf-8') + '\r\n')
    print('样本分词效果:' + '/'.join(split_words).encode('utf-8')+ '\r\n')
    print('样本的topK(10)词语' + str(get_TF(split_words))+ '\r\n')

if __name__ == '__main__':
    main()

分析得到高频词TOP10

样本的topK(10)词语[(u',', 806), (u'。', 612), (u'、', 324), (u'的', 216), (u'和', 187), (u'发展', 134), (u'改革', 92), (u'要', 88), (u'“', 63), (u'”', 63)]

显然停用词和标点符号占据了很高的位置,而这类词语对于把控文章毫无意义,需要将这些数据剔除。这里需要用到"停用词典”功能。
stop_words.utf8

修改后的代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File  : jieba_gov_report.py
# @Author: evenvi
# @Date  : 19-4-28
# @Desc  : 使用Jieba对2019政府工作报告分词
import codecs
import uniout # 中文显示


# 读取待分词文本数据
def get_content(path, encoding='gbk'):
    with codecs.open(path, 'r', encoding=encoding
            , errors='ignore') as f:
        content = ''
        for l in f:
            l = l.strip()
            content += l
        return content

# 定义高频词函数
def get_TF(words, topK=10):
    tf_dic = {}
    for w in words:
        tf_dic[w] = tf_dic.get(w, 0) + 1
    return sorted(tf_dic.items(), key=lambda x:x[1], reverse=True)[:topK]

def main():
    import jieba

    reportContent = get_content('./data/reports/2019gov.txt', encoding='utf-8')

    split_words = list(jieba.cut(reportContent))
    print('样本之一:'+ reportContent.encode('utf-8') + '\r\n')
    print('样本分词效果:' + '/'.join(split_words).encode('utf-8')+ '\r\n')
    print('样本的topK(10)词语' + str(get_TF(split_words))+ '\r\n')

if __name__ == '__main__':
    main()

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File  : jieba_gov_report.py
# @Author: evenvi
# @Date  : 19-4-28
# @Desc  : 使用Jieba对2019政府工作报告分词
import codecs
import uniout # 中文显示


# 读取待分词文本数据
def get_content(path, encoding='gbk'):
    with codecs.open(path, 'r', encoding=encoding
            , errors='ignore') as f:
        content = ''
        for l in f:
            l = l.strip()
            content += l
        return content

# 定义高频词函数
def get_TF(words, topK=10):
    tf_dic = {}
    for w in words:
        tf_dic[w] = tf_dic.get(w, 0) + 1
    return sorted(tf_dic.items(), key=lambda x:x[1], reverse=True)[:topK]

def stop_words(path):
    with codecs.open(path, 'r', encoding='utf-8' , errors='ignore') as f:
        return [l.strip() for l in f]

def main():
    import jieba

    reportContent = get_content('./data/reports/2019gov.txt', encoding='utf-8')

    # split_words = list(jieba.cut(reportContent))
    split_words = [x for x in jieba.cut(reportContent) if x not in stop_words('./data/stop_words.utf8')]
    print('样本之一:'+ reportContent.encode('utf-8') + '\r\n')
    print('样本分词效果:' + '/'.join(split_words).encode('utf-8')+ '\r\n')
    print('样本的topK(10)词语' + str(get_TF(split_words))+ '\r\n')

if __name__ == '__main__':
    main()

改造之后的高频词TOP!10结果

样本的topK(10)词语[(u'发展', 134), (u'改革', 92), (u'加强', 62), (u'推进', 59), (u'建设', 56), (u'新', 54), (u'企业', 51), (u'经济', 46), (u'完善', 43), (u'加快', 43)]

对比第一次的分词结果有了很大提升,这里使用的“停用词典”是一个通用版本,也是《python自然语言处理实践 核心技术与算法》作者提供的。一般实践过程中都是根据自己任务定期维护该词典。

总结

通常情况下针对特定情况下定制“领域词典”以提升分词效果,Jieba提供领域词典功能。

具体代码实现在git,包括资源和代码 https://gitee.com/basic_work_of_programming/NLP_CTAP.git

参考: python自然语言处理实践 核心技术与算法

Tags: none

Related Posts:
  • [尚无相关文章]

Leave a Comment