自然语言处理(3):词性标注

您所在的位置:网站首页 secret的词性和词义 自然语言处理(3):词性标注

自然语言处理(3):词性标注

2023-11-24 02:20| 来源: 网络整理| 查看: 265

文章目录 1 概述2 词性标注难点3 词性标注算法3.1 基于字符串匹配的字典查找算法3.2 基于统计的词性标注算法 4 jieba词性标注原理4.1 准备工作4.2 遍历语句,进行分词和词性标注4.3 未登录词,HMM隐马尔科夫模型处理 5 总结 转载来源:https://blog.csdn.net/u013510838/article/details/81907121

1 概述

词性标注在自然语言处理中也属于基础性的模块,为句法分析、信息抽取等工作打下基础。和分词一样,中文词性标注也存在着很多难点,比如一词多词性,未登录词处理等诸多问题。通过基于字符串匹配的字典查询算法和基于统计的词性标注算法,可以很好的解决这些问题。一般需要先将语句进行分词,然后再进行词性标注。

2 词性标注难点

词性作为词语基本的语法属性,是词语和语句的关键性特征。词性种类也很多,ICTCLAS 汉语词性标注集归纳的词性种类及其表示见 https://www.cnblogs.com/chenbjin/p/4341930.html 词性标注中的难点主要有

相对于英文,中文缺少词形态变化,不能从词的形态来识别词性一词多词性很常见。统计发现,一词多词性的概率高达22.5%。而且越常用的词,多词性现象越严重。比如“研究”既可以是名词(“基础性研究”),也可以是动词(“研究计算机科学”)。词性划分标准不统一。词类划分粒度和标记符号等,目前还没有一个广泛认可的统一的标准。比如LDC标注语料中,将汉语一级词性划分为33类,而北京大学语料库则将其划分为26类。词类划分标准和标记符号的不统一,以及分词规范的含糊,都给词性标注带来了很大的困难。jieba分词采用了使用较为广泛的ICTCLAS 汉语词性标注集规范。未登录词问题。和分词一样,未登录词的词性也是一个比较大的课题。未登录词不能通过查找字典的方式获取词性,可以采用HMM隐马尔科夫模型等基于统计的算法。 3 词性标注算法

和分词一样,词性标注算法也分为两大类,基于字符串匹配的字典查找算法和基于统计的算法。jieba分词就综合了两种算法,对于分词后识别出来的词语,直接从字典中查找其词性。而对于未登录词,则采用HMM隐马尔科夫模型和viterbi算法来识别。

3.1 基于字符串匹配的字典查找算法

先对语句进行分词,然后从字典中查找每个词语的词性,对其进行标注即可。jieba词性标注中,对于识别出来的词语,就是采用了这种方法。这种方法比较简单,通俗易懂,但是不能解决一词多词性的问题,因此存在一定的误差。

下图即为jieba分词中的词典的一部分词语。每一行对应一个词语,分为三部分,分别为词语名 词数 词性。因此分词完成后只需要在字典中查找该词语的词性即可对其完成标注。 Alt

3.2 基于统计的词性标注算法

和分词一样,我们也可以通过HMM隐马尔科夫模型来进行词性标注。观测序列即为分词后的语句,隐藏序列即为经过标注后的词性标注序列。起始概率 发射概率和转移概率和分词中的含义大同小异,可以通过大规模语料统计得到。观测序列到隐藏序列的计算可以通过viterbi算法,利用统计得到的起始概率 发射概率和转移概率来得到。得到隐藏序列后,就完成了词性标注过程。

4 jieba词性标注原理

jieba在分词的同时,可以进行词性标注。利用jieba.posseg模块来进行词性标注,会给出分词后每个词的词性。词性标示兼容ICTCLAS 汉语词性标注集,可查阅网站https://www.cnblogs.com/chenbjin/p/4341930.html

import jieba.posseg as pseg words = pseg.cut("我爱北京天安门") for word, flag in words: ... print('%s %s' % (word, flag)) ... 我 r # 代词 爱 v # 动词 北京 ns # 名词 天安门 ns # 名词

下面来对pseg.cut()进行详细的分析,其主要流程为

准备工作:check字典是否初始化好,如果没有则先初始化字典。将语句转为UTF-8或者GBK。根据正则匹配,将输入文本分隔成一个个语句。遍历语句list,对每个语句进行单独分词和词性标注。对于未登录词,使用HMM隐马尔科夫模型处理。 4.1 准备工作

