【Python自然语言处理】中文分词技术——统计分词

中文分词方法

本文参考自书籍《Python自然语言处理实战:核心技术与算法》
用做个人的学习笔记和分享

1. 规则分词

规则分词的详细笔记

2. 统计分词

2.1 一般步骤

  1. 建立统计语言模型。
  2. 句子划分为单词,对划分结果进行概率分析,获得概率最大的分词方式。
  3. 常用统计学习算法:隐马尔可夫、条件随机场。

2.2 语言模型

语言模型的形式化描述:
长度为m的字符串的概率分布:
P(w1,w2,...,wm)=P(w1)P(w2∣w1)P(w3∣w1,w2)...P(wm∣w1,w2,...,wm−1)(1)P(w_1,w_2,...,w_m)=P(w_1)P(w_2|w_1)P(w_3|w_1,w_2)...P(w_m|w_1,w_2,...,w_{m-1}) \tag{1}P(w1,w2,...,wm)=P(w1)P(w2w1)P(w3w1,w2)...P(wmw1,w2,...,wm1)(1)
其中w1w_1w1wmw_mwm依次表示文本中的各个词语,采用链式法则计算概率值。

n-gram模型:文本过长,计算难度大,可忽略距离大于等于n的上文词的影响:
P(wi∣w1,w2,...,wi−1)≈P(wi∣wi−(n−1),...,wi−1)(2)P(w_i|w_1,w_2,...,w_{i-1})≈P(w_i|w_{i-(n-1)},...,w_{i-1}) \tag{2}P(wiw1,w2,...,wi1)P(wiwi(n1),...,wi1)(2)
一元模型:n=1,在一元语言模型中,整个句子的概率等于各个词语概率的乘积。言下之意就是各个词之间都是相互独立的,这无疑是完全损失了句中的词序信息。所以一元模型的效果并不理想:
P(w1,w2,...,wm)=P(w1)P(w2)...P(wm)(3)P(w_1,w_2,...,w_m)=P(w_1)P(w_2)...P(w_m) \tag{3}P(w1,w2,...,wm)=P(w1)P(w2)...P(wm)(3)
二元模型:n=2,式(2)变为:
P(wi∣w1,w2,...,wi−1)≈P(wi∣wi−1)(4)P(w_i|w_1,w_2,...,w_{i-1})≈P(w_i|w_{i-1}) \tag{4}P(wiw1,w2,...,wi1)P(wiwi1)(4)
三元模型:n=3,式(2)变为:
P(wi∣w1,w2,...,wi−1)≈P(wi∣wi−2,wi−1)(5)P(w_i|w_1,w_2,...,w_{i-1})≈P(w_i|w_{i-2},w_{i-1}) \tag{5}P(wiw1,w2,...,wi1)P(wiwi2,wi1)(5)
当n≥2 时,该模型是可以保留一定的词序信息的,而且n 越大,保留的词序信息越丰富,但计算成本也呈指数级增长。
一般使用频率计数的比例来计算n 元条件概率,如式(6)所示:
P(wi∣wi−(n−1),...,wi−1)=count(wi−(n−1),...,wi−1,wi)count(wi−(n−1),...,wi−1)(6)P(w_i|w_{i-(n-1)},...,w_{i-1}) = \frac{count(w_{i-(n-1),...,w_{i-1},w_i})}{count(w_{i-(n-1)},...,w_{i-1})} \tag{6}P(wiwi(n1),...,wi1)=count(wi(n1),...,wi1)count(wi(n1),...,wi1,wi)(6)
当n越大时,模型包含的词序信息越丰富,同时计算量随之增大。与此同时,长度越长的文本序列出现的次数也会减少,如按照公式( 3.3 )估计n 元条件概率时,就会出现分子分母为零的情况。因此,一般在n 元模型中需要配合相应的平滑算法解决该问题,如拉普拉斯平滑算法等。

2.3 隐马尔可夫模型(HMM)

