数具手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)

Posted 有数La

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数具手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)相关的知识,希望对你有一定的参考价值。

【数具】手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)

豆瓣水军检测、《权游》续写、越来越神的谷歌翻译......最近自然语言处理(NLP)的各路应用可是被玩得风生水起。这些NLP应用看起来炫酷到没道理,但其实背后的原理并不难理解。今天,小编就来扒一扒最常用的自然语言处理技巧和模型,手把手教你做一个简单神奇的小应用。


编译 | 小饭盆、周佳玉、笪洁琼、钱天培

版式 | 数小妹


豆瓣水军检测、《权游》续写、越来越神的谷歌翻译......


最近自然语言处理(NLP)的各路应用可是被玩得风生水起。


这些NLP应用看起来炫酷到没道理,但其实背后的原理并不难理解。


今天,文摘菌就来扒一扒最常用的自然语言处理技巧和模型,手把手教你做一个简单神奇的小应用。


不吹不黑,90%的NLP问题都能用类似方法解决。

 

今天这个教程从数据处理的三大阶段教你自然语言处理:

  • 收集,准备、检查数据

  • 建立简单的模型(包括深度学习模型)

  • 解释、理解你的模型


整篇教程的Python代码都在这儿啦:

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

 

赶紧开始吧!

第1步:收集数据


自然语言数据的来源太多啦!淘宝评论、微博、百度百科等等。


不过今天呢,我们要处理的数据集来自推特“社交媒体上的灾难”数据集(Disasters on Social Media dataset)。


我们将使用由CrowdFlower慷慨提供的一个名为“社交媒体灾难”的数据集。该数据集由一万多条与灾难有关的推特组成。


其中一部分推特确实描述了灾难事件,而剩下的则是影评、笑话等等奇怪的东西=。=

 

我们的任务将是检测哪些推文是关于一个灾难性的事件,而不是一个不相关的话题,如电影。为啥要这么做呢?有关部门就可以用这个小应用及时得到灾难事件信息了嘛!


接下来,我们将把有关灾难的推特称为“disaster”,并将其他推文称为“irrelevant”。


Labels标签


注意哦,我们用的是有标签的数据。正如NLP大神Socher所说,与其花一个月用无监督学习处理一堆没有标记过的数据,还不如花个一周时间标记一点数据,整一个分类器。


【数具】手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)


第2步:清洗数据


我们遵循的第一原则是:“再好的模型也拯救不了shi一样的数据”。所以,先来清洗一下数据吧!


我们做以下处理:

1. 删除所有不相关的字符,如任何非字母数字字符

2. 通过文本分隔分成单独的单词来标记你的文章

3. 删除不相关的字词,例如“@”推特或网址

4. 将所有字符转换为小写字母,以便将诸如“hello”,“Hello”和“HELLO”等单词看做相同单词

5. 考虑整合拼写错误或多种拼写的单词,用一个单词代表(例如“cool”/“kewl”/“cooool”)相结合

6. 考虑词形还原(把“am”,“are”,“is”等词语缩小为“be”这样的常见形式)


按照这些步骤并检查其他错误之后,我们可以开始使用干净的标记数据来训练模型!


第3步:找到一个好的数据表示方式


数据清理完了,我们还得把这些文字转换成数值——这样机器才看得懂嘛!


例如,在图像处理中,我们就需要把图片转换成一个表示像素点RGB强度数字矩阵。


【数具】手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)

一个笑脸代表着一个数字矩阵


自然语言处理中的表示稍微复杂一点。我们会尝试多种表示方法。


独热编码(词袋)


表示计算机文本的一种自然方法是将每个字符单独编码为一个数字(例如ASCII)。


例如,我们可以建立数据集中所有唯一字的词汇表,并将唯一索引与词汇表中的每个单词相关联。然后,每个句子都被表示为一个与我们词汇表中唯一字数量一样长的列表。在这个列表中的每个索引处,我们标记给定词语出现在我们句子中的次数。这就是所谓的词袋模型,因为它是一个完全忽略我们句子中单词顺序的表现形式。如下所示。

【数具】手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)

代表句子作为一个词袋。左边为句子,右边是其表示形式。向量中的每个索引代表一个特定的词


可视化嵌入


在“社交媒体的灾难”这个例子中,我们有大约2万字的词汇,这意味着每个句子都会被表示为一个长度为2万的向量。该向量将包含大部分0,因为每个句子只包含我们词汇的一个很小的子集。


为了了解我们的表示是否捕获与我们的问题相关的信息(即推文是否与灾难有关),让我们将它们可视化并查看这些类是否看起来很好地分离是一个好主意。由于词汇通常非常大,并且不可能在20,000维度上显示数据,所以像PCA这样的技术将有助于将数据投影到两个维度。如图所示:


【数具】手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)

可视化

 

这两类看起来不太好分开,这可能是我们嵌入的一个特征,或者仅仅是由于我们的维度降低。为了看看词袋特征是否有用,我们可以根据它们来训练一个分类器。