准备工作中做的事情和jieba分词基本一致,check字典是否初始化好,如果没有则先初始化字典。将语句转为UTF-8或者GBK。根据正则匹配,将输入文本分隔成一个个语句。代码如下。

def __cut_internal(self, sentence, HMM=True): # 如果没有字典没有初始化,则先加载字典。否则直接使用字典缓存即可。 self.makesure_userdict_loaded() # 将语句转为UTF-8或者GBK sentence = strdecode(sentence) # 根据正则匹配,将输入文本分隔成一个个语句。分隔符包括空格 逗号 句号等。 blocks = re_han_internal.split(sentence) # 根据是否采用了HMM模型来进行不同方法的选择 if HMM: cut_blk = self.__cut_DAG else: cut_blk = self.__cut_DAG_NO_HMM # 遍历正则匹配分隔好的语句,对每个语句进行单独的分词和词性标注 for blk in blocks: if re_han_internal.match(blk): # 分词和词性标注 for word in cut_blk(blk): yield word else: tmp = re_skip_internal.split(blk) for x in tmp: if re_skip_internal.match(x): yield pair(x, 'x') else: for xx in x: if re_num.match(xx): yield pair(xx, 'm') elif re_eng.match(x): yield pair(xx, 'eng') else: yield pair(xx, 'x') 4.2 遍历语句,进行分词和词性标注

步骤和jieba分词基本一致,主体步骤如下,详细的每个步骤见 自然语言处理2jieba分词用法及原理

得到语句的有向无环图DAG动态规划构建Route,计算从语句末尾到语句起始,DAG中每个节点到语句结束位置的最大路径概率,以及概率最大时节点对应词语的结束位置遍历每个节点的Route,组装词语组合。如果词语不在字典中,也就是新词,使用HMM隐马尔科夫模型进行分割通过yield将词语逐个返回。 def __cut_DAG(self, sentence): # 构建DAG有向无环图,得到语句分词所有可能的路径 DAG = self.tokenizer.get_DAG(sentence) route = {} # 动态规划,计算从语句末尾到语句起始,DAG中每个节点到语句结束位置的最大路径概率,以及概率最大时节点对应词语的结束位置 self.tokenizer.calc(sentence, DAG, route) # 遍历每个节点的Route,组装词语组合。 x = 0 buf = '' N = len(sentence) while x }] # 每个汉字的每个BEMS状态的最大概率。 mem_path = [{}] # 分词路径 # 初始化每个state,states为"BEMS" all_states = trans_p.keys() for y in states.get(obs[0], all_states): # init V[0][y] = start_p[y] + emit_p[y].get(obs[0], MIN_FLOAT) mem_path[0][y] = '' # 逐字进行处理 for t in xrange(1, len(obs)): V.append({}) mem_path.append({}) #prev_states = get_top_states(V[t-1]) prev_states = [ x for x in mem_path[t - 1].keys() if len(trans_p[x]) > 0] prev_states_expect_next = set( (y for x in prev_states for y in trans_p[x].keys())) obs_states = set( states.get(obs[t], all_states)) & prev_states_expect_next if not obs_states: obs_states = prev_states_expect_next if prev_states_expect_next else all_states # 遍历每个状态 for y in obs_states: # 计算前一个状态到本状态的最大概率和它的前一个状态 prob, state = max((V[t - 1][y0] + trans_p[y0].get(y, MIN_INF) + emit_p[y].get(obs[t], MIN_FLOAT), y0) for y0 in prev_states) # 将该汉字下的某状态(BEMS)的最大概率记下来 V[t][y] = prob # 记录状态转换路径 mem_path[t][y] = state last = [(V[-1][y], y) for y in mem_path[-1].keys()] # if len(last)==0: # print obs prob, state = max(last) route = [None] * len(obs) i = len(obs) - 1 while i >= 0: route[i] = state state = mem_path[i][state] i -= 1 return (prob, route) 5 总结

jieba可以在分词的同时,完成词性标注,因此标注速度可以得到保证。通过查询字典的方式获取识别词的词性,通过HMM隐马尔科夫模型来获取未登录词的词性,从而完成整个语句的词性标注。但可以看到查询字典的方式不能解决一词多词性的问题,也就是词性歧义问题。故精度上还是有所欠缺的。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3