基本思路:每个字在构造一个特定的词语时都占据着一个确定的构词位置( 即词位),
现规定每个字最多只有四个构词位置:即B (词首)、M (词中)、E (词尾)和s (单独成词),那么下面句子①的分词结果就可以直接表示成如②所示的逐字标注形式:
①中文/文本处理/需要/进行/中文/分词/。
②中/B文/E文/B本/M处/M理/E需/B要/E/进/B行/E中/B文/E/分/B词/E。/S

形式化描述
句子:λ=λ1λ2...λnλ=λ_1λ_2...λ_nλ=λ1λ2...λn
标签:σ=σ1σ2...σnσ=σ_1σ_2...σ_nσ=σ1σ2...σn
KaTeX parse error: \tag works only in display equations
其中λiλ_iλi是字,n为句长,σ∈{B,M,E,S}
P(σ|λ)是关于2n个变量的条件概率,n不固定,无法对P(σ|λ)进行精确计算,故引入观测独立性假设:每个字的输出仅与当前字有关。
P(σ1σ2...σn∣λ1λ2...λn)=P(σ1∣λ1)P(σ2∣λ2)...P(σn∣λn)(8)P(σ_1σ_2...σ_n|λ_1λ_2...λ_n) = P(σ_1|λ_1)P(σ_2|λ_2)...P(σ_n|λ_n) \tag{8}P(σ1σ2...σnλ1λ2...λn)=P(σ1λ1)P(σ2λ2)...P(σnλn)(8)

观察独立性假设存在的问题:完全没有考虑上下文,且会出现不合理的情况。比如按照之前设定的B 、M 、E 和S 标记,正常来说B后面只能是M或者E ,然而基于观测独立性假设,我们很可能得到诸如BBB 、BEM 等的输出,显然是不合理的。

