首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

从模型到算法,用机器学习解决90%的自然语言处理

在本文中,我们将分八大步骤来介绍如何用机器学习处理文本数据。我们将从最简单的方法开始,逐一讲解,然后分析更具体的方案细节,如特征工程、词向量和深度学习。你可以把本文看作是标准方法的高度概括。

读完本文后,你将学会:

如何收集,准备和检查数据

如何建立简单的模型,有必要的话,应构建深度学习模型

如何解释并理解你的模型,以确保模型学习的是特征信息而不是噪音

此外,本文还附有一个交互式笔记,让你可以随意运行本文中的代码,来演示和应用其中的技术,特别是一些比较抽象的概念:

代码链接 https://github.com/hundredblocks/concrete_NLP_tutorial/blob/master/NLP_notebook.ipynb

步骤1:收集数据

数据标签

在样本数据中,每条推文属于哪个类别都已被标记出来。正如Richard Socher在推文中所说的,找到并标记足够的数据来训练有监督模型,往往是一条更快、更简单、成本更低的路径,远比难于优化的无监督方法有效。

Richard Socher的观点

步骤2:数据清洗

机器学习的第一条原则是:“数据有多好,模型的性能才会有多好”。

知道何时该调整模型何时要处理数据,这一能力是数据科学家的核心技能之一。一条良好的经验就是先查看数据进而把它清洗好。一个干净的数据集,可以让机器学习模型学到有意义的特征,而非过拟合在不想关的噪音信息上。

