本文是对前段时间学习自然语言处理(NLP)的总结。本文先介绍自然语言处理的内容,及其基于统计学的处理方式,在这个过程,逐渐矩阵化数据,看到矩阵化即可以想到机器学习方法的引入,预见到深度学习技术广泛应用的必然性。本文结尾我提供两个自己学习过程中建立的仓库,一个是对学习内容的总结,另一个是个对话机器人。
自然语言处理由以下几个任务构成:
分词
个人理解,NLP 根据问题的定义所关注的是文本的规模是不一样的,如文本聚类/分类,是以文档规模考量,而命名实体识别(NER),关注语言规模的则是文档中的词语。但和很多 NLP 任务一样,都绕不开分词这一操作,如果以文本为基本单位作为语言处理的对象,那语料是太稀疏,所做的处理泛化性太差太差了。这对语料的数量或者特征工程来说,尤其是深度学习以外的方法来说,几乎是不可能完成的任务。分词的方法有:
词典分词
中文分词有两类方法,一类是基于词典分词,一类基于机器学习方法。词典分词需要两部分:词典和查词典的规则。通过词典查询到的字符串才会被认定为词。词典查词涉及齐夫定律:越新的词,它的词频越小,趋于 0 。因此可以构建词典来查词。
词典分词的步骤:
(1) 构建词典
词典的样式如下:
词语1 | 词性1 | 词频1 |
词语2 | 词性2 | 词频2 |
… | … | … |
在词典分词中,词性和词频都是可以忽略的,它在接下来的章节中才有用。
(2) 从句子中切分单词(字符串)
采用完全切分的方法,在文本的开头设置两个指针,for 循环向前移动,判断切分的字符串是否是步骤 1 中词典的元素,是的话,则记录为单词 ,保存之,继续寻找单词。
这一方法有两个缺点:第一,效率低,双指针的循环遍历复杂度是 O(n^2) ;第二,会把长词切分为不同的短词汇( NLP 中认为长词的表达的信息比短词更丰富)。因此,最长匹配发应运而来,正向匹配的过程是与玩完全匹配法相似,逆向匹配法首位各放置一个指针,在这个固定尾指针,头指针向尾指针移动,同时判断截取的 string 是否是词典中的元素,是的话保存单词,我的理解是,保存为单词后,这段 string 内就不在继续遍历查词了,因为那样做,会把相对字少的单词找出来,失去了逆向匹配法的意义。上述两种方法得到单词后,按照单词的顺序,对文本进行切割,单词间插入空格。最后,还有双向匹配法,即上述两种方法同时采用,对得到的结果,有如下规则:第一,优先选择得到词数少的方案。第二,词数相同,则选择单字少的方案。第三,单字相同的情况,选取逆向最长匹配法的结果作为首选。
这部分还提到了字典树和 AC 自动机技术,我的理解是,字典树是将字符串转化为字典树,通过定义遍历字典树的路径,找到该字典树(字符串)中所包含的单词。AC 自动机这里不做过多赘述,我还需要看书搞懂。
统计方法分词
统计方法是统计训练数据什么是单词,以及该单词的词频(出现的次数),将统计结果作为对目标文档的分类依据。统计方法需要数据,训练,用得到的模型来产生句子的分词序列。
句子的模型就是句子出现的概率,这部分用到了马尔科夫模型,句子由单词构成,句子的概率等于单词序列的条件概率,简化为两个单词的条件概率,根据最大似然估计由二者频数算出,单词频数可由语料训练得到。
训练需要的数据称为语料,语料是已经分词的句子(文章)。经过训练得到模型,模型包括两部分,一元模型(一个词的频率)和(两个连续相邻词的频率)。有了这个模型,就可以对未分词的句子/文章进行分词。
有了模型,根据一元词的模型,可以构建词网,词网有个特色:第 i 行的词 $w$ 和第 $i + len(w)$ 行的词构成二元语法,依据词网可以构建词图,求解该图的最短路径,可以获得最佳的分词序列。
序列标注
序列标注是方法,不是最终应用,序列标注技术可以用于分词,命名实体识别,词性标注。
为什么需要序列标注,在前面词典分词的方法中,文本中的单词能否被识别,直接由词典决定,在词典中则能够识别,不在词典中则一定不能识别,一个语言的词汇是如此的丰富,这种方法对新词( OOV )无任何泛化能力,分词是将 NLP 处理数据的粒度由句子降为单词,提升对句子处理能力,序列标注则是将操作的粒度变为字符,以此提升对文本信息的敏感度。
序列标注的语料形式如下:
字符1 , $label ∈ { B , M , E , S }$
字符2 , $label ∈ { B , M , E , S }$
…
有了每个字符的 label 值,分词的结果方式就是 将 string [ B:最近的 $E$ ] 作为单词.通过得到的单词,为每个单词加入新的 $label_E ∈ 实体 {人名 , 地名, 物品 ,… }$ 则可进行实体识别,加入 $label_p ∈ { N,V,…}$ 等词性,则可以将序列标注用于词性标注。
这一部分,引入了隐马尔科夫模型,隐马尔科夫模型有两部分,一部分可见 $y$ ,如 $label$,一部分不可见,记做 $x$。该模型能够 由 $y$ 映射到 $x$, 在 NLP 中即根据语料 $label$ 反推语料特征。(PS:隐马尔科夫模型有其它用处,这里是生成隐藏部分 )。
马尔科夫模型的特点是,当前元素状态 $yt$ 仅由上个相邻元素状态 $yt-1$ 决定,与其它元素的状态无关。 而当前隐状态 $x$ 仅有当前时刻的显状态 $y$ 来决定。二者数学上都是条件概率。隐马尔科夫记做 $(π,A,B)$
在这部分,感知机(神经网),CRF 算法登场,用于序列标注。
命名实体识别
多个单词构成的复合词,称作命名实体。命名实体识别包括实体边界识别和实体性质 $(人,物,地?)$ 识别两部分。不同的任务中,对实体是有不同的定义的,这类任务有两类方法,一类基于规则,一类基于统计学习,这部分应用前面提到的方法,作者直接调用开发包完成的。
信息抽取
信息抽取是指在文本中找到文本中新单词的过程,这是个新词发下的过程。它的步骤是:第一,提取文本中的词语,不论新旧。第二,用词典过滤掉已有的词,得到新词,第三,对新词进行删选,留下的词则是文本的信息描述。
具体的,给定文本,切分得到新词后,对其有个测量值,左右搭配的丰富程度,叫做信息熵,记做 $H(X) h$,另一个是文本内内容搭配的固定程度,称作互信息,记做 $I(X,Y)$ 。信息熵表征信息量,它的值表征对时间 $X$ 不确定信息的减少量。其中,
$H ( X ) = - ∑ p (x) log( x) , P ( X, Y ) = P( X , Y ) / P ( X ) P ( Y )$,计算了新词的信息熵和互信息后,将低于设定阈值的新词剔除,余下的新词就是文本中抽取的新信息。
关键词/句抽取
关键词抽取
信息抽取关注的是文本中提取出的词语的新鲜程度,另一种需求是提取文本的关键信息的描述词,即关键词抽取。关键词抽取可以应用于单文档或者多文档,单文档中有词频法和 Textrank 算法。多文档应用 TF-IDF 算法。
词频法过程,分词后统计词频,过滤掉停用词后,取m个单词,从中选取词频最高的n个单词,算法的复杂度是 $O (m* log n)$。该方法的缺点是,高频词未必是关键词,不一定能反应文本特色。
如何确定一个高频词的重要程度呢?可由多文档验证,那么有 TF-IDF 算法如下:
其中 $t$, $D$ 为词和包含 $t$ 的文档,$TF (t,D)$ 是 $t$ 在文档中出现的频次,$DF( t )$ 是包含 $t$ 的数量。该算法在大型语料库上,类似 ML 的学习过程,如果没有大型语料库 或者 硬件上无法实施这一算法,可以尝试下 TextRank 算法,这一算法,这一算法类似 Google 提出的 PageRank,PageRank 中的节点是网页,根据节点间连接的权重可以计算节点的重要程度, TextRank 算法中,节点变为了单词,迭代计算 单词的重要程度
根据这一公式有如下结论:第一,节点给别的节点外链越多,每条外链的权重就越低;第二,一个节点如果都是这种权重很低的外链,在不断迭代中,该结点的权重会降低。
对于文本,选定中心词,确定半径为定值的窗口,让窗口内每个词都连接到它,模拟了窗口内的单词都对中心词进行描述。(PS: 初始时所有值是1)
关键句抽取
文档中难以有重复的句子,即缺少其它句子对该句子的描述,难以建立类似网页的那种多连接结构。因此,不能套用 TextRank 算法进行关键句提取。引入 BM25 算法,辅助进行关键句提取。BM25 是 TF-IDF 算法的改进,改进的是连接权重计算。 BM25 描述了一个句子与其它句子的相似度,即与其它句子的关联程度,一般认为,一个句子越是关键,那么文章中就会越多的对其进行解释,说明的语句,这些句子就与需要判断的句子有一定的相似性。 BM25 可以用于衡量多个词语与文档的关联程度。
文档 $D$,$Q$ 为句子,由 短语$q1,q2,q3…$构成。
可视作 IDF 的加权和,常数 $k1$ 越大,$TF$ 频次对文档得分的证明影响大, 常数 $b$ 越大,文档长度第二分的负面影响越大。将 BM25 算法带入到 TextRank 算法中,$BM25 ( Vi , Vj)$ 描述句子间的相似度,可得到句子重要性评分。正比于两个句子的相似度,反比于描述其它句子的总数。
现代NLP的共性
接下来是文本聚类,文本分类,深度学习等算法。
这些任务引入一个新的工具,词向量。也就是向量化后的文本用于现代NLP算法,词向量越来越重要,一些生成词向量的算法也要掌握。
one-hot,假设某个特征有三个取值,如 $1 ,2 , 3$,他们的含义是相似的。 但是计算平方和,有 $1,4$ 两种结果,说明不能以数字来标志该特征的取值。可以定义长度为 3 的向量,初始值为 $0$,三个值可以记做3个向量不同项取 1。
$[1,0,0],[0,1,0],[0,0,1]$,互相间欧式距离都是 1。
词袋模型这种特征提取方法,是将文档建立词典分词,取频数最大若干项放入词袋,也就是确定了文档向量的属性值和个数。遇到新的文档,先分词再取前 $n$ 个频数最大的单词与词袋中的词(属性)对比,不在词袋中则标记为 OOV,不予考虑。文档包含词袋中的词则将该属性记为1,不包含则置零,得到自身的特征向量。
深度学习的引入,给 NLP 带来的突破,这和我以前做的 CV 方面有相似性。这个方向内容简单几句话能够能概括,学界亦有分歧。我的观点是,自然语言处理当作验证新的深度神经网络方法论的角色,而深度学习也是融合进自然语言处理方法论的一部分。最近马毅教授对机器学习(深度学习)技术理论进行了探索,并且有新书及新课程问世,推荐学习。
我的两个关于自然语言处理的 Github 仓库
[1]. 本文对应 GitHub 仓库
[2]. 对话机器人