赞
踩
笔记来源:《python自然语言处理核心算法与技术》 涂铭 等
nlp 即自然语言处理。
英文分词自然的以空格作为分隔符。
中文分词比较困难,典型的思路是基于字典的最长字符匹配,可以解决部分问题,但是对于歧义性很难解决。
词性指的是:动词、名词、形容词等。标注的目的是表征词的一种隐藏状态。
指的是从文本中识别具体特定类别的实体(通常是名词),例如人名、地名、机构名、专有名词等。
句法分析的目的是解析句子中哥哥成分之间的依赖关系。
代词出现的频率很高,但是真正具有实际意义的只有第一次出现的具体名词。消解这些代词也是研究方向。
正负面词汇。有时也有中性词汇
自动纠错词汇,输入法中常用。
这种就很厉害了,人工智能小爱等
import re
text_string = "我是一个爬虫。我是一个正常程序"
regex = "爬虫"
p_string = text_string.split("。")
for line in p_string:
if re.search(regex,line) is not None:
print(line)
以上代码就是一个最常用的匹配字符串的代码。
这个部分可以展开将很多,有机会专门出一个博客用于记录。
前面提到过,中文没有像英语一样的天然分词,所以我们需要专门针对中文得到一些中文分词的关键技术。
经过多年的探索,当前的中文分词技术大致有:
囧顶分词词典中的最长词有i个汉字字符,则用被处理文档的当前字符串中的前i个子作为匹配字段,查找字典,若字典中存在这样的一个i字词,则匹配成功,匹配字段被作为在一个词切分出来。如果词典中找不到这样的一个i自此,则匹配失败,将匹配字段中的最后一个字去掉,对剩下的字串进行匹配处理。如此迭代,知道匹配成功,或者剩余的字串长度为0为止。
class MM(object): def __init__(self): self.window_size = 3 def cut(self, text: str): result = [] index = 0 text_length = len(text) dic = ['研究', '研究生', '生命', '命', '的', '起源'] while text_length > index: for size in range(self.window_size+index, index, -1): piece = text[index:size] if piece in dic: index = size - 1 break index = index + 1 result.append(piece + '----') print(result) if __name__ == '__main__': text = '研究生命的意义' tokenizer = MM() print(tokenizer.cut(text))
大同小异,不再介绍。直接看示例
class RMM(object): def __init__(self): self.window_size = 3 def cut(self, text: str): result = [] index = len(text) text_length = len(text) dic = ['研究', '研究生', '生命', '命', '的', '起源'] while index > 0: for size in range(index-self.window_size, index): piece = text[size:index] if piece in dic: index = size + 1 break index = index - 1 result.append(piece + '----') result.reverse() print(result) if __name__ == '__main__': text = '研究生命的意义' # tokenizer = MM() tokenizer = RMM() print(tokenizer.cut(text))
是将正向最大匹配法得到的分词结果和逆向最大匹配法得到的结果进行比较,然后按照最大匹配原则,选取次数切分最少的作为结果。
大规模语料库的建立使得统计学习方法成为中文分词算法的主流。
主要思想是:
一般来说,基于统计的分词需要做下面两个操作:
下面针对一些关键技术作介绍:
长度为 m m m的字符串确定其概率分布 P ( ω 1 , ω 2 , ω 3 , . . . , ω m ) P(\omega_1,\omega_2,\omega_3,...,\omega_m) P(ω1,ω2,ω3,...,ωm),其中 ω 1 \omega1 ω1到 ω m \omega_m ωm的依次表示文本中的各个词语。一般采用链式法则计算其概率值,如下面式子所示:
P ( ω 1 , ω 2 , . . . , ω m ) = P ( ω 1 ) P ( ω 1 ∣ ω 2 ) . . . P ( ω m ∣ ω 1 , ω 2 , . . . , ω m − 1 ) P(\omega_1,\omega_2,...,\omega_m) = P(\omega_1)P(\omega_1|\omega_2)...P(\omega_m|\omega_1,\omega_2,...,\omega_{m-1}) P(ω1,ω2,...,ωm)=P(ω1)P(ω1∣ω2)...P(ωm∣ω1,ω2,...,ωm−1)
可以发现,当文本过长的时候,公式计算难度加大。为解决这个问题,有人提出了n元模型,以降低计算难度。
所谓n元模型就是在估算条件概率是,忽略距离大于等于n的上文词的影响,因此 P ( ω i ∣ ω 1 , ω 2 , . . . , ω i − 1 ) P(\omega_i|\omega_1,\omega_2,...,\omega_{i-1}) P(ωi∣ω1,ω2,...,ωi−1)的计算可以简化为:
P ( ω i ∣ ω 1 , ω 2 , . . . , ω i − 1 ) ≈ P ( ω i ∣ ω i − ( n − 1 ) , . . . , ω i − 1 ) P(\omega_i|\omega_1,\omega_2,...,\omega_{i-1}) \approx P(\omega_i|\omega_{i-(n-1)},...,\omega_{i-1}) P(ωi∣ω1,ω2,...,ωi−1)≈P(ωi∣ωi−(n−1),...,ωi−1)
当n=1时成为医院模型,此时整个句子的概率可以表示为: P ( ω 1 , ω 2 , . . . , ω m ) = P ( ω 1 ) P ( ω 2 ) . . . P ( ω m ) P(\omega_1,\omega_2,...,\omega_{m}) = P(\omega_1)P(\omega_2)...P(\omega_m) P(ω1,ω2,...,ωm)=P(ω1)P(ω2)...P(ωm)观察可知,在一元语言模型中,整个句子的该来等于各个词语概率的乘积。言下之意就是各个词之间都是相互独立的,这无疑是完全损失了剧中的此讯信息。所以医院模型的效果并不理想。
n = 2时成为二元模型,n=3时称为3元模型,显示n越大,仅保留的词序信息越丰富,但是计算升本也呈指数级上升。一般使用频率计数的比例来计算n元条件概率:
P ( ω i ∣ ω i − ( n − 1 ) , . . . , ω i − 1 ) = c o u n t ( ω i − ( n − 1 ) , . . . , ω i − 1 , ω i ) c o u n t ( ω i − ( n − 1 ) , . . . , ω i − 1 ) P(\omega_i|\omega_{i-(n-1)},...,\omega_{i-1})=\frac{count(\omega_{i-(n-1)},...,\omega_{i-1},\omega_i)}{count(\omega_{i-(n-1)},...,\omega_{i-1})} P(ωi∣ωi−(n−1),...,ωi−1)=count(ωi−(n−1),...,ωi−1)count(ωi−(n−1),...,ωi−1,ωi)
其将分词作为字在字串中的序列标注任务来实现的。其基本思路是:每个字在构造一一个词语的时候都占据着一个确定的构词位置,先规定每个字最多只有四个构词位置:B(词首)、M(词中)、E(词尾)和S(单独成词)。
马尔可夫模型的话题太大,之后将会作为专题发布博客。
多种分词方式并用,实际中经常如此。
这个分词工具是目前看来最棒的中文分词工具,其具有以下特点:
import jieba ''' description: jieba分词,全模式 param {*} return {*} ''' sent = "中文分词是文本处理不可或缺的一步!" seg_list = jieba.cut(sent,cut_all=True) print("全模式:", '/ '.join(seg_list)) ''' description: jieba分词,精确模式 param {*} return {*} ''' seg_list = jieba.cut(sent,cut_all=False) print("精确模式", '/ '.join(seg_list)) ''' description: 默认精确模式 param {*} return {*} ''' seg_list = jieba.cut(sent) print("默认精确模式:",'/ '.join(seg_list)) ''' description: 搜索引擎模式 param {*} return {*} ''' seg_list = jieba.cut_for_search(sent) print("搜索引擎模式:",'/ '.join(seg_list))
高频词一般值文档中出现频率较高且减肥无用的词语,其一定程度上代表了文档的焦点所在。针对单片文档,可以作为一种关键词来看。对于如新闻这样的多篇文档,可以将其作为热词,发现舆论焦点。
高频词提取将在之后作为专题介绍。
词性是词汇的基本语法属性,通常也成为词类。 词性标注是在给定句子中判定每个词的语法范畴,确定其词性并加以标注的过程。例如,表示人、地点、十五以及其他抽象概念的名称几位名词,表示动作或状态变化的词即为动词,描述或修饰名词属性、状态的词为形容词。
在中文中,一个词的词性很多时候都是不固定的,一般表现为同音同形的词在不同的语境下,其表示的语法截然不同,这就为词性标注带来很大的困难;但是另一方面,从整体上看,大多数词语,尤其是诗词,一般只有一道两个词性,且其中一个词性的使用频次远远大于另一个,即使每次都将高频词行作为词性选择进行标注,也能实现80%以上的准确率。如此,若我们对常用词的词性都能进行很好的识别,那么就能覆盖绝大所属场景,满足基本的准确度要求。
目前较为主流的方法是如同分词一样,将句子的词性标注作为一个序列标注问题来解决,纳闷分词中常用的手段,如HMM,RCF等皆可在词性标注任务中使用。
本节介绍利用jieba分词工具来完成词性标注任务。
import jieba
import jieba.posseg as psg
sent = "中文分词是文本处理不可或缺的一步!"
seg_list = psg.cut(sent)
result = [(w,t) for w,t in seg_list]
print(result)
以上词典相当于用力默认的词典,但是jieba其实是支持自定义词典的。这个有机会作为专题讲解。
明明实体的目的是识别预料中任命、地名、组织机构名等命名实体。又是这些命名实体数量不断增加,通常不可能在词典中穷尽列出,且其狗比给方法具有各自的规律性,因此,通常吧对这些词的识别在词汇形态处理任务中独立处理,称为明明实体识别NER.。
NER研究的明明实体一般分为3大类(实体类、时间类和数字类)和7小类(任命、地名、组织机构名、时间、日期、货币和百分比)。
中文的命名实体识别主要有一下半点:
当前的主流的明明识别识别方法如下:
序列标注方法是目前命名实体识别中的主流方法。HMM,CRF等
条件随机场也将在之后作为专题介绍。
较为经典有效的关键词提取算法包括:
这个步骤主要用于机器翻译。句法分析的主要任务是识别出句子所包含的句法成分依据这些成分之间的关系,一般以句法树来表示句法分析的结果。
句法分析主要面对两个难点:
统计学习方法多需要预料数据的支撑,统计句法分析也不例外。相较于分词或词性标注,句法分析的数据集要复杂很多,其是一种树型的标注结构,因此有称为树库。
句法分析评测主要任务是评测句法分析器生成的树结构与手工标注的树结构之间的相似程度。其主要考虑两方面的性能:满意度和效率。其中满意度是值测试句法分析器是否适合或者胜任某个特定的自然语言处理任务;二效率主要用于对比卷发分析器的运行时间。
目前主流的分析评测方法是PARSEVAL评测体系。
相较于词法分析,句法分析的成熟度相对较低。目前常用的方法如下:
probabilistic Context Free Grammar 是基于概率的短语结构分析方法,是目前研究最为充分,形式最为简单的统计句法分析模型,也可以认为是规则方法与统计方法的结合。
PCFG是上下无关文法的结合。
文本表示是自然语言处理中的基础工作,文本表示的好坏直接影响到整个自然语言处理系统的性能。因此,研究者们投入了大量的人力物力来研究文本表示方法,以期提高自然语言处理系统的性能。在自然语言处理研究领域,文本向量化是文本表示的一种重要方式。顾名思义,文本向量化就是将文本表示成一系列能够表达文本语义的向量。无论是中文还是英文,词语都是表达文本处理的最基本单元。当前阶段,对文本向量化大部分的研究都是通过词向量化实现的。
有研究者将文章或者句子作为文本处理的基本单元,由此产生了doc2vec和str2vec技术。
基本思想是将文档中所有的单词都单独表示为一个向量的话,最简单的方式是全是(0,1)向量,如果是这个词汇则对应位置为1,其他位置为0(BOW)。但是这样做会造成以下几个问题:
word2vec可以从无标注的数据中提取有用信息。
一般来说词语是表达语义的基本单元。因为磁带模型知识将词语符号话,所以磁带模型是不包含任何语义信息的。如何使得“词表示”包含语义信息是该领域研究者们面临的问题。分布假设(distributional hypothesis)的提出也为解决上述问题提供了理论基础。
假说的核心是:
上下文相似的词,其语义也相似。
随后,有学者斋藤利了利用上下文分布表示词义的方法,这类方法就是又名的此空间模型。随着各类硬件设备计算能力的提升和相关算法的发展,神经网络模型逐渐在各个领域中崭露头角,可以灵活的对上下文进行建模是神经网络构造词的最大优点。下文将介绍神经网络构建词向量的方法:
前面提到过二元语言模型,神经网络语言模型与传统模型的不同点在于,传统的方法是估算 P ( ω i ∣ ω i − ( n − 1 ) , . . . , ω i − 1 ) P(\omega_i|\omega_{i-(n-1)},...,\omega_{i-1}) P(ωi∣ωi−(n−1),...,ωi−1),而NNLM模型直接通过一个神经网络结构对n元条件概率进行估计。
大致的操作是:
从语料库中搜集一系列长度为n的文本序列 ω i − ( n − 1 ) , . . . , ω i − 1 , ω i \omega_{i-(n-1)},...,\omega_{i-1},\omega_i ωi−(n−1),...,ωi−1,ωi,假设这些长度为n的文本序列组成的集合为D,那么NNLM的目标函数如下面式子所示:
∑ D P ( ω i ∣ ω i − ( n − 1 ) , . . . , ω i − 1 ) ) \sum_DP(\omega_i|\omega_{i-(n-1)},...,\omega_{i-1})) ∑DP(ωi∣ωi−(n−1),...,ωi−1))
上式的含义是:在输入词序列为 ω i − ( n − 1 ) , . . . , ω i − 1 \omega_{i-(n-1)},...,\omega_{i-1} ωi−(n−1),...,ωi−1的情况下,计算目标词为 ω i \omega_i ωi的概率。
上图所示的神经网络语言模型是经典的三层前馈神经网络结构,其中包括三层:输入层、隐藏层和输出层。为解决词袋模型的数据稀疏问题,输入层的输入为低纬度的、紧密的词向量,输入层的操作就是将词序列 ω i − ( n − 1 ) , . . . , ω i − 1 \omega_{i-(n-1)},...,\omega_{i-1} ωi−(n−1),...,ωi−1中的每个词向量按顺序拼接。
x = [ v ( ω i − ( n − 1 ) ) ; . . . ; v ( ω i − 2 ) ; v ( ω i − 1 ) ] x = [v(\omega_{i-(n-1)});...;v(\omega_{i-2});v(\omega_{i-1})] x=[v(ωi−(n−1));...;v(ωi−2);v(ωi−1)]
在得到x支行吧,将x输入到隐藏层h,再将h接入输出层得到最后的输入变量y,隐藏层变量h和输出变量y。
卷积、循环、LSTM
将会持续补充内容。。。。
2021年3月13日 更新
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。