下面列出了一些数据清洗的方法,你可以自己尝试(更多细节见代码https://github.com/hundredblocks/concrete_NLP_tutorial/blob/master/NLP_notebook.ipynb):

删除所有不相关的字符,如任何非字母或数字的字符串。

将文本信息分离成单独的文字,并逐字进行标记。

移除一些不相关的字词串,比如Twitter的“@”标识、网址链接等。

将所有字幕转换为小写,避免重复识别“hello”,“Hello”和“HELLO”等同类词汇。

考虑合并拼写错误或替代拼写的单词,如“cool”/“kewl”/“cooool”。

考虑将不同变体的词形还原回来,如将“a”、“is”和“are”等单词还原成“be”的这种通用形式。

按照上述步骤处理并检查数据后,我们就可以使用这些干净的标注数据来训练机器学习模型了!

步骤3:找到一种好的数据表示

机器学习模型通常以数值作为输入。例如,处理图像的模型是以每个颜色通道中像素值矩阵作为输入的。

一副笑脸图可以被表示成这样的数字矩阵

我们这里的数据集是句子列表,为了让模型可以从数据中学到句子的特征模式,我们首先要找到一种方法来把它转换成模型能理解的形式,即数字列表。

独热编码(词袋)

通常,计算机文本数据的表示是将每个字符编码成一个独特的数字(例如ASCII码表)。如果把这么简单的表示输入给分类器,它就只能根据这些数据从头来学习单词的结构,这对大部分数据集来说是不现实的。这就要求我们采用更高级的数据表示方法。

例如,我们可以为数据集的所有词汇建立一个特定的词汇表,令每一个词汇对应一个唯一的索引值。这样,每句话均可表示为一个列表,列表的长度由词汇表中单词的数量来决定。列表的每处索引值,标识一个给定单词在句中出现的次数。这就是我们常说的词袋模型(bag-of-words),因为它完全无视单词在句中的先后次序。如下图所示:

将句子表示为词袋模型(bag-of-words):左边是句子,右边是对应的表示。向量中的每个索引都代表一个特定的词。

词嵌入模型的可视化

在“社交媒体灾难”样本中,我们有大约20000个的单词,这意味着每个句子都会被表示成一个长度为20000的向量。该向量的大部分元素都是0,因为相对于完整的词汇表,每个句子都只是一个非常小的子集。

为了进一步了解词嵌入模型能否捕获到与问题相关的信息(即推文内容是否与灾难有关),我们可以将其可视化并检查不同类别的数据是否能很好地分离。由于词汇表的量通常都非常大,在20000个维度上显示数据不现实,因此像PCA(主成分分析)这样能把数据降维到两个维度的技术就很有帮助了。绘图如下:

词袋嵌入模型的可视化结果

结果表明,这两类数据的分离效果不是很好。这可能是由于我们所嵌入的某一个特征,或仅仅是因为我所降低的特征维度。为了验证词袋模型(bag-of-words)所学到的特征是否对分类有用,我们可以用它们来训练一个分类器。

步骤4:模型分类

刚接触机器学习问题时,我们最好从能解决问题的最简单工具上手。每每涉及到数据的分类,Logistic回归都会是很好的选择。因为它的通用性与可解释性都很好,训练过程也非常简单,结果极易解释,很容易就能提取出模型中最重要的系数。

我们将数据分成训练集和测试集,训练集用于生成模型,测试集用于检查模型在未知数据上的泛化情况。训练完成时,我们得出75.4%的分类准确度。还不算太差!而判断“不相关内容”时,准确度只有57%。尽管如此,75%的识别精度也足以满足我们的需求。下一步,在部署前,我们要做尽可能全面的可视化分析,并彻底理解这个模型。

步骤5:模型检查

混淆矩阵

理解模型的第一步是要知道模型错分的数据类型,以及最不应该出现的错误类别。在我们的例子中,假阳性结果是指将不相关推文错分为灾难性推文,而假阴性结果类则将灾难性推文归类为不相关推文。如果要优先处理潜在的灾难性事件,那我们要降低假阴性结果。而如果资源比较受限,我们就需要优先降低假阳性结果,以减少误报。使用混淆矩阵可以很好地可视化这里的信息,并将模型预测结果与数据的真实标签进行比较。理想情况下,混淆矩阵是一条从左上角到右下角的对角线。

混淆矩阵

相比假阳性结果,我们的分类器产生了更多的假阴性结果。换句话说,模型中最常见的错误是将灾难性推文错误归类为不相关推文。如果假阳性结果的执法成本很高的话,那么我们分类器的这种偏差就是良性的。

模型的可解释性

为了验证模型并解释它的预测结果,我们需要明确模型用以进行判断的那些词汇。如果我们的数据有偏差,而分类器在样本数据中却能做出准确预测,那这样的模型就无法在现实世界中很好地推广。

在这里,我们可以用图表来表示灾难性推文与不相关推文两类预测中最重要的词汇。由于我们可以对模型的预测系数进行提取和排序,用词袋模型(bag-of-words)和Logistic回归模型很容易就能计算出单词的重要性。

词袋模型(bag-of-words):单词的重要性

我们的分类器能够正确识别出一些模式(如广岛、大屠杀等),但在一些毫无意义的词汇(如heyoo、x1392等)上还是出现了过拟合。词袋模型(bag-of-words)仅能处理庞大词汇表内的不同词汇,并对所有的词汇分配相同的权重。然而,其中一些词汇出现得非常频繁,但却只是预测结果的噪音数据。接下来,我们将试着找到一种能够表示词汇在句子中出现频率的方法,尽量让模型从数据中获取更多的信号。

步骤6:词汇结构的统计

TF-IDF嵌入模型

为了让模型专注于学习更有意义的词汇,我们可以在词袋模型上面使用TF-IDF评分(术语频率,逆文档频率)。TF-IDF通过词汇在数据集中的稀有程度来评估它的重要性,适度削弱出现过于频繁的单词。下图是TF-IDF嵌入模型的PCA映射:

可视化TF-IDF嵌入模型

从中可以看出,两种颜色之间有了更清晰的区分,使这两类数据更易于被分类器分开。在新模型上训练Logistic回归,我们得到了76.2%的准确度,说明TF-IDF确实有助于提高识别性能。

TF-IDF嵌入模型:单词的重要性

可以看到,新模型学到的词汇看起来相关度更高!尽管测试集的指标只是略有增加,但是我们对模型的识别性能更有把握,因此部署新模型的交互系统会让用户体验更为舒适。

步骤7:语义信息的利用

Word2Vec

TF-IDF嵌入模型能够学习到信号更高频的词汇。然而,如果部署该模型后,我们很可能会遇到一些训练集中从未出现过的词汇。先前的模型均无法正确分类这样的新数据,即便其中的词汇与训练集非常相似。

要解决这个问题,我们就要捕捉词汇的语义,这就意味着模型需要理解“好”与“积极”在语义上的距离要比“杏”和“大陆”更接近。这里的工具就是Word2Vec。

使用预训练的嵌入模型

Word2Vec是一种为单词查找连续嵌入的技术。通过阅读大量的文字,它能够学习并记忆那些倾向于在相似语境中出现的词汇。经过足够的数据训练之后,它会为词汇表中的每个单词都生成一个300维的向量,用以记录语义相近的词汇。

Word2Vec作者在一个非常大的语料库上预训练并开源了该模型。利用这一语料库,我们可以将一些语义知识纳入到我们的模型内。预训练好的词向量可以在本文的GitHub代码库中找到。

GitHub地址:

https://github.com/hundredblocks/concrete_NLP_tutorial

句子分级表示

让分类器快速得到句子嵌入的方法,是先将句中所有词汇Word2Vec得分的平均化。这与此前词袋模型的做法类似,但这里我们在保留语义信息的同时只丢弃句法。

Word2vec模型的句子嵌入

利用前面的可视化技术对新模型绘图,结果如下:

Word2Vc嵌入模型的可视化结果

在这里,两组颜色的分离程度更大一些,这就意味着Word2Vec能够帮助分类器更好地分离这两种类别。再一次使用Logistic回归,得到77.7%的准确率,是我们迄今最好的结果!

复杂性/可解释性权衡取舍

与先前的模型不同,新模型无法将每个单词都表示成一维向量,因此很难看出哪些词汇与我们的分类结果相关度最高。尽管我们仍可使用Logistic回归的系数,但它们仅与嵌入的300个维度相关,而与词汇索引值并不相关。

模型准确率确实提高了,但完全做不了可解释性分析就有点得不偿失了。不过,对于更复杂的模型,我们可以利用LIME这样的“黑盒解释器”来稍微解释一下分类器具体是如何工作的。

LIME

LIME是Github上的一个开源软件包,它允许用户通过观察输入的扰动来分析一个特定分类器的预测结果是如何变化的。

从下图来看它对我们数据集中几个句子的解释:

正确分类的灾难性词汇被归类为“相关”

这个词对分类的影响似乎不太明显

不过,我们没有时间去逐一探索数据集中的数千个样本。我们要做的是在代表性的测试样本上运行LIME,以此来分析哪些词汇对于分类预测的影响更大。这样,我们就可以像前面一样获取到单词的重要性分数,以验证模型的预测结果。

Word2Vec:单词的重要性

模型能够提取高度相关的词,这意味着它做出了可解释的决定。这些词汇的相关度是最高的,因此我们更愿意在实际生产中部署这样的模型。

步骤8:使用端到端的方式训练语法特征

我们已经介绍过如何用快速有效的办法来生成紧凑的句子嵌入。然而,通过省略词汇的顺序,我们也放弃了语句的所有句法信息。如果简单的方法给不出令人满意的结果,那我们就用更为复杂的模型:将整个句子作为输入并预测标签,同时无需建立中间表示。一种常见的做法是把句子视为词向量的序列,如使用Word2Vec,或是GloVe、CoVe等更先进的方法。接下来我们详细讨论。

高效的端到端的训练体系结构(源)

用于句子分类的卷积神经网络训练速度很快快。它作为一种入门级的深度学习架构,能够很好地解决分类问题。尽管CNN声名主要源自它在图像处理方面的出色能力,但在文本相关任务上,它所提供的结果也相当优异。且相比多数复杂的NLP方法,CNN训练速度也更快。它能够保留单词的顺序,很好地学习单词的序列特征以及其他有用信息。相对于先前的模型,它可以区分出“Alex eats plants”与“Plants eat Alex”之间差异。

上述八大步骤所用的模型是我们处理短文本时的几个特定实例,但其背后的解决方法已经广泛被用在各类NLP问题的实际处理上。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180127B04YOA00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券