第4步:分类


首先遇到问题时,一般的最佳做法是从最简单的工具开始解决问题。每当涉及到对数据进行分类时,基于通用性和可解释性的一个普遍喜好是Logistic回归。训练非常简单,结果可以解释,因为你可以轻松地从模型中提取最重要的系数。


我们将数据分成一个用于拟合模型的训练集和一个用于评估模型泛化能力的测试集,以此来推广到不可见的数据。训练结束后,我们得到了75.4%的准确度。还不错哦!如果我们简单地猜测最频繁的类(“irrelevant”),准确率只能达到57%。但是,即使75%的精度足够满足我们的需求,我们也不应该在不尝试了解它的情况下,发布一个模型。


第5步:检查


混淆矩阵


第一步是了解我们模型的错误类型,以及哪种类型的错误是最不可取的。在我们的例子中,假阳性划分为irrelevant,事实上是diasaster,而假阴性实际是disaster,而归类为irrelevant。如果要优先处理每一个潜在的事件,我们会想要降低我们的假阴性。然而,如果我们受到资源的限制,我们可能会优先考虑较低的假阳性来减少误报。 将这些信息可视化的一个好方法是使用混淆矩阵,它将我们的模型的预测与真实标签进行比较。理想情况下,矩阵将是从左上角到右下角的对角线(预测和实际完美匹配)。


【数具】手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)

混淆矩阵(绿色是高,蓝色是低)


相对于假阳性来说,我们的分类器按比例产生更多的假阴性。换句话说,我们模型最常见的错误是将disaster归类为irrelevant。如果假阳性导致高的执法成本,这使我们的分类器可以有一个很好的bias(偏差)。

 

模型解析

    

为了对我们的模型进行验证并分析它预测的准确性,我们需要看它通过使用哪些词来做决定,这是十分重要的。如果我们的数据存在偏差,那么分类器将只能在样本数据中做出准确预测,而这个模型在现实世界中则不能很好地推广。在此,我们分别为disaster和irrelevant绘制了“最关键的词”的表。由于我们可以对用于预测的模型的系数进行提取和排序,使用词袋和逻辑回归来计算单词的重要性其实很简单。

【数具】手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)

词袋:关键词

  

我们的分类器正确地采取了一些模式(如hiroshima广岛、massacre大屠杀),但这其中也显然有一些看似无意义的过度拟合(heyoo蓝调摇滚,x1392话题简称)。现在,我们的词包模型正在处理包含各种不同单词的巨大词汇表,并且平等地对待所有单词。然而,这其中的一些词语出现的非常频繁,只会对我们的预测产生影响。接下来,我们将尝试一种新方法来表示能够统计单词频率的句子,看看能否从我们的数据中获取更多的信号。


第6步:统计词汇结构


为了使我们的模型更多的专注于有意义的单词,我们可以在词袋模型顶部使用TF-IDF评分(术语频率、逆文档频率)。TF-IDF通过在数据集中的出现频率来确定词权重,减少出现过于频繁的词的权重而增加到噪音干扰上。下图是对我们新嵌入数据的PCA预测。


【数具】手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)

TF-IDF嵌入可视化

  

从上图可以看出,在这两种颜色之间有一个相对清晰的分界。这将会使我们的分类器更容易将其分为两组。让我们来看看这是否会带来更好的表现吧!接下来在我们新嵌入的数据上训练另一个Logistic回归参数,我们得到了76.2%的准确性。

 

这是一个非常细微的改进。我们的模型是否已经开始采用更关键的词?如果我们在防止我们模型“作弊”的同时取得了更好的效果,那么我们就可以真正认为这个模型实现了一次突破了。

【数具】手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)

TF-IDF:关键词

 

模型所采取的词看起来更相关!尽管我们测试集的指标只是略有增加,但是我们对模型使用的术语将会更有信心,所以将其应用在与客户交互的系统中会感到更加舒适。


第7步:巧妙利用语义


将词转化为向量

  

我们的最新模型设法采取具有高信号的词。然而,如果我们配置这个模型,很可能会遇到我们之前在训练集中没有看到的词。然而即使在训练中看到非常相似的单词,以前的模型也不能准确辨别这些干扰。

  

为了解决这个问题,我们需要捕捉词的语义,这意味着我们需要理解“好”和“积极”等词比“杏”和“大陆”更相近。我们将用名为Word2Vec这个工具帮助我们捕捉语义。


使用预训练的词

 

Word2Vec是一种实现连续词嵌入的技术。它通过阅读大量的文字来学习,并记忆哪些词倾向于出现在相似的语境中。在训练足够多的数据后,它会为词汇表中的每个词生成一个300维的向量,意思相近的词彼此则会更接近。

   

本文的作者开源了一个模型,它在一个非常庞大的语料库上预先训练好,我们可以利用这个语料库将一些语意知识纳入到我们的模型中。预训练的向量可以在与这篇文章相关的知识库中找到。