HMM通过贝叶斯公式求解P(σ|λ)
P(σ∣λ)=P(σ,λ)P(λ)=P(λ∣σ)P(σ)P(λ)(9)P(σ|λ)=\frac{P(σ,λ)}{P(λ)}=\frac{P(λ|σ)P(σ)}{P(λ)} \tag{9}P(σλ)=P(λ)P(σ,λ)=P(λ)P(λσ)P(σ)(9)
λ为给定的输入,因此P(λ)计算为常数,可以忽略,因此最大化P(σ|λ)等价于最大
化P(λ|σ)P(σ)。
对P(λ|σ)P(σ)做马尔可夫假设
P(λ∣σ)=P(λ1∣σ1)P(λ2∣σ2)...P(λn∣σn)(10)P(λ|σ)=P(λ_1|σ_1)P(λ_2|σ_2)...P(λ_n|σ_n) \tag{10}P(λσ)=P(λ1σ1)P(λ2σ2)...P(λnσn)(10)
P(σ)=P(σ1)P(σ2∣σ1)P(σ3∣σ1,σ2)⋅⋅⋅P(σn∣σ1,σ2,…,σn−1(11)P(σ) = P(σ_1)P(σ_2|σ_1)P(σ_3|σ_1,σ_2)···P(σ_n|σ_1,σ_2,…,σ_{n-1}\tag{11}P(σ)=P(σ1)P(σ2σ1)P(σ3σ1,σ2)P(σnσ1,σ2,,σn1(11)
HMM做齐次马尔可夫假设
P(σ)=P(σ1)P(σ2∣σ1)P(σ3∣σ2)...P(σn∣σn−1)(12)P(σ)=P(σ_1)P(σ_2|σ_1)P(σ_3|σ_2)...P(σ_n|σ_{n-1}) \tag{12}P(σ)=P(σ1)P(σ2σ1)P(σ3σ2)...P(σnσn1)(12)

综上所述:
P(λ∣σ)P(σ)~P(λ1∣σ1)P(σ2∣σ1)P(λ2∣σ2)P(σ3∣σ2)...P(σn∣σn−1)P(λn∣σn)P(λ|σ)P(σ)~P(λ_1|σ_1)P(σ_2|σ_1)P(λ_2|σ_2)P(σ_3|σ_2)...P(σ_n|σ_{n-1})P(λ_n|σ_n)P(λσ)P(σ)P(λ1σ1)P(σ2σ1)P(λ2σ2)P(σ3σ2)...P(σnσn1)P(λnσn)
其中P(λk∣σk)P(λ_k|σ_k)P(λkσk)式发射概率,P(σk∣σk−1)P(σ_k|σ_{k-1})P(σkσk1)是转移概率,设置P(σk∣σk−1)=0P(σ_k|σ_{k-1})=0P(σkσk1)=0可以排除BBB、EM等不合理的组合。

求解maxP(λ|σ)P(σ):常用Veterbi算法,算法效率O(n∗l2)O(n*l^2)O(nl2),l为候选数目最多的节点σiσ_iσi的候选数目,与n成正比。
Veterbi算法:是一种动态规划方法,核心思想是:如果最终的最优路径经过某个σiσ_iσi,那么从初始节点到σi−1σ_{i-1}σi1点的路径必然也是一个最优路径一一因为每一个节点σiσ_iσi只会影响前后两个P(σi−1∣σi)P(σ_{i-1}|σ_{i})P(σi1σi)P(σi∣σi+1)P(σ_i|σ_{i+1})P(σiσi+1)

HMM状态转移示意图如下图所示:
HMM状态转移示意图

2.4 HMM的Python实现

  1. 定义HMM类,包含_init_方法、try_load_model方法、train方法
  2. init:初始化一些全局信息,用于初始化一些成员变量。如状态集合(标记
    S 、B 、E 、M ),以及存取概率计算的中间文件。
def __init__(self):import os# 主要是用于存取算法中间结果,不用每次都训练模型self.model_file = './data/hmm_model.pkl'# 状态值集合self.state_list = ['B', 'M', 'E', 'S']# 参数加载,用于判断是否需要重新加载model_fileself.load_para = False
  1. try_load_model:接收一个参数,用于判别是否加载中间文件结果。当直接加载中间结果时,可以不通过语料库训练,直接进行分词调用。否则,该函数用于初始化初始概率、转移概率以及发射概率等。
# 用于加载已计算的中间结果,当需要重新训练时,需初始化清空结果
def try_load_model(self, trained):if trained:import picklewith open(self.model_file, 'rb') as f:self.A_dic = pickle.load(f)self.B_dic = pickle.load(f)self.Pi_dic = pickle.load(f)self.load_para = Trueelse:# 状态转移概率(状态->状态的条件概率)self.A_dic = {}# 发射概率(状态->词语的条件概率)self.B_dic = {}# 状态的初始概率self.Pi_dic = {}self.load_para = False
  1. train:主要用于通过给定的分词语料进行训练。语料的格式为每行一句话(这里以逗号隔开也算一句),每个词以空格分隔,这里采用了人民日报的分词语料。该函数主要通过对语料的统计, 得到HMM 所需的初始概率、转移概率以及发射概率。
# 计算转移概率、发射概率以及初始概率
def train(self, path):# 重置几个概率矩阵self.try_load_model(False)# 统计状态出现次数,求p(o)Count_dic = {}# 初始化参数def init_parameters():for state in self.state_list:self.A_dic[state] = {s: 0.0 for s in self.state_list}self.Pi_dic[state] = 0.0self.B_dic[state] = {}Count_dic[state] = 0def makeLabel(text):out_text = []if len(text) == 1:out_text.append('S')else:out_text += ['B'] + ['M'] * (len(text) - 2) + ['E']return out_textinit_parameters()line_num = -1# 观察者集合,主要是字以及标点等words = set()with open(path, encoding='utf8') as f:for line in f:line_num += 1line = line.strip()if not line:continueword_list = [i for i in line if i != ' ']words |= set(word_list)  # 更新字的集合linelist = line.split()line_state = []for w in linelist:line_state.extend(makeLabel(w))assert len(word_list) == len(line_state)for k, v in enumerate(line_state):Count_dic[v] += 1if k == 0:self.Pi_dic[v] += 1  # 每个句子的第一个字的状态,用于计算初始状态概率else:self.A_dic[line_state[k - 1]][v] += 1  # 计算转移概率self.B_dic[line_state[k]][word_list[k]] =\self.B_dic[line_state[k]].get(word_list[k], 0) + 1.0  # 计算发射概率self.Pi_dic = {k: v * 1.0 / line_num for k, v in self.Pi_dic.items()}self.A_dic = {k: {k1: v1 / Count_dic[k] for k1, v1 in v.items()}for k, v in self.A_dic.items()}# 加1平滑self.B_dic = {k: {k1: (v1 + 1) / Count_dic[k] for k1, v1 in v.items()}for k, v in self.B_dic.items()}# 序列化import picklewith open(self.model_file, 'wb') as f:pickle.dump(self.A_dic, f)pickle.dump(self.B_dic, f)pickle.dump(self.Pi_dic, f)return self
  1. veterbi方法:为Veterbi 算法的实现,是基于动态规划的一种实现,主要是求最大概率的路径。其输入参数为初始概率、转移概率以及发射概率,加上需要切分的句子。
def veterbi(self, text, states, start_p, trans_p, emit_p):V = [{}]path = {}for y in states:V[0][y] = start_p[y] * emit_p[y].get(text[0], 0)path[y] = [y]for t in range(1, len(text)):V.append({})newpath = {}# 检验训练的发射概率矩阵中是否有该字neverSeen = text[t] not in emit_p['S'].keys() and \text[t] not in emit_p['M'].keys() and \text[t] not in emit_p['E'].keys() and \text[t] not in emit_p['B'].keys()for y in states:emitP = emit_p[y].get(text[t], 0) if not neverSeen else 1.0  # 设置未知字单独成词(prob, state) = max([(V[t - 1][y0] * trans_p[y0].get(y, 0) *emitP, y0)for y0 in states if V[t - 1][y0] > 0])V[t][y] = probnewpath[y] = path[state] + [y]path = newpathif emit_p['M'].get(text[-1], 0) > emit_p['S'].get(text[-1], 0):(prob, state) = max([(V[len(text) - 1][y], y) for y in ('E', 'M')])else:(prob, state) = max([(V[len(text) - 1][y], y) for y in states])return (prob, path[state])
  1. cut方法:用于分词,其通过加载中间文件,调用veterbi 函数来完成。
def cut(self, text):import osif not self.load_para:self.try_load_model(os.path.exists(self.model_file))prob, pos_list = self.viterbi(text, self.state_list, self.Pi_dic, self.A_dic, self.B_dic)begin, next = 0, 0for i, char in enumerate(text):pos = pos_list[i]if pos == 'B':begin = ielif pos == 'E':yield text[begin: i + 1]next = i + 1elif pos == 'S':yield charnext = i + 1if next < len(text):yield text[next:]
  1. 主函数
if __name__ == '__main__':hmm = HMM()hmm.train('./data/trainCorpus.txt_utf8')text = '这是一个非常棒的方案!'res = hmm.cut(text)print(text)print(str(list(res)))# 分词结果:[’这是’, ’ 一个’, ’ 非常’, ’ 棒·, ’ 的’ , ’ 方案’ , ' !' l

2.5 其他统计分词算法

条件随机场CRF:基于马尔可夫思想的统计模型。在隐含马尔可夫中,有个很经典的假设,那就是每个状态只与它前面的状态有关。这样的假设显然是有偏差的,于是学者们提出了条件随机场算法,使得每个状态不止与他前面的状态有关,还与他后面的状态有关

神经网络分词算法:深度学习方法在NLP 上的应用。通常采用CNN 、LSTM 等深度学习网络自动发现一些模式和特征,然后结合C RF , softmax 等分类算法进行分词预测。

2.6 总结

对比机械分词法,这些统计分词方法不需耗费人力维护词典,能较好地处理歧义和未登录词,是目前分词中非常主流的方法。但其分同的效果很依赖训练语料的质量,且计算量相较于机械分词要大得多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/481128.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

你的模型真的陷入局部最优点了吗?

小夕曾经收到过一个提问&#xff1a;“小夕&#xff0c;我的模型总是在前几次迭代后很快收敛了&#xff0c;陷入到了一个局部最优点&#xff0c;怎么也跳不出来&#xff0c;怎么办&#xff1f;”本文不是单纯对这个问题的回答&#xff0c;不是罗列工程tricks&#xff0c;而是希…

如何与深度学习服务器优雅的交互?(长期更新)

0. 故事序言 如果有人问小夕&#xff1a;"小夕&#xff0c;要是人工智能的就业岗位一夜之间消失了&#xff0c;你会去转行做什么呢&#xff1f;" 答曰&#xff1a;"当然是去做Linux运维啊23333" 小夕有一台自己负责的GPU服务器&#xff0c;她可让小夕操碎了…

风控模型师面试准备--技术篇(逻辑回归、决策树、集成学习)

原文地址&#xff1a;https://zhuanlan.zhihu.com/p/56175215 编辑于2019-02-12&#xff0c;持续更新中&#xff0c;有风控建模工作经验的&#xff0c;或者想转行风控建模的小伙伴可以互相交流下... 一.算法 逻辑回归决策树集成学习&#xff08;随机森林&#xff0c;Adaboost&…

step-by-step: 夕小瑶版神经网络调参指南(上)

距离上一篇文章已经过去好久好久好久啦。闭关几个月后&#xff0c;其实早有继续码文章的打算&#xff0c;先后写了一下核函数与神经网络的一些思考、文本预处理tricks、不均衡文本分类问题、多标签分类问题、tensorflow常用tricks、噪声对比估算与负采样等文章&#xff0c;结果…

谷歌发布端到端AI平台,还有用于视频和表格的AutoML、文档理解API等多款工具

谷歌又有了大动作。在大洋彼岸的谷歌Cloud Next conference大会上&#xff0c;谷歌一口气发布了多款AI新品和工具&#xff0c;主要包括&#xff1a; 端到端的AI平台 用于处理视频和表格数据的AutoML Tables和AutoML Video 文档理解API 联络中心AI 视觉产品搜索 对于开发者…

跨性别,你所不知道的事

今晚原计划在订阅号里推送南溪妹子前几天录制的跨性别科普视频&#xff0c;没想到今天收到南溪的私信&#xff0c;说不做科普了&#xff0c;还是算了吧。急忙去了解了一下原因 (http://www.zhihu.com/pin/963101597957644288) &#xff0c;才知道南溪因这段视频所遭受的无故攻击…

文本分类问题不需要ResNet?小夕解析DPCNN设计原理(上)

历史回顾回顾一下图像和文本的发展史&#xff0c;似乎这就是一场你追我赶的游戏。在上一阶段的斗争中&#xff0c;朴素贝叶斯、最大熵、条件随机场这些理论完备的统计机器学习模型使得文本分类、中文分词、NER等诸多自然语言处理问题取得了差强人意&#xff08;释义&#xff1a…

【Tensorflow】TensorFlow的嵌入layer和多层layer

计算图中的操作 # python 3.6 import tensorflow as tf import numpy as npsess tf.Session()# 将张量和占位符对象组成一个计算图&#xff0c;创建一个简单的分类器# 一、计算图中的操作 # 1. 声明张量和占位符&#xff0c;创建numpy数组&#xff0c;传入计算图操作 x_vals …

文本分类问题不需要ResNet?小夕解析DPCNN设计原理(下)

哎呀呀&#xff0c;说好的不拖稿的又拖了两天T_T&#xff0c;小夕过一阵子分享给你们这两天的开心事哦。后台催稿调参系列的小伙伴们不要急&#xff0c;下一篇就是第二篇调参文啦。好啦&#xff0c;接着上一篇文章&#xff0c;直接搬来DPCNN、ShallowCNN、ResNet的对比图。从图…

注意力机制-深度学习中的注意力机制+注意力机制在自然语言处理中的应用

1 深度学习中的注意力机制 https://mp.weixin.qq.com/s?__bizMzA4Mzc0NjkwNA&mid2650783542&idx1&sn3846652d54d48e315e31b59507e34e9e&chksm87fad601b08d5f17f41b27bb21829ed2c2e511cf2049ba6f5c7244c6e4e1bd7144715faa8f67&mpshare1&scene1&src…

【TensorFlow】常用的损失函数及其TensorFlow实现

1 损失函数 定义&#xff1a;将随机事件或其有关随机变量的取值映射为非负实数以表示该随机事件的“风险”或“损失”的函数。 应用&#xff1a;作为学习准则与优化问题相联系&#xff0c;即通过最小化损失函数求解和评估模型。 分类&#xff1a;回归问题、分类问题 2 回归问…

从经典文本分类模型TextCNN到深度模型DPCNN

如今深度学习已经成为NLP领域的标配技术&#xff0c;在图像中大为成功的卷积神经网络&#xff08;CNN&#xff09;也开始广泛渗透到文本分类、机器翻译、机器阅读等NLP任务中。但是&#xff0c;在ACL2017以前&#xff0c;word-level的文本分类模型&#xff08;以单词为语义单位…

从特征分解到协方差矩阵:详细剖析和实现PCA算法

从特征分解到协方差矩阵&#xff1a;详细剖析和实现PCA算法本文先简要明了地介绍了特征向量和其与矩阵的关系&#xff0c;然后再以其为基础解释协方差矩阵和主成分分析法的基本概念&#xff0c;最后我们结合协方差矩阵和主成分分析法实现数据降维。本文不仅仅是从理论上阐述各种…

NLP中常用文本分类模型汇总

如今深度学习已经成为NLP领域的标配技术&#xff0c;在图像中大为成功的卷积神经网络&#xff08;CNN&#xff09;也开始广泛渗透到文本分类、机器翻译、机器阅读等NLP任务中。但是&#xff0c;在ACL2017以前&#xff0c;word-level的文本分类模型&#xff08;以单词为语义单位…

【TensorFlow】随机训练和批训练的比较与实现

一、随机训练和批训练 随机训练&#xff1a;一次随机抽样训练数据和目标数据对完成训练。批训练&#xff1a;一次大批量训练取平均损失来进行梯度计算&#xff0c;批量训练大小可以一次上扩到整个数据集。批训练和随机训练的差异&#xff1a;优化器方法和收敛的不同批训练的难…

「小公式」平均数与级数

喵喵喵&#xff0c;小夕最近准备复习一下数学和基础算法&#xff0c;所以可能会推送或者附带推送点数学和基础算法的小文章。说不定哪天就用&#xff08;考&#xff09;到了呢(&#xffe3;∇&#xffe3;)注意哦&#xff0c;与头条位的文章推送不同&#xff0c;「小公式」和「…

最新出炉-阿里 2020届算法工程师-自然语言处理(实习生)以及补充:快递最短路径

问题2感觉跟下面的分苹果类似&#xff1b; 问题 G: 分梨 题目描述 zzq非常喜欢吃梨&#xff0c;有一天他得到了ACMCLUB送给他的一筐梨子。由于他比较仗义&#xff0c;就打算把梨子分给好朋友们吃。现在他要把M个梨子放到N个盘子里面&#xff08;我们允许有的盘子为空&#xff0…

如何匹配两段文本的语义?

喵喵喵&#xff0c;好久不见啦。首先很抱歉大家期待的调参手册&#xff08;下&#xff09;迟迟没有出稿&#xff0c;最近两个月连着赶了4个DDL&#xff0c;整个人都不好了。最近几天终于有时间赶一下未完成的稿子了。在赶DDL的时候夹着写了这篇文章&#xff0c;就先发布这一篇吧…

【TensorFlow】实现简单的鸢尾花分类器

代码实现及说明 # python 3.6 # TensorFlow实现简单的鸢尾花分类器 import matplotlib.pyplot as plt import tensorflow as tf import numpy as np from sklearn import datasetssess tf.Session()#导入数据 iris datasets.load_iris() # 是否是山鸢尾 0/1 binary_target …