入门 NLP 项目前,你必须掌握哪些理论知识?
引言
今年一月开始,我一直在从事一个从非结构化的文本中提取信息的项目。在开始这个项目之前,我对自然语言处理(NLP)领域一无所知。当我刚开始研究这个领域时,我很快就找了一本名为「Python 自然语言处理」的书(图书查阅地址: https://www.nltk.org/book/ )。这本书对于我来说过于理论化了,但其中的知识基本是正确的,因此它对我来说仍然是无价的资源。接下来,我发现了 Dipanjan Sarkar 编写的「Python 文本分析」(图书查阅地址: https://www.apress.com/gp/book/9781484243534 ),并从头到尾通读了此书。这本书真的太棒了,它教会了我入门 NLP 项目所需的所有技术技能。最近,此书的第二版( https://www.apress.com/gp/book/9781484243534 )也面世了,对上个版本进行了大量的扩充。
在本文中,我想概述一下我在学习 NLP 技术时研究过的一些问题。我知道有已经有很多很棒的文章也讨论过相同的问题(比如 Sarkar 撰写的一系列文章: https://towardsdatascience.com/a-practitioners-guide-to-natural-language-processing-part-i-processing-understanding-text-9f4abfd13e72 ),但对于笔者来说,将这些问题写下来对于自己梳理自己所掌握的知识很有帮助。
本文涉及的内容
为简洁起见,本文主要还是偏理论一些。今后我会编写更多的实用性的文章。现在,我将讨论以下几个问题:
-
1. 使用 NLP 处理文本
-
2. 从文本中提取特征
-
3. 文本的监督学习
-
4. 文本的非监督学习
文本预处理
一个典型的文本预处理工作流程由以下 4 个步骤组成:
-
1. 句子分割
-
2. 文本归一化和分词
-
3. 词性标注(POS)
-
4. 命名实体识别
在大多数应用中,并不需要执行以上所有的预处理步骤。是否需要进行命名实体识别取决于应用的具体业务需求,而词性标注工作则通常由现代工具自动完成,从而改进归一化和分词步骤的某些部分。
句子分割
预处理工作流程的第一步是将文本分割成多个句子。在许多语言环境下(例如英语),标点符号(特别是句号、感叹号和问号)可以被用来表明句子的结束。然而,句号字符也可以被用在缩写中(如 Ms. 或 U.K.),此时句号字符则并不表示句子结束了。在这种情况下,我们会使用缩写表来避免对句子边界的误分类。当文本包含特定领域的术语时,必须创建一个额外的缩写词典,从而避免产生不自然的词(token)。
分词和归一化
分词时的极端情况
「分词」指的是将文本划分成单词和标点(即「词」(token))。与在句子分割中的情况一样,此时对标点符号的处理仍是一个具有挑战性的问题。例如,U.K. 应该被视为一个词,同时「don't」不应该被分成两个词:「do」和「not」。
词干提取(stemming)和词形还原(lemmatization)是文本归一化过程的重要组成部分。归一化由词干提取和词形还原组成。在词干提取过程中,通过删除后缀(如 -ed 和 -ing)来识别单词的词干。由此得到的词干并不一定是一个单词。类似地,词形还原包括删除前缀和后缀的过程,它与词干提取的重要区别在于它的结果是自然的语言。这里的结果被称为词元(lemma)。词干提取和词形还原的例子如下表所示:
词干提取和词形还原的差异
这两种技术都通过讲将单词转化为其基本形式来降低文本中的噪声。对于大多数应用来说(如文本分类或文档聚类),保留单词的意义是非常重要的,因此最好使用词形还原而不是词干提取。例如,「meeting」(名词,会议)和「meeting」(动名词,会见)通过词干提取都会得到「meet」,因此并没有准确地保留原本的意思,它们各自的词元分别为「meeting」和「meet」。
其它的归一化技术还包括:缩写扩展、删除数字和标点符号、纠正典型的语法错误等。这些操作大多都可以通过使用正则表达式来完成。
词性标注
这一步是基于单词的上下文和定义,将词(token)分类为不同的词性(POS)类别,也被称为单词分类或词法分类。POS 类别包括名词、动词、介词、副词等。英语环境下的词法分类示例如下图表所示。词性标注提升了词形还原的效果,其对于命名实体识别是必要的。
常用的 POS 类的示例
通常有三种类型的词性标注器: 基于规则的、基于统计的和基于深度学习的词性标注器 。基于规则的词性标注器依赖于显式的规则,例如一篇文章的标题后面必须紧跟一个名词,从而对这个词(token)进行标注。基于统计的词性标注器使用概率模型来标注单个单词或单词序列。基于规则的词性标注器非常精确但是却与语言高度相关。
基于统计的标注器更易于创建,并且是与语言无关的,而代价则是牺牲了一定的精确度。如今,尽管工业界开始逐渐转而寻求深度学习解决方案(在预先标注的句子集上训练模型),但基于规则的模型和统计模型仍然会被混合使用。基于混合方法和深度学习的方法提升了上下文敏感的词性标注任务的性能。
命名实体识别
在识别命名实体之前,必须对词(token)进行组块分析(chunk)。组块分析意味着对一组词进行分割和标记。最常用的组块是名词短语组块,它由限定词、形容词、以及一个名词组成(例如,「a happy unicorn」(一只快乐的独角兽))。句子「He found a happy unicorn」(他发现了一只快乐的独角兽)由两个组块「他」和「一只快乐的独角兽」组成。
命名实体是指示特定物体(例如,人、祖师、地点、日期、地缘政治实体)的名词短语。命名实体识别(NER)的目标是识别文本中提到的命名实体。
带有 NER 标签的句子
机器学习
正如 Brink 等人定义的那样,机器学习(ML)就是利用历史数据中的模式来对新的数据做出决策[1],或者就像谷歌首席决策科学家 Cassie Kozyrkov 所述:「机器学习就是一个对事物的标记器,根据你对某件事物的描述,告诉你它应该被赋予什么标签」(相关阅读: https://hackernoon.com/the-simplest-explanation-of-machine-learning-youll-ever-read-bebc0700047c )。当你所面临的问题过于复杂,而无法通过编程解决时(比如区分出图像中不同种类的猫),或者解决方案需要适应时间的变化(比如识别手写文本)时,应用机器学习技术是非常有用的。
通常而言,机器学习被分为监督学习和无监督学习。当我们的历史数据包含标签(例如,下图中的「鸭子」和「不是鸭子」)时,我们可以使用监督学习。另一方面,如果数据中没有包含标签,这应该使用非监督学习。非监督机器学习方法旨在总结或压缩数据。
下面我们通过垃圾邮件检测和异常检测的例子来说明这两种学习方法之间的区别。在监督学习中,我们拥有带有「垃圾邮件/非垃圾邮件」标签的训练数据;而在非监督学习中,我们则须要基于(无标签的)电子邮件的训练集检测异常邮件。
监督学习和非监督学习的区别
特征提取
所有的机器学习算法都需要数值型数据作为输入。这意味着文本数据必须被转化为数值型数据。这就是 NLP世界中特征提取步骤的本质。
基于计数的策略
将文本转化为数值向量的最简单的方法就是使用词袋(BoW)方法。词袋方法的的原理是提取出文本中所有特有的单词,并且创建一个文本语料库,称为词汇表。通过使用该词汇表,可以将每个句子表示为一个由 0 和 1 组成的向量,向量元素的取决于词汇表中的某个词是否出现在该句子中。下图显示了使用 BoW 方法在五个归一化处理后的句子上创建的矩阵的一个示例。
例句
根据上面的句子创建的 BoW 特征矩阵
为了给词汇表添加更多的上下文信息,可以将词(token)组合在一起。这种方法被称为 N 元(N-gram)方法。一个 N-gram 是由 N 个词(token)组成的序列。例如,一个 2-gram(双字母组,bigram)是由两个单词组成的序列,而三字母组(trigram)则是由三个单词组成的序列。
一旦选定了单词表,无论是对于 1-gram、2-gram 还是 3-gram,都需要计算出 gram 出现的次数。我们可以使用 BoW 方法。这种方法的缺点是,会使流行词(出现频率高的单词)变得过于重要。因此,这里最受欢迎的方法被称为「词频-逆文档频率法」(TFIDF)。
对 TF-IDF 的抽象解释
TF-IDF 由词频(TF)和逆文档频率(IDF)构成,前者表示单词相对于句子长度的重要性,而后者则表示单词相对于文档总行数出现的行数。直观地说,如果一个单词经常出现在目标文档中,但并不经常出现在所有文档的集合中,那么它的 TF-IDF 值就会较高。下图显示了根据之前见过的例句创建的 TF-IDF 矩阵的示例。请注意,单词「fox」(狐狸)的得分与出现更为频繁的单词「rabbit」的得分有何不同。
根据例句创建的 TF-IDF 特征矩阵
高级策略
虽然基于技术的方法可以被用来表征单词序列(n-gram),但它们并不能捕获单词的语义上下文,而这正是许多 NLP 应用的核心。我们通过词嵌入技术来解决这个问题。我们可以使用词嵌入将单词表转化为向量,这样一来具有相似上下文的单词的距离就相近。
「Word2Vec」(相关论文: https://papers.nips.cc/paper/5021-distributed-representations-of-words-and-phrases-and-their-compositionality.pdf )是谷歌开发的一个框架。它使用浅层神经网络训练词嵌入模型。
「Word2Vec」算法有两种类型:(1)Skip-gram,被用来预测给定单词的上下文。(2)连续词袋(CBOW)模型,被用来在给定上下文的情况下,预测下一个单词。
全局向量方法(GloVe, https://www.aclweb.org/anthology/D14-1162 )使用共现统计量来创建向量空间。该方法是对 Word2Vec 的扩展,期望得到更好的词嵌入。下图显示了根据例句构建的 GloVe 词嵌入的示例,以及这些词嵌入的图形化表示。正如我们设想的那样,类似的概念距离相近。
使用 GloVe 嵌入创建的特征矩阵
投影到一个二维空间的词向量
此外,Facebook 也开发了一个名为「FastText」的 Word2Vec 的版本。FastText 是一个深度学习框架,它在创建向量空间时考虑到了单个的字符。
监督学习
根据标签(也被称为目标)的格式不同,可以将监督学习分为两类。如果目标是一个类别的离散值(猫/狗),那么它就是一个分类问题;而如果目标是连续数值(房价),那么它就是一个回归问题。在处理文本时,我们经常会遇到分类问题。
典型的监督学习工作流程
上图显示了一个文本分类系统的典型工作流程。我们首先将数据划分为一个训练集和一个测试集。我们需要对训练数据和测试数据进行预处理和归一化,接着就可以提取特征了。本文前面的章节已经介绍了大多数流行的特征提取技术。当文本数据被转化为数值形式后,我们就可以对其应用机器学习算法了。
我们将这个过程称为训练模型——模型从特征中学习模式从而预测标签。首先使用通过一个被称为超参数调优的过程得到的模型参数,可以对模型进行优化,从而得到更好的性能。然后使用模型之前没有遇到过的测试数据对生成的模型进行评价。模型的性能是通过各种度量来衡量的,例如准确率、精度、召回率、F1 值,等等。本质上,这些得分是为了将真实标签和预测标签进行比较而建立的。
用于文本分类的典型算法包括:
-
多项式朴素贝叶斯——该算法属于朴素贝叶斯算法家族,构建在对贝叶斯定理的应用之上,假设每个特征之间都是相互独立的。多项式朴素贝叶斯是一种用于具有两个以上不同标签的分类任务的(多分类问题)对朴素贝叶斯算法的扩展。
-
Logistic 回归——该算法使用 Sigmoid 函数预测分类得分。广受欢迎的「sklearn」程序包允许对模型参数进行调优,使得该算法也可以用于多标签分类问题。
-
支持向量机(SVM, https://medium.com/machine-learning-101/chapter-2-svm-support-vector-machine-theory-f0812effc72 )——该算法使用一条直线或一个超平面(如果有两个以上的特征,此时需要创建一个多维空间)来分离不同的类。
-
随机森林——该算法是一种在不同数据子集山并行地训练多个决策树的集成方法。
-
梯度提升机(GBM)——这是一个集成学习方法家族,它们训练一系列弱学习器(如决策树),从而获得准确的结果。XGBoost 是这个算法家族中最流行的实现之一。
分类算法列表中的最后两项是集成方法,它们使用许多预测算法来实现更好的泛化。集成方法的效果通常比单个模型更平均,并且集成方法在较大的数据集上效果更好。然而,正如 Sarkar 在[6]中所证明的,集成方法并不一定能更好地处理文本数据。
评价指标
混淆矩阵以及从中得出的各种度量方法
混淆矩阵是评估机器学习模型最简单、最直观的工具之一。它给出了实际值与预测值之间的关系。尽管混淆矩阵本身就是一个有力的工具,但是与其相关的术语又被用作了其它度量方法的基础。关于混淆矩阵的重要术语如下所示:
-
真正例——我们预测为正而实际也为正的情况。
-
真负例——我们预测为负而实际也为负的情况。
-
假正例——我们预测为正而实际为负的情况。
-
假负例——我们预测为负而实际为正的情况。
根据混淆矩阵导出的度量标准如下:
-
准确率(accuracy)——模型做出正确预测的数量与全部预测数量之比。
-
精度(precision)——正确预测为正的样本数与所有预测为正的样本数之比,即有多少选中的项是相关的。
-
召回率(recall)——正确预测为正的样本数与所有实际为正的样本数之比,即有多少相关的项被选中。
-
F1 值——使用调和均值融合精度和召回率得到的单个分值。调和均值是 x 和 y 相等时的平均值。但是当 x 和 y 不同时,它就会接近于更小的值,而不是更大的值。
只有当标签包含大致相同数量的数据点时,准确率才是一个有用的度量指标。以上四个度量指标的取值范围都是 0-1,其中 1 位最佳得分,而 0 位最差的得分。
非监督学习
当待分析的数据集没有标签的时候,可以使用非监督机器学习技术(如聚类)。聚类是非监督学习的一个分支,其目的是将相似的对象组合到一起。
聚类的示例
常用的聚类算法分为以下几类:
-
基于连通性的聚类——也被称为层次聚类,根据数据点之间的距离将它们连接起来。连接这些点的策略有两类:(1)凝聚型。这是一种「自底向上」的方法,其中每个数据点一开始会形成自己的簇,然后迭代地合并成对的簇。(2)分裂型。这是一种「自顶向下」分裂的方法,其中整个数据空间被递归地分裂。对于凝聚型层次聚类来说,还有两种必要的度量指标:说明两个数据点相似程度的距离度量(典型的例子有:欧几里得距离、汉明距离、余弦距离),以及一个说明数据点簇相似程度的连接标准。
-
基于质心的聚类算法——根据数据点与簇的质心的临近程度将数据划分到不同的簇中。「K-Means」是这类算法中最流行的一种实现。算法的基本流程如下:(1)选取簇的个数 k,(2)将数据点分配到簇中,(3)计算簇的质心,(4)重新将数据点分配到最近的质心代表的簇中,(5)重复前两个步骤,直到质心不再变化。
-
基于密度的聚类算法——数据空间被划分,并形成密度不同的区域。其中 DBSCAN 和 OPTICS 是两种最流行的算法,它们会提取出数据空间中臭咪咪的区域,将「早上」数据留在稀疏区域中。OPTICS 算法试图克服 DBSCAN 在边界和密度不一的数据集上性能不佳的缺点。
文本摘要
文本摘要任务可以被划分为两个部分:主题建模和自动文本摘要。其中,自动文本摘要是一类使用机器学习算法创建文档摘要或一组文档的过程。这些算法在处理大量文档和长文档时效果最佳。
另一方面,主题建模侧重于从文档集合中提取出主题。主题模型通常被称为概率统计模型,因为他们使用到了统计技术(例如,奇异值分解(SVD)),从文本中发现潜在的语义结构。SVD 依赖于线性代数中的矩阵分解技术,能将特征矩阵分解成更小的部分。诸如潜在语义索引(LSI)、潜在狄利克雷分布(LDA)、以及非负矩阵分解(NNMF)等方法利用线性代数中的技术将文档内容划分为不同的主题,其本质上是单词聚类,如下图所示。当文本多样性高时,主题建模算法往往会得到更好的结果。
主题建模原理示意图
结语
在本文中,我针对读者开始从事与自然语言处理和机器学习相关的项目时可能遇到的重要问题进行了概述。本文只是触及了这个领域的皮毛。我甚至没有涉及到使用迁移学习进行语言建模这样激动人心的最新进展,读者可以从 Sebastian Ruder 的博文( https://ruder.io/nlp-imagenet )中阅读到相关信息。
在我看来,现在正是在工业界实践应用 NLP 技术的大好时机。正如 Yoav Goldberg 在最近的一次会议上所说的,大部分工业界同仁还停留在使用正则表达式解决问题的阶段(相关阅读: https://medium.com/@arnelapnin/highlights-from-spacy-irl-802229333785 )。通过理解我在本文中介绍的理论,并将其应用到现实生活问题中,你可以真正造福于大众。 雷锋网雷锋网雷锋网 (公众号:雷锋网)
Yoav Foldberg 在 spaCy IRL 会议上报告应用 NLP 的最新进展
参考文献
[1] H. Brink, J. W. Richards, and M. Fetherolf, Real-world Machine Learning (2017), Manning Publications
[2] S. Shalev-Shwartz, S. Ben-David, Understanding Machine Learning: From Theory to Algorithms (2014), Cambridge University Press
-
https://www.cs.huji.ac.il/~shais/UnderstandingMachineLearning/ )
[3] T. Mikolov, I. Sutskever, K. Chen, G. S Corrado, and J. Dean. Distributed Representations of Words and Phrases and their Compositionality (2013), Advances in Neural Information Processing Systems 26
-
https://papers.nips.cc/paper/5021-distributed-representations-of-words-and-phrases-and-their-compositionality.pdf
[4] J. Pennington, R. Socher, and C. D. Manning, GloVe: Global Vectors for Word Representation (2014), In EMNLP.
-
https://www.aclweb.org/anthology/D14-1162
[5] P. Bojanowski, E. Grave, A. Joulin, and T. Mikolov. Enriching word vectors with subword information (2016), arXiv preprint
-
https://aclweb.org/anthology/Q17-1010
[6] D. Sarkar. Text Analytics with Python: A Practitioner’s Guide to Natural Language Processing (2019), Apress
via https://towardsdatascience.com/the-theory-you-need-to-know-before-you-start-an-nlp-project-1890f5bbb793
。