Press "Enter" to skip to content

[译] 掌握这些套路,你也能解决 90% 的 NLP 问题

 

编译-maistern

 

今天将传授大家如何一步一步解决 NLP 自然语言处理中 90% 常见问题。 要知道,NLP 并不难入门,作为人工智能领域的认知智能,是目前大家关注的焦点。很多企业和研究机构都已进入自然语言领域,寄望未来在人工智能方向大展身手。俗话说,万事开头难。如果第一件事情成功了,大家就能建立信心,找到窍门,今后越做越好。否则,也可能就灰心丧气,甚至离开这个领域。今天,优达君就来说说个人应该如何开始 NLP 领域的学习和研究。

 

无处不在的文本数据

 

不管是企业运营还是新服务推广,你将难免和文本数据打交道,甚至用它来验证、提升以及拓展产品性能。而这种涵盖信息提取和文本挖掘的科学正是目前热门的研究领域——自然语言处理(NLP)。

 

自然语言处理是一个非常宽泛的领域,每天都会有各种新的令人兴奋的研究成果。但是在商业应用中,即使是对于服务了上百家企业的洞察团队,常见的也就在几个的核心的应用上:

 

识别不同的客户/用户群体 (如客户流失预测、生命周期价值,产品偏好)

 

准确提取客户的不同反馈(如正负面评论判断,提到如衣服尺寸这类特殊属性信息的提取)

 

依据语意进行文本分类(如判断客户需求是基本请求还是紧急问题)

 

虽然网上有很多自然语言处理的论文和教程,但很难找到一些指导和技巧教你如何从零开始有效的解决这些问题。

 

本文的正确打开姿势

 

本文结合丰富的项目经验和大牛建议,总结了一些如何用机器学习的方法来解决上述问题的套路。首先,我们会从最简单的方法入手,然后慢慢进阶到更高级的方法,比如特征工程,词向量和深度学习。

 

阅读完本文,你将掌握:

 

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

 

从建立简单模型入手,进阶到深度学习

 

解释和理解你的模型, 确保已捕捉到关键信息

 

你既可以将本文作为逐步学习的指导手册,也可以作为一套高效标准方法的简要概述。

 

代码链接:

 

https://github.com/hundredblocks/concrete_NLP_tutorial/blob/master/NLP_notebook.ipynb

 

第一步:收集数据

 

数据源实例

 

每一个机器学习的问题都是从数据开始,例如一系列邮件、文章或者推特。文本信息的常见来源有:

 

商品评论(如亚马逊,Yelp 商店和各种应用商店)

 

UGC(如推特,脸书文章,Stack Overflow 问题)

 

故障诊断信息(如客户需求,支持请求,聊天记录)

 

“社交媒体灾难”数据集

 

本文采用的是 Figure Eight (优达学城「数据科学家」合作企业)提供的“社交媒体灾难”数据集。该数据集筛选出超过 1 万条包含了像“纵火 (ablaze)”,“检疫 (quarantine)”,“暴动 (pandemonium)”关键词的推文,并标注出改推文是否真的说的是灾难事件,而不是一些玩笑或者影评之类的内容。

 

我们的任务是判断那条推文说的是真正的灾难事件而不是无关内容。为什幺要这样呢?一个潜在的应用场景就是可以筛选出一些真正的紧急情况来通知执法部门,而过滤掉一些无关信息。

 

而对于这项任务难度在于,两类推文其实都包含了一些相同的字句,所以我们需要找到一些微妙的差异来区分它们。后文中,将称灾难有关的推文为“灾难”,其余称为“无关”。

 

标签

 

我们的数据集已经打好了标签,也就是说,我们已经知道每个推文属于哪一类。正如 Richard Socher 下面说的,与其试图去优化复杂的无监督模型,更简单易行的方法是,寻找或者标记够多的标签数据来训练模型。

 

 

“相比于花上一个月的时间去解决非监督机器学习问题,还不如花上一周的时间打标签来训练一个分类器。” ——专业贴士

 

第二步:清洗数据

 

首要原则:“数据的优劣决定了模型好坏!”

 

作为数据科学家/自然语言处理专家,一项关键技能就是清楚自己下一步是研究模型还是数据,好的做法是:先检查数据然后清洗数据。干净的数据集可以使模型提取更多有效特征。

 

你可以通过以下步骤来进行数据清洗(英文场景下):

 

 

删除所有无关字符,比如非字母数字字符

 

文本分词

 

删除无关词,比如推特中的“@”和网址链接

 

将所有字符串转成小写,为了使“hello”,“Hello”,“HELLO”这类词统一

 

修正错拼的单词,如“cool”,“kewl”,“ cooool”

 

词干化,避免词性变化干扰

 

 

当你完成以上步骤并检查好其他错误之后,便可以使用干净的标签数据来建模啦!

 

第三步:找到一个好的数据表示

 