句级表示

   

为我们的分类器获得句子嵌入的一个快速方法是:平均句中所有词的Word2Vec得分。这跟以前一样也是一个词袋的方法,但是这次我们只丢掉句子的语法,而保留一些语意信息。

【数具】手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)

Word2Vec句嵌入

    

下图是使用先前技术获得的新嵌入可视化:


【数具】手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)

Word2Vec嵌入可视化

   

两组颜色的分界看起来更加明显,我们的新嵌入技术一定能帮助我们的分类器找到两个类之间的分离。第三次(使用Logistic回归)训练同一个模型后,我们得到了77.7%的精准度,这是我们到目前为止得到的最好的结果!接下来该检查我们的模型了。


复杂性与可解释性的权衡

   

由于新嵌入技术没有像我们以前的模型那样以每个单词一维向量来表示,所以很难看出哪些单词与我们的分类最为相关。虽然我们仍能使用Logistic回归的系数,但它们只与我们嵌入的300维度相关,而与词汇索引没有关联。

  

对于如此低的准确度,失去所有可解释性似乎是一个艰难的权衡。然而,对于更复杂的模型,我们可以利用LIME等黑盒解释器来深入了解分类器的工作原理。

 

Github通过开源软件包提供LIME。黑盒解释器允许用户通过干扰输入(在我们例子中即去除句子中的单词)来解释任何分类器的决定,并查看预测的变化。

   

接下来让我们一起看看我们数据集中的几个句子的解释。

【数具】手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)

【数具】手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)

然而,我们并没有时间去探索数据集中的数千个案例。我们应该做的则是在测试案例的典型范例上继续运行LIME,看看哪些词的占有率仍能位居前列。通过这种方法,我们可以获得像以前模型那样的单词的重要性分数,并验证模型的预测。

 

【数具】手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)

Word2Vec:关键字

 

模型似乎能提取高度相关的词,这意味着它也许能做可理解的决定。而这些看起来像是以前所有模型中最相关的词,因此我们更愿意将其配置到实际操作中。


第8步:使用端到端的方法来巧妙利用语义

  

我们已经介绍了快速有效的方法来生成紧凑的句嵌入。然而,通过省略词序,我们放弃了句子的所有句法信息。如果这些方法不能提供充分的结论,则可使用更复杂的模型,将整个句子作为输入并预测标签,而不需要建立中间表示。一种常见的方法是将句子作为一个词向量序列,使用Word2Vec或更新的方法,如GloVe或CoVe。这就是我们将在下面做的。


【数具】手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)

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

 

用于句子分类的卷积神经网络训练非常迅速,并且作为入门级的深度学习体系能够很好地完成任务。虽然卷积神经网络(CNN)主要因其在图像数据上的性能而闻名,但它们早已在文本相关任务上提供了优异的结果,并且通常比大多数复杂的NLP方法(例如LSTM和编码器/解码器体系结构)能更快地训练。这个模型保留了词序,并且学习了关于哪些词序列可以预测我们目标类的有价值的信息。与之前的模式相反,它是可以区分“亚历克斯吃植物”和“植物吃亚历克斯”的不同。

  

训练这个模型不仅不需要比以前方法更多的工作(详见代码),而且给了我们一个比以前方法更好的模型,准确率达到了79.5%!与上述模型一样,下一步应该是继续使用我们描述的方法来进行探索和解释预测,以验证它确实是配置给用户的最佳模型。现在,你应该能自己上手处理这个问题了。


小结

   

  • 从一个简单快捷的模型开始

  • 解释其预测

  • 了解它正在犯的错误类型

  • 利用这些知识来确定下一步工作:模型对数据是否有效,还是应该使用更为复杂的模型


这些方法被应用于特定的案例,如理解和利用诸如推文之类的短文本模型,但实际上这些思想广泛地适用于各种问题哦!


就像开头小编说的,90%的自然语言处理问题都可以用这个套路解决,那还不是砍瓜切菜!

 

原文链接:

https://blog.insightdatascience.com/how-to-solve-90-of-nlp-problems-a-step-by-step-guide-fda605278e4e?gi=6fefa8b6c671


文章来源:本文转载自大数据文摘,已获转载授权!

 • end • 


更多精彩数据,尽在有数啦!快来和小伙伴一起“玩”转大数据!

有数啦网址:https://www.udata.la/


以上是关于数具手把手:自然语言处理太难?按这个套路走,就是砍瓜切菜!(附Python代码)的主要内容,如果未能解决你的问题,请参考以下文章

自然语言处理太难?按这个方式走,就是砍瓜切菜!

“手把手撕LeetCode题目,扒各种算法套路的裤子”

动态规划太难?刷题无数,不如掌握这些套路

NLP is hard! 自然语言处理太难了系列

Leetcode 675.为高尔夫比赛砍树

英雄联盟设置走A键