版权声明:转载请注明出处 https://blog.csdn.net/zhouchen1998/article/details/88871149
中文分词技术
- 简介
- 自然语言处理的一项核心技术。在语言理解中,词是最小的能够独立活动的有意义的语言成分。将词确定下来是理解自然语言的第一步,只有跨越这一步,中文才能像英文那样过渡到短语划分、概念抽取以及主题分析,已至自然语言理解,最终达到智能计算的最高境界。因此,每个NLP研究者应该掌握最基本的分词技术。
- “词”这个概念一直是汉语语言学界纠缠不清而又绕不开的问题。“词是什么”(词的抽象定义)和“什么是词”(词的具体界定),这两个问题迄今为止也没有权威、明确的表述,更不可能拿出令人认可的词表来。主要的难点在于汉语结构与英语等语种差异很大,对词的构成边界方面很难界定。
- 在英语中,单词本身就是“词”的表达,一篇英文文章就是“单词”加分隔符(空格或者逗号和句号)来表示的,而在汉语中,词以字为基本单位的,但是一篇文章的语义表达确实 以词来划分的。因此,在处理中文文本时,需要进行分词处理,将句子转化为词的表示。这个切词处理过程就是中文分词,它通过计算机自动识别出句子的词,在词间加入边界标记符,分隔出各个词汇。整个过程看似简单,然而实践起来确实无比复杂的,主要就是因为中文歧义。
- 很多句子人来判定都有问题,更不用说机器了。此外,像未登录词、分词粒度粗细等都是影响分词效果的重要因素。
- 从中文分词提出以来,历经30多年的探索,提出来很多方法,归纳为**规则分词、统计分词和混合分词(规则+统计)**这三个主要流派。
- 规则分词是最早兴起的办法,主要是通过人工设立词库,按照一定的方式进行匹配切分,其实现简单高效,但对新词很难进行处理。
- 统计分词是随着机器学习的技术兴起,应用到了分词任务上而产生的,它能够较好应对新词发现等特殊场景。然而,实践中统计分词太过依赖语料的质量。
- 混合分词是基于前两者的结合,如今大多采用这种方式。
- 规则分词
- 基于规则的分词是一种机械分词方法,主要是通过维护词典,在切分语句时将语句的每个字符串与词表中的词逐一匹配,找到则切分,否则不予切分。
- 按照匹配切分的方式,主要有正向最大匹配法、逆向最大匹配法以及双向匹配法三种。这三种方法每一个都是对前者的优化。
- 基于规则的分词,一般简单高效,但是词典的维护是一个庞大的工程。在网络发达的今天,新词层出不穷,很难通过词典覆盖所有词。
- 统计分词
- 随着大规模语料的建立,统计机器学习方法的研究和发展,基于统计的中文分词算法渐渐成为主流。
- 其主要思想是把每个词看做是由词的最小单位的各个字组成的,如果相连的字在不同的文本中出现的次数越多,就证明这相连的字很可能就是一个词。因此我们就可以利用字与字相邻出现的频率来反映成词的可靠度,统计语料中相邻出现的各个字的组合的频度,当组合频度高于某一个临界值时,我们便认为此字组可能会构成一个词语。
- 基于统计的分词一般做如下两个步骤。
- 建立统计语言模型。
- 对句子进行单词划分,然后对划分结果进行概率计算,获得概率最大的分词方式。这里就用到了统计学习算法,如隐含马尔可夫(HMM)、条件随机场(CRF)等。
- 主要的有HMM模型、CRF模型、神经网络分词算法(常采用CNN、LSTM等深度学习网络自动发现一些模式和特征,然后结合CRF、softmax等分类算法进行分词预测。)
- 对比机械分词法,统计分词方法不需要耗费人力维护词典,能较好地处理歧义和未登录词,是目前分词的主流方法。但是,其分词的效果很依赖训练语料的质量,且计算量很大。
- 混合分词
- 事实上,目前不管是基于规则的算法、还是基于HMM、CRF或者深度学习的方法,其分词效果在具体任务中,其实差距并没有多明显。在实际工程应用中,多是基于一种分词方法,然后用其他分词算法加以辅助。如此,能在保证词典分词准确率的基础上,对未登录词和歧义词有较好的识别,jieba就是如此实现的。
- 中文分词工具Jieba
- 简介
- 北大之前开源的pkuseg在我之前的博客有过介绍。
- 近年来,NLP技术的日益成熟,开源实现的分词工具越来越多,如Ansj、盘古分词等。
- 相对而言,jieba有着如下优势。
- 社区活跃。
- GitHub近10000的star,社区反馈快。
- 功能丰富
- 并不只是分词,其实是一个开源框架,提供了很多分词之上的算法,如关键词提取、词性标注等。
- 多语言实现
- 官方提供Python、Java、C++、Go、R、iOS等多平台多语言支持,不仅如此,还提供了很多热门社区项目的扩展插件,如ElasticSearch、solr、lucene等。
- 使用简单
- API不多,配置不复杂,方便上手。
- 社区活跃。
- jieba结合了基于规则和统计两种方法。首先,基于前缀字典的词图扫描;然后,对于未登录词,使用基于汉字成词的HMM模型,采用了Viterbi算法进行推导。
- 安装
- Python下使用pip安装
pip install jieba
- Python下使用pip安装
- 三种分词模式(见JiebaDemo)
- 精确模式(默认)
- 试图将句子最精确切开,适合文本分析。
- 全模式
- 把句子中可以成词的词语都扫描出来,速度很快,但是不能解决歧义。
- 搜索引擎模式
- 在精确模式的基础上,对长词再次划分,提高召回率,适合用于搜索引擎分词。
- 代码
-
# -*-coding:utf-8-*- import jieba sentence = "中文分词是文本处理不可或缺的一步!" seg_list = jieba.cut(sentence, cut_all=True) print('全模式', '/'.join(seg_list)) seg_list = jieba.cut(sentence, cut_all=False) print('精确模式', '/'.join(seg_list)) seg_list = jieba.cut(sentence) print('默认精确模式', '/'.join(seg_list)) seg_list = jieba.cut_for_search(sentence) print('搜索引擎模式', '/'.join(sentence))
-
- 运行结果
- 精确模式(默认)
- 自定义字典
- jieba有默认的一套字典,然而很多情况下,不同的应用场合需要不同的字典,jieba支持用户自定义字典,只要分词之前加载即可。
jieba.load_userdict('./data/user_dict.utf8')
- 用户字典格式
- 每行
- 词语 词频(可以省略) 词性(可以省略)
- 需为utf8编码
- 每行
- jieba有默认的一套字典,然而很多情况下,不同的应用场合需要不同的字典,jieba支持用户自定义字典,只要分词之前加载即可。
- 简介
- 实战
- 高频词提取
- 数据集为搜狗实验室新闻数据
- 高频词一般指文档中出现频率较高且非无用的词语,其一定程度上代表了文档的焦点所在。针对单篇文档,可以作为关键词看待。对于新闻这样的多篇文档,可以作为热词,发现舆论焦点。
- 高频词提取其实就是NLP中的TF策略。(后面具体介绍)主要有标点符号和停用词(“的”“了”等无意义词)两个干扰项。
- 这个项目是使用jieba,针对搜狗实验室新闻数据,进行高频词提取。
- 代码
-
# -*-coding:utf-8-*- def get_content(path): """ 获取文件内容 :param path: :return: """ with open(path, 'r', encoding='gbk', errors='ignore') as f: content = '' for l in f: l = l.strip() content += l return content def get_TF(words, topK=10): """ 计算TF值 :param words: :param topK: :return: """ 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): """ 获取停用词 :param path: :return: """ with open(path, encoding='utf-8') as f: return [l.strip() for l in f] stop_words('./data/stop_words.utf8') def main(): """ 主模块 :return: """ # 文件操作模块,允许通配符等 import glob import jieba import random files = glob.glob('./data/news/C000013/*.txt') corpus = [get_content(x) for x in files] # 随机文字进行高频词提取 sample_inx = random.randint(0, len(files)) split_words = [x for x in jieba.cut(corpus[sample_inx]) if x not in stop_words('./data/stop_words.utf8')] print('样本之一:' + corpus[sample_inx]) print('样本分词效果:' + '/ '.join(split_words)) print('样本的topK(10)词:' + str(get_TF(split_words))) if __name__ == '__main__': main()
-
- 结果
- 补充说明
- 参考书为《Python自然语言处理实战》
- 具体数据集代码可以查看我的GitHub,欢迎star或者fork