机器学习以数值性变量作为输入,而对于图像处理任务时,则利用矩阵来表示各个颜色通道的像素亮度。

 

 

而我们的数据是一系列句子,所以为了我们的算法能从文本中提取信息,我们首先要为文本数据找到一种算法可识别的表示方法,也就是一串数字。

 

独热编码(词袋模型)

 

一个常见的文本数据表示方式是将每个字符单独编码为一个数字(如 ASCII )。如果我们将这种简单的表示输入分类器的话,那模型将仅根据我们有的数据从头开始学习词的结构,这对于大多数数据集来说是不适用的,我们需要更高级的表示方法。

 

例如,我们可以构建一张由数据集中的所有不同的词构建的词汇表,并为每个词创建唯一索引。这样,每个句子就能表达成一个数列,数列的长度为词汇表的长度,在每个索引的位置标记出该单词在句子中出现的次数。这种表示方式称为词袋模型,因为这种方法完全忽略了句子中词语的顺序,下面是一个简单的独热编码的列子:

 

 

词嵌入可视化

 

在”社交媒体灾难“数据集中,包含将近 2 万个单词。也就是说,每一个句子将表示为一个长度为 2 万的向量,而这个向量里将包含大量的 0 ,因为每个句子仅涵盖了整个词汇表里很小的一个子集。

 

为了观察我们的词句嵌入是否捕捉了有用的信息(推文是否与灾难有关),可以将词嵌入和分类结果可视化,看分类效果如何。由于词汇表非常大,也没办法对2万维的数据可视化,我们采用 PAC 降维将数据表示成两维,如下图:

 

 

从图上可以看到分类结果不是很理想,一方面可能是因为我们的词嵌入本身的特点,另一方面是我们简单粗暴的降维所致。为了看词袋模型是否能起作用,我们可以用它来训练分类器。

 

第四步:分类

 

通常第一次尝试解决问题时,最好是先从简单的方法入手。而每每提到分类器时,人们最喜欢用的就是逻辑回归,因为它不但训练起来很简单,而且模型结果可解释性强。

 

我们将数据集分成训练集和验证集,训练集用来拟合模型,验证集用来验证模型表现。经过逻辑回归分类器的训练,我们的准确度达到 75.4%,结果还可以。但到这里,我们的工作还没有结束,还需要理解我们的模型。

 

第五步:检验

 

混淆矩阵

 

理解模型的第一步就是理解模型误差,看哪些误差是不应该出现的。在本文的案例中,

 

误报的情况是将无关推文归类成灾难

 

而漏报的情况是将灾难推文归成无关

 

如果我们的首要任务是发掘潜在灾难事件,那我们就要降低漏报率。但如果我们有资源限制,那就要优先考虑降低误报率。混淆矩阵式可以很好的将我们的模型预测值和真实标签值进行对比。通常理想情况下,矩阵是一条从左上到右下的一条对角线,也就是说预测完全符合事实。

 

 

从混淆矩阵中可以看到,我们分类器的漏报率高于误报率。换句话说,就是我们模型最多的错误出在将灾难推文归类到无关。但考虑到误报将带来很高的执法成本,所以这个分类器的误差也在接受范围内。

 

模型解释

 

为了验证并解释我们的模型,我们可以看一下模型是基于哪些词进行的分类的。如果我们的数据存在偏差,那模型将只适用于样本数据,而很难推广到真实数据中。下面列出了两个类型中最重要的数据。基于词袋模型和逻辑回归获取词的重要度是很简单的,只要对模型系数进行排序就好。

 

 

我们的分类器确实选取了一些特征模式(广岛,大屠杀),但是很显然也过度拟合了一些没有意义的词(heyoo,x1392)。目前我们的词袋模型处理的是大量不同的词汇,并对所有词一视同仁。但是有些词出现的频率过高会对我们的预测造成干扰。接下来,我们将尝试用另一种包含词频信息的句子表示,看能否从数据中选取出包含信息量更大的词。

 

第六步:考虑词汇结构

 

TF-IDF

 

为了使我们的模型可以专注于更有意义的词语,可以用 TF-IDF 得分来替换词袋模型。TF-IDF 的思想是用权重来代表这个词的重要度,而不是词频,如果一个词在数据集中出现频率过高将降低它的权重,或者说视为无效信息。下图是用对 TF-IDF 算法结果降维后的图:

 

 

可以看到两种颜色已经有明显的区分,这也可以帮助分类器更好的对两类不同推文进行分类。通过基于 TF-IDF 词嵌入进行逻辑回归模型的训练,我们得到 76.2% 的准确度。

 

这一个细微的改善,有没有帮助我们模型选择更重要的词汇呢?如果结果更好而且模型更稳定的话,我们就可以考虑升级模型了。

 

 

第七步:加入语义信息

 

Word2Vec

 

