赵走x博客
网站访问量:151843
首页
书籍
软件
工具
古诗词
搜索
登录
16、算法部分源码解析
15、系统总体流程与词典结构
14、中文分词
13、词汇与分词技术
12、三个平面中的语义研究
11、汉语的发展
10、字形的流变
9、六书及其他
8、文字符号的起源
7、整合语义角色标注模块
6、整合句法解析模块
5、整合命名实体识别模块
4、整合词性标注模块
3、整合中文分词模块
2、现代自然语言系统简介
1、中文语言的机器处理:历史回顾
3、整合中文分词模块
资源编号:75994
NLP汉语自然语言处理原理与实践
自然语言处理
热度:89
为使读者深入了解NLP的各个功能模块,从本节开始,举例介绍如何将几个开源的NLP系统整合到NLTK中。
为使读者深入了解NLP的各个功能模块,从本节开始,举例介绍如何将几个开源的NLP系统整合到NLTK中。 本节主要介绍中文分词部分。汉语自然语言处理的第一部分是中文分词。因为中文不像英文那样,实行分词连写,即词与词之间用空格分隔。在分析中文文本之前必须将一个汉字序列切分成一个一个单独的词。这个过程称为中文分词(Chinese Word Segmentation)。它是汉语自然语言处理的第一步。不执行或不能正确地进行中文分词,根本谈不上汉语自然语言处理后续过程。因此,长久以来这一步都是汉语NLP最关键的环节。该系统对分词的规模性和精确性都要求非常高。 按照使用的算法不同,下面介绍两大类中文分词模块。 ❑ 基于条件随机场(CRF)的中文分词算法的开源系统。 ❑ 基于张华平NShort的中文分词算法的开源系统。 # 1、安装Ltp Python组件 国内使用CRF做中文分词的开源系统主要为哈工大的HIT LTP语言技术平台。该项目的源代码可从https://github.com/HIT-SCIR/ltp 获取,源代码用C++编写,对源代码感兴趣的读者可下载用于学习。本书的后面章节会对LTP的源代码做进一步解析,读者可以先下载源码备用。 对应于该源代码的语言模型库可从http://pan.baidu.com/share/link?shareid=1988562907&uk=2738088569#dir/path=%252Fltp-models 下载。目前最高版本为3.4版。 源代码和语言模型包括:中文分词、词性标注、未登录词识别、依存句法、语义角色标注几个模块。 这里要将项目与Python整合,HIT LTP也提供了该项目与Python扩展包。扩展包的源码和案例可从https://github.com/HIT-SCIR/pyltp 下载。一般我们都直接使用已经预编译的pyltp安装包,可参考:https://pypi.python.org/pypi/pyltp 网页。 ###(1)pyltp安装。 ``` pip install pyltp ``` ###(2)部署语言模型库。 读者首先从http://pan.baidu.com/share/link?shareid=1988562907&uk=2738088569#dir/path=%252Fltp-models%252F3.3.0 下载Ltp 3.3版的模型文件。在自己的X盘下新建立一个目录X:\ltp3.3,将模型文件解压到此目录下。解压后的文件结构如图1.7所示。  图1.7 解压后的文件结构 如图1.7所示,cws.model为中文分词模块所需的语言模型,fulluserdict.txt为用户可添加的外部词典文件。cws.model是一个二进制文件,有关文件的内容,将在后面章节详细讲解。 fulluserdict.txt是用户可添加的外部词典文件,图1.8给出该文件的词汇结构。  图1.8 Ltp用户词典样例 第一列是词,第二列到第n列是该词的候选词性,如果仅用于分词,该词的词性可以忽略。由于Ltp 3.3能够支持大约50万个常用词的中文分词,并提供高于95%以上的准确结果,因此,如果仅用于实验和中小规模的文本语料,该分词器足以满足需求。 Ltp的用户词典可放置一些不能正确切分的专用词汇,但该用户词典不属于外部词典,有专门的算法给予支持,并与CRF算法相融合。有关更多的细节使用,可参照:http://ltp.readthedocs.org/zh_CN/latest/ltptest.html 。 # 2、使用Ltp 3.3进行中文分词 ### (1)Ltp 3.3安装成功之后,新建一个Python文件如下。 ``` # -*- coding: utf-8 -*- import sys import os from pyltp import Segmentor # 导入ltp库 model_path = "/Volumes/UP/data/ltp_data_v3.4.0/cws.model" # Ltp3.3 分词模型库 segmentor = Segmentor() # 实例化分词模块 segmentor.load(model_path) # 加载分词库 words = segmentor.segment("在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根节 点出发深度探索解空间树。") # 分割后的分词结果 print(" | ".join(words)) ``` 这里不使用外部词典,仅用Ltp 3.3进行中文分词。 分词结果如下。 ``` 在 | 包含 | 问题 | 的 | 所有 | 解 | 的 | 解 | 空间 | 树 | 中 | , | 按照 | 深度 | 优先 | 搜 索 | 的 | 策略 | , | 从 | 根节点 | 出发 | 深度 | 探索 | 解 | 空间 | 树 | 。 ``` ### (2)分词结果的后处理。 观察上述分词结果,“解 | 空间”、“解 | 空间 | 树”、“深度 | 优先”都可以看作一个完整的专有名词:解空间、解空间树、深度优先,而分词器划分的粒度过细。为了获得更精确的结果可以将错分的结果合并为专有名词。这就是分词结果的后处理过程,即一般外部用户词典的构成原理。 ``` # -*- coding: utf-8 -*- import sys import os from pyltp import Segmentor # 导入ltp库 model_path = "/Volumes/UP/data/ltp_data_v3.4.0/cws.model" # Ltp3.3 分词模型库 segmentor = Segmentor() # 实例化分词模块 segmentor.load(model_path) # 加载分词库 words = segmentor.segment("在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根节 点出发深度探索解空间树。") seg_sent = '|'.join(words) postdict = {"解 | 空间": "解空间", "深度 | 优先": "深度优先"} for key in postdict: seg_sent = seg_sent.replace(key, postdict[key]) print(seg_sent) ``` 分词结果如下。 ``` 在 | 包含 | 问题 | 的 | 所有 | 解 | 的 | 解空间 | 树 | 中 | , | 按照 | 深度优先 | 搜索 | 的 | 策略 | , | 从 | 根节点 | 出发 | 深度 | 探索 | 解空间 | 树 | 。 ``` ###(3)现在加入用户词典,词典中登录一些新词,如解空间。 ``` # -*- coding: utf-8 -*- import sys import os from pyltp import Segmentor # 导入ltp库 model_path = "/Volumes/UP/data/ltp_data_v3.4.0/cws.model" #外部专有名词词典路径 user_dict='fulluserdict.txt' # Ltp3.3 分词模型库 segmentor = Segmentor() # 实例化分词模块 segmentor.load_with_lexicon(model_path,user_dict) # 加载分词库 words = segmentor.segment("在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根节 点出发深度探索解空间树。") print(" | ".join(words)) ``` 其分词结果如下。 ``` 在 | 包含 | 问题 | 的 | 所有解 | 的 | 解空间 | 树 | 中 | , | 按照 | 深度优先 | 搜索 | 的 | 策略 | , | 从 | 根节点 | 出发 | 深度 | 探索 | 解空间 | 树 | 。 ``` 这里使用的用户词典不是基于词匹配的外部词典,而是内置的专有名词词典。有关专有名词词典的编写,需要根据应用场景的不同来制作。CRF类分词器的专有名词识别被称为领域自适应问题,这部分的算法将在后面章节给出详细讲解。 # 3、使用结巴分词模块 张华平NShort的中文分词算法是目前大规模中文分词的主流算法。在商用领域,大多数搜索引擎公司都使用该算法作为主要的分词算法。具有算法原理简单、容易理解、便于训练、大规模分词的效率高、模型支持增量扩展、模型占用资源低等优势。 这里使用的结巴分词器是该算法的Python实现,结巴分词的算法核心就是Nshort中文分词算法。 结巴分词可从https://github.com/fxsjy/jieba 目录下载。结巴分词模块可支持如下三种分词方式。 ❑ 精确模式,试图将句子最精确地切开,适合文本分析(类似Ltp的分词方式)。 ❑ 全模式,把句子中所有可以成词的词语都扫描出来,速度非常快,但是不能解决歧义。 ❑ 搜索引擎模式,在精确模式的基础上对长词再次切分,提高召回率,适合用于搜索引擎分词。 ❑ 支持繁体分词。 ❑ 支持基于概率的用户词典。 ### (1)结巴分词库的安装。 ``` pip install jieba ``` ###(2)使用结巴分词。 ``` # -*- coding: utf-8 -*- import jieba # 导入结巴分词库 # 结巴分词--全模式 sent = '在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根节点出发深度探索解空间树。' wordlist = jieba.cut(sent, cut_all=True) print(" | ".join(wordlist)) # 结巴分词--精确切分 wordlist = jieba.cut(sent) # cut_all=False print(" | ".join(wordlist)) # 结巴分词--搜索引擎模式 wordlist = jieba.cut_for_search(sent) print(" | ".join(wordlist)) ``` 分词结果如下。 ``` Building prefix dict from the default dictionary ... Dumping model to file cache /var/folders/0n/5_hyy_657xl50dvv9rb02f_c0000gn/T/jieba.cache Loading model cost 0.875 seconds. 在 | 包含 | 问题 | 的 | 所有 | 解 | 的 | 解空 | 空间 | 树 | 中 | | | 按照 | 深度 | 优先 | 搜索 | 的 | 策略 | | | 从 | 根 | 节点 | 点出 | 出发 | 深度 | 探索 | 索解 | 解空 | 空间 | 树 | | Prefix dict has been built succesfully. 在 | 包含 | 问题 | 的 | 所有 | 解 | 的 | 解 | 空间 | 树中 | , | 按照 | 深度 | 优先 | 搜索 | 的 | 策略 | , | 从根 | 节点 | 出发 | 深度 | 探索 | 解 | 空间 | 树 | 。 在 | 包含 | 问题 | 的 | 所有 | 解 | 的 | 解 | 空间 | 树中 | , | 按照 | 深度 | 优先 | 搜索 | 的 | 策略 | , | 从根 | 节点 | 出发 | 深度 | 探索 | 解 | 空间 | 树 | 。 ``` 结巴分词的基础词库较之Ltp分词要少一些,标准词典的词汇量约有35万个。上例的分词结果显示,一些专有名词的切分缺乏足够的精度,不仅出现粒度问题,还出现错分问题(如上例中的“树中”、“从根”)。由此可见,分词器的精度不仅受到算法的影响,更受到语言模型库的规模影响。这一点对于NShort最短路径算法尤其明显。 ###(3)定义用户词典。 如图1.9所示,词典格式为一个词占一行;每一行分为三部分:词语、词频和词性,用空格隔开,顺序不可颠倒。Userdict.txt文件必须为UTF-8编码。 ``` 深度优先 5 n ``` 结巴分词中的词典词频设置,默认为5。这个数越大,说明该字符串成词的概率越高,受到内置词典的干扰就越小;这个数越小,用户词典内的词受到内置词典的干扰越强,不能正确切分的概率就越大。用户需要根据实际情况来设置这个值。 ###(4)使用用户词典。 ``` # -*- coding: utf-8 -*- import jieba # 导入结巴分词库 sent = '在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根节点出发深度探索解空间树。' jieba.load_userdict("userdict.txt") # 加载外部 # 结巴分词--精确切分 wordlist = jieba.cut(sent) # cut_all=False print(" | ".join(wordlist)) ``` 分词结果如下。 ``` Building prefix dict from the default dictionary ... Loading model from cache /var/folders/0n/5_hyy_657xl50dvv9rb02f_c0000gn/T/jieba.cache Loading model cost 0.652 seconds. 在 | 包含 | 问题 | 的 | 所有 | 解 | 的 | 解 | 空间 | 树中 | , | 按照 | 深度优先 | 搜索 | 的 | 策略 | , | 从根 | 节点 | 出发 | 深度 | 探索 | 解 | 空间 | 树 | 。 Prefix dict has been built succesfully. ```