本文为雷锋字幕组编译的技术博客,原标题How to solve 90% of NLP problems: a step-by-step guide,作者Emmanuel Ameisen。
翻译 | 于泽平 整理 | 凡江 编辑 | 吴璇
如何将这五个W和H开头的词应用在文本数据中?
想要了解更多类似的内容,请在Twitter上关注Insight和Emmanuel。
文本数据无处不在
无论你是已成立的公司还是致力于推出新服务,你都可以使用文本数据验证、提升和扩展产品的性能与功能。学习并提取文本数据中的意义,这一科学是自然语言处理(NLP)中的一个活跃的研究课题。
NLP是一个非常庞大的领域,每天都会产生新的令人兴奋的结果。然而,Insight团队与数百家公司合作之后,发现一下几个关键的实用的应用,在实际中使用的频率比其它应用高得多。
识别不同的用户/客户群体(例如预测客户流失,生命周期,产品偏好)
准确地检测并提取不同类别的反馈(正面或负面的评论/意见,特定属性的评论,例如衣服尺寸/合身)
根据意图对文本进行分类(例如请求基本帮助,紧急的问题)
尽管网上有许多NLP的论文和教程,但我们发现很难找到,如何从头开始学习高效处理这些问题的指导与技巧。
本文如何提供帮助
我们每年领导数百个项目,从美国的顶尖团队获得建议后,我们写下这篇文章来解释如何构建机器学习的方案解决上述问题。我们将从最简单的方法开始,然后转向更细致的解决方案,比如特征工程,词向量和深度学习。
读完这篇文章,你将学会如何:
收集、准备并检查数据
建立简单的模型,并在必要时转化为深度学习
解释并理解你的模型,确保你获取到的是信息而不是噪声
我们写这篇文章是作为一个逐步的指南,它也可以作为高效的标准方法的一个高级概述。
这篇文章中包含一个交互式的notebook,用来演示和应用这些所有的技术。
随意运行代码,并一步一步跟上吧!
第一步:收集你的数据
数据源样例
每一个机器学习问题都始于数据,例如电子邮件,帖子或推文。文本信息的常见来源包括:
产品评论(来自于亚马逊,Yelp和各种应用商店)
用户生成的内容(Tweet和Facebook的帖子, StackOverflow 的问题 )
疑难解答(客户的请求,服务记录,聊天记录)
“社交媒体上的灾难”数据集
在这篇文章中,我们将使用CrowdFlower提供的数据集,叫作“社交媒体上的灾难”。
贡献者查看了超过10000条tweet内容,做了各种各样的搜索,如“着火”,“隔离”和“混乱”,然后标记这些tweet是否对应到一个灾难事件(而不是一个玩笑或是影评等无灾难性的语句)
我们的任务是检测哪些tweet是关于灾难事件的,而不是像电影这样的无关的话题。为什么要这样做呢?一个潜在的应用是只把关于紧急事件的tweet通知给执法人员,而忽略掉最近的电影Adam Sandler的评论。这个任务一个特殊挑战是这两类推文都包含同样的搜索关键词,因此我们需要使用更细致的差异来区分它们。
在本文此后的叙述中,我们将关于灾难的tweet称为“灾难”,把其它的tweet成为“无关”。
标签
我们对数据作了标记,因此我们知道哪些tweet属于哪种类别。正如Richard Socher在下面概述的一样: 与试图优化复杂的无监督方法相比,找到并标记足够数据从而把模型训练起来通常更快,更简单也更便宜。
第二步:清理数据
我们遵从的首要规则是:你的模型优劣取决于你的数据。
数据科学家的关键技能之一就是知道下一步应该专注于提升模型效果还是处理数据。一个好的经验法则是先查看数据然后清理它。一个干净的数据集将使模型学习到有意义的特征,而不是在无关的噪音上过拟合。
下面是一个清单,用来清理你的数据(更多细节见代码):
删除所有不相关的字符,如不是字母和数字的字符
将文本切分成独立的单词进行标记
移除不相关的词,例如twitter中的“@”或者是网址
将所有字母转为小写,以便于将“hello”,“Hello”和“HELLO”统一对待
考虑将拼写错误或是有多种拼写方法的单词用同一中表示方法表示(例如“cool”/"kewl"/“cooool”)
考虑词形还原(例如将类似"am","are","is"的词语统一缩写为“be”)
在按照这个清单逐步检查之后,我们就可以开始使用清洁之后的,已经标注好的数据开始训练模型了!
第三步:找到一个好的表示数据的方式
机器学习模型将数值作为输入。例如,用于图像处理的模型将每个颜色通道中每个像素的强度矩阵作为输入。
一个数字矩阵,它表现出一副笑脸的样子
我们的数据集是句子的列表,为了让我们的算法从数据中提取特征,我们首先需要找到一种表达方法,使我们的算法可以理解,即用数字列表来表示。
one-hot编码(词袋)
为了让计算机理解,一种自然的文本表达方式是将每个字符编码成一个单独的数字(例如ASCII码)。如果我们把这种表达方式喂给分类器的话,它就需要从头开始,仅仅根据我们的数据学习出单词的结构,这对大多数数据集都是不可能的。我们需要使用更高级的方法。
例如,我们可以根据我们的数据集创建一个包含所有单词的词汇表,并使用唯一的索引与词汇表中的每个单词相连。每个句子都被表示成一个与词汇表中单词数量一样长的列表。在这个列表中的每个索引出,我们标记对应单词在句子中出现的次数。这种方法被称为词袋模型,因为这种表示方法完全忽视了句子中的词语顺序。如下所示。
使用词袋表示句子。句子在左边,右边是句子的表示向量。向量中的每个索引代表一个特定的词。
向量可视化
在“社交媒体的灾难”这个例子中,我们词汇表中有大约20000个词汇,这意味着每个句子都被表示成长度为20000的向量。这个向量包含的大部分都是0,因为每个句子只包含词汇表中很少的单词子集。
为了了解我们的表示向量是否捕获到与我们的问题相关的信息(即tweet与灾难是否相关),将它们可视化并是一种好方法,可以查看这些类是否看起来可以很好地分离。因为词汇表通常很大,将20000维的数据可视化是不可能的,PCA等技术可以帮助我们把数据降至2维。如下图所示。
词袋向量可视化
这两类看起来没有被很好地分开,可能是向量的特征就是如此,也可能只是因为降维。为了看看词袋特征有没有用,我们可以根据它们训练一个分类器。
第四步:分类
第一次遇到问题时,通常最好的做法是从最简单的工具开始解决问题。每当遇到分类问题时,一个大家普遍喜欢用的方法是逻辑回归,因为它功能多,可解释。训练非常简单,而且结果可以解释,因为你可以很容易地提取模型中最重要的系数。
我们将数据分成训练集和测试集。训练集用来训练我们的模型,测试集用来看看模型在看不见的数据上表现如何。训练后,我们得到了75.4%的准确率,不是太烂!猜测频率最高的类别(无关)只会达到57%的准确率。然而,即使75%的准确率已经足够满足我们的需求,我们也不应该不试图理解这个模型就使用它。
第五步:检查
混淆矩阵
第一步是了解模型的错误种类,以及哪些错误是我们无法接受的。在我们的例子中,误报将无关的tweet分类为灾难,而错报将灾难的tweet分类为无关。如果我们想要优先应对每一个潜在的灾难事件,我们可能想要减少错报率。如果受资源的限制,我们可能优先想要低的误报率以减少错误警报。一个将这些信息可视化的好方法是使用混淆矩阵,将我们的模型预测的标签与真实标签比较。理想情况下,这个矩阵是从左上角到右下角的对角线(当我们的预测完美预测真实标签时)。
混淆矩阵(绿色比例高,蓝色比例低)
我们的分类器产生的错报比误报(比例)多。换句话说,我们的模型更普遍的错误是将灾难标记为无关。如果误报的执法成本很高,这对于我们分类器来说可能是一个好的偏差。
解释我们的模型
为了验证我们的模型并解释它的预测,很重要的是看看模型使用哪些单词做预测。如果我们的数据有偏差,我们的分类器将在训练集中做出准确预测,但可能在现实世界中无法很好地推广。这里我们将灾难与无关两类中最重要的单词做成图表。当使用词袋模型和逻辑回归时,将词语重要性绘成图表很简单,因为我们只需要将模型用于预测的系数提取出来并将其排序。
词袋的重要性
我们的分类器正确提取了一些词语(如广岛,屠杀),但很明显,在一些无意义的词语中过拟合(如heyoo,x1392)。现在,我们的词袋模型处理不同词语的词汇表,并将所有单词同等对待。然而,其中某些词语出现的频率很高,对于我们的预测只是起到噪声的作用。接下来,我们将尝试一种考虑词语频率表示句子的方式,看看能否从我们的数据中提取更多的意义。
第六步:考虑词语结构
TF-IDF
为了让我们的模型专注于更有意义的单词,我们可以在词袋模型的基础上使用TF-IDF分数(词频-逆文档频率)。TF-IDF通过词语在数据集中出现的稀少程度决定词语权重,减少出现频率太多的词语权重,因为它们可能只会带来噪声。这里是使用PCA获得的新向量。
TF-IDF向量可视化
我们从上图中可以看到,两种颜色间有一个更清晰的区别。这可以让我们的分类器更容易地将两类分开。让我们看看它是否带来了更好的表现。使用另一个逻辑回归模型训练我们的新向量,我们得到了76.2%的准确率。
只改进了一点点。我们的模型是否开始获得更重要的单词?如果我们在防止模型“作弊”的同时得到了一个更好的结果,我们可以考虑升级这个模型。
TF-IDF:词语重要性
它获得的词语看起来相关性更强!即使我们在测试集的评价指标只是略微增加了一些,但我们对我们模型使用的词语有了更多的自信,因此我们将其部署在与客户的交互系统中会感觉更加舒服。
第七步:利用语义
Word2Vec
我们刚刚的模型尝试获取词语的意义。然而,如果我们使用这个模型,我们很可能会遇到在训练集中没有看见过的词语。即使在训练过程中遇到很多相似的词汇,之前的模型也无法将这些tweet准确分类。
为了解决这个问题,我们需要捕捉单词的语义,意思是我们需要理解像“好”和“积极”的距离比“杏”和“大陆”的距离更近。我们使用的帮助我们捕捉语义的工具叫作Word2Vec。
使用预训练的词语
Word2Vec是为词语寻找连续向量的工具。它通过阅读大量的文本来学习,并记忆哪些词语倾向于在相似的上下文中出现。在足够数据中训练后,它为词汇表中的每一个单词生成一个300维的向量,其中语义相似的词语向量间的距离更近。
这篇论文的作者开源了一个使用巨大语料集预训练的模型,我们可以利用它将语义知识纳入我们的模型中。预训练词向量可以在这篇博客的相关存储库中找到。
句子层级向量表示
为我们的分类器快速获得句向量的方法是对句子中的所有词使用平均词向量分数。这与以一样,是一个词袋的方法,但这一次我们只丢失了句子的语法信息,而保存了一些语义信息。
Word2Vec句向量
这是我们对用之前的技术获得的新向量的可视化:
Word2Vec 向量可视化
这两种颜色看起来更容易分离,我们的新向量应该可以帮助我们的分类器将两类分开。在第三次用同样的模型(逻辑回归)训练后,我们得到了一个77.7%的准确率,这是我们目前最好的结果!是时候检查我们的模型了。
困惑度/可解释的权衡
我们的向量不像之前的模型那样将每一个单词表示成一个一维的向量,因此更难看出哪些词语对分类的相关性最强。虽然我们仍然可以使用逻辑回归的系数,它们对应的是我们向量的300个维度,而不是词语的索引。
对于如此低的准确率提升,失去所有的可解释性看起来是一个不太好的权衡。然而,对于更复杂的模型,我们可以利用LIME等黑盒解释器来解释分类器的工作原理。
LIME
LIME可以通过Github上面开源的包得到。一个黑盒解释器允许用户扰动输入(我们这种情况是移除句子中的词语)并查看在预测中如何改变,通过这种方法在一个特例中解释分类器的决定。
我们来看看我们的数据集中几个句子的解释。
正确的灾难词汇被分类为“相关”。
这里,词语对分类的贡献看起来不太明显。
但是我们没有时间查看数据集中的数千个例子。我们能做的是在测试集中的代表样例中运行LIME,并查看哪些单词持续做很多的贡献。使用这种方法我们可以得到像之前模型一样的单词重要性分数,并验证模型的预测结果。
Word2Vec:词语重要性
看起来模型可以获取高度相关的词汇,暗示它做出可以理解的决定。这些看起来是在之前的所有模型中最相关的词汇,我们将它应用在产品中时感觉更舒服。
第八步:使用端到端方法利用语法
我们已经介绍了快速高效的获得句向量的方法。然而,通过省略单词的顺序,我们放弃了句子所有的语法信息。如果这些方法无法提供足够好的结果,你可以利用更多复杂的模型,将整个句子作为输入并预测模型,而不需要建立中间的表示向量。一个普遍的方法是将句子作为词向量的序列,可以通过Word2Vec或者最近的GloVe与CoVe等方法获得词向量。这是我们接下来要做的。
一个搞笑的端到端结构(源)
用于句子分类的卷积神经网络训练十分迅速,并且作为入门级深度学习结构表现出色。虽然卷积神经网络(CNN)主要因其图像处理中的表现而闻名,它们在文本相关人物中也取得了很好的结果,而且它们通常比大多数复杂的NLP方法(如LSTM和编码器/解码器结构)速度快得多。这个模型保留了单词的顺序,并学习到哪些词语序列可以预测目标类别这些有价值的信息。与之前的模型相反,它可以分别“Alex吃植物”和“植物吃Alex”的区别。
训练这个模型不需要比以前方法更多的工作(详见代码),并让我们得到了比以前更好的模型,达到了79.5%的准确率!与上面的模型一样,下一步我们应该使用我们讲过的方法探索并解释预测,以此验证它的确是部署给用户的最佳模型。现在,你应该可以自己处理这个问题。
最后的笔记
以下是对我们成功使用的方法的快速回顾
从一个简单快速的模型开始
解释它的预测
了解它正在犯的是哪种错误
使用这些知识决定下一步应该处理数据还是使用一个更复杂的模型
我们将这些方法应用在一个特例中,使用模型理解并利用诸如tweet的短文本。但这些思想在许多问题中都适用。我希望这对你有帮助,我们很乐意听到你的意见和问题!你可以通过在下面评论或是在Twitter上@EmmanuelAmeisen 联系我们!
博客原址
更多文章,关注雷锋网
添加雷锋字幕组微信号(leiphonefansub)为好友
备注「我要加入」,To be a AI Volunteer !
雷锋网雷锋网