前面的模型中,我们基于词语出现的重要度作为词嵌入,但会有一个问题,就是我们部署这个模型之后,如果遇到训练集中没有出现过的词使,模型将很难准确对推文进行分类,即使训练中有类似的词也没办法识别。

 

解决这个问题的关键在于,我们要捕捉单词的语义,也就是说,我们需要让模型知道:”好的“与”可以“两个词要比”橘子“与”大洋洲“两个词更相相似。目前最成熟的这种可以实现语义捕捉的词嵌入方法叫 Word2Vec。

 

使用已训练好的词向量

 

Word2Vec 可在用连续性词嵌入的方式表示词语,它通过学习大量文本,并记住那些词会出现在相同的语境下。只要训练足够多的数据,Word2Vec 可以为每个词汇表里的单词生成一个 300 维的向量,并且通过这种方式表的的单词会在空间上与自己意思相近的词距离很近。

 

句式表达

 

前面已经只是将词转换成了向量,将句子嵌入分类器最快速的方法就是将句子中每个词的Word2Vec结果取均值。这里与之前词袋模型采用的方法相似,但这次我们只是忽略了句子的语法结构,但保留了词义信息。

 

 

下面是基于 Word2Vec 的词嵌入可视化:

 

 

现在这两类颜色看起来分离更加明显,Word2Vec 词嵌入能够帮分类器更好的进行分类。我们再一次基于新的词嵌入训练逻辑回归模型后,准确率达到 77.7%,这是目前最好的结果了,现在我们可以开始检查模型了!

 

复杂性/可解释性的权衡

 

由于我们的词嵌入不像之前的模型那样,每个维度可以代表一个单词,所以很难看出哪些单词与我们的分类最相关。但是我们仍然可以观察逻辑回归的系数,但要注意,这时候不同系数代表的 300 维的词嵌入的信息,而不是单独的单词了。

 

可能有人会觉得,Word2Vec 丢弃了解释性只换来了一点点精确度的提升,似乎是一件不划算的事情。但其实对于更复杂的模型,我们可以通过 LIME 这样的黑箱解释来了解我们的分类器是如何工作的。

 

LIME

 

在 Github 上可以获取 LIME 的开源包。黑箱解释器可以提供任何分类器的特定案例的解释。它主要的方法是通过观察扰动项输入(本案例中是删掉句子中的单词)对预测结果的影响。

 

Github 资源包链接:https://github.com/marcotcr/lime

 

我们来看看本文的数据集中的几个句子解释

 

 

 

当然,我们数据集好几千的句例,我们没那幺多时间一个个去探究。我们要做的是在一个有代表性的样本中运行 LIME,看看哪些词对于分类的贡献最大。通过这种办法,我们可以得到单词的重要度得分,来验证模型预测。

 

 

可以看到基于 Word2Vec 词嵌入,模型提取出来的单词具有很高相关度,可以用来解释分类器。这些词几乎是前面所有模型中最相关的词汇,现在我们可以放心的应用模型了。

 

第八步:采用端到端的方法使用语法

 

前面介绍了高效的句子嵌入的方法,但前面也提到了,之前的做法省略了单词的顺序,也就是说放弃了句子的语法信息。如果之前的做法达不到满意的结果,那你可以考虑使用更复杂的模型,不需要建立中间表示,而是将整个句子作为输入来进行标签预测。通常的做法是用 Word2Vec, 或者更新的 GloVe 或 CoVe 来实现将句子所为一系列单词向量序列。下面是一个例子:

 

 

用卷积神经网络进行句子分类训练非常快,而且效果很好,非常适合作为入门级的深度学习框架。虽然卷积神经网络(CNN)以其在图像处理上的性能着称,但它在处理文本相关任务时性能也很棒,要比大多数复杂的 NLP 方法(像 LSTM 和 Encoder/Decoder 架构)快得多。与前面的模型不同,现在这个模型保留了词序信息,它现在已经可以区分”小明吃苹果“和”苹果吃小明“了!

 

虽然这个模型看起来高大上,但它训练起来并没有比前面的模型更麻烦,而且得到的模型效果会比之前的好很多,准确率已经达到 79.5% ! 和前面的套路一样,我们需要验证这个模型是不是目前最好的选择,相信到这里大家已经可以自己尝试来验证一下了,是时候展现你真正的技术啦!

 

最后

 

快速回顾一下,我们是怎样一步步完成分类任务的吧!

 

先从一个最快速简单的模型入手

 

解释并预测模型

 

了解模型误差出在哪里

 

判断接下来是处理数据还是换更复杂的模型

 

本文将这些方法应用在一个实例中,结合不同模型来处理类似与推特、微博这种短文本,但这些思想都可以推广到处理各种其他问题。

 

参考-https://blog.insightdatascience.com/how-to-solve-90-of-nlp-problems-a-step-by-step-guide-fda605278e4e(文- Emmanuel Ameisen)

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注