当前位置: 灰狼 >> 灰狼的形状 >> 干货NLP使用手册快来收藏
一个简单的问题:怎么把文字转为特征?
假设你的任务是为你的公司产品评论建立一个情绪分析工具。作为一个经验丰富的数据科学家,你对未来的销售预测建立了许多见解,甚至能够根据客户的购买行为对其进行分类。
但是现在,你很感兴趣:你有这么多的文本条目,并且必须将它们转化为机器学习模型的特性。怎么能做到?这是科学家首次遇到文本时的一个常见问题。
尽管寻找经验丰富的NLP数据科学家可能很简单,但对于该领域的新手来说,将文本转换为特征并非易事。本文的目的是提供一个将文本转换为特性的指南,作为我在过去几个月里构建的NLP系列的延续。
之前,我已经讨论了NLP预处理管道中的几个步骤。现在,这是预处理管道的最后一步,当你精心策划的文本最终变成机器学习模型可用的特性时(如果这是你的目的-可以有没有机器学习的NLP,另一个时间的主题)。
与往常一样,我将介绍三种最常用的建模技术:词袋模型、基于TF-IDF算法的模型和Word2Vec模型。
特征
对于那些不习惯这个词的人,让我稍微跑一下题。特征是被选择或处理的数据的名称,这些数据准备用作算法(通常是机器学习算法)的输入。特征可以是房子的价格,像素的RGB值,或者在我们的例子中,一个单词的表示。
从谷歌开发人员机器学习速成课程拿到的图片,完美描述了什么是功能。
甚至还有一种叫做“特征工程”的很酷的技能,即数据科学家对数据进行研究,从数据中获取特征。这些特征在数据中甚至可能不显式,但可以通过修改现有数据或添加新数据使其更完整来获得,从而帮助实现更可靠的决策。
因此,最终,我们的目标是获取原始数据(文本)并将其转化为特征(计算机算法可以处理的东西)。
文本矢量化
用于将文本转换为特征的技术可以称为“文本矢量化”技术,因为它们都是为了一个目的:将文本转换为向量(或数组,如果你希望它更简单;或者张量,如果你希望它更复杂),然后可以用经典的方式输入机器学习模型。
文本矢量化旨在将文本转换为整数(或布尔值或浮点数)向量。图片由作者提供。
把我们的预期结果作为一个向量来思考,这是一个很好的起点,可以让我们形象化地将文本转化为特征。让我们再考虑一下这个问题。考虑以下短语:
我要把文本转为数据。
在简单的计算术语中,向量是具有n个位置的列表。思考如何将文本转换为向量的一种自然方法是创建所有单词的有序列表,例如:
图片由作者提供
但是,如果您有较短或较大的条目,会发生什么情况?还有,你的机器学习算法(基本上是一系列的矩阵和向量计算)如何比较两个词——人类发明的具有特殊意义的符号?
既然你很聪明,你已经在想:让我做一本字典或一些类似的结构(一般来说,一个词汇表),用单词索引代替单词!
一个假设的解决方案是为每个单词创建一个映射……图片由作者提供
然后用单词索引对向量进行编码
你走的路是对的,但是让我们考虑一下这里的一些问题:“我的”这个词比“想要”更重要吗?这就是机器学习算法的数据“告诉”的。机器学习算法不关心这个数字是否是一个索引,只关心它是一个需要计算的值(当然,您可以有一个分类特性,但我们将进一步了解它)。
别大喊大叫,词汇不是值!图片来自《海绵宝宝》,由作者编辑。
“归一化,归一化,归一化!!!”可以思考一下。但是,请记住:这些不是值!它们是indices。
如果你在数据科学和机器学习方面玩得够久的话,你可能会想到一个解决方案:使用“”。
独热编码是对分类特征进行编码的过程,其中该特征的每个可能值都映射到一个新的“列”,如果存在,则将该列设置为1,否则设置为0。
让我们使用前面提到的词汇“map”和建议的短语(在本例中,词汇表与短语中的单词相同)。我们得到这个:
用独热编码分析“我想把我的文本变为数据”。图片由作者提供。
现在,如果我们想编码:“我想要我的数据”,我们会得到:
用独热编码分析“我想要数据”。图片由作者提供。
太好了,我们找到了一种将数据编码成机器学习方式的方法!但是有很多问题需要解决:让我们考虑一下第一个单字频率——这就是词袋模型的用武之地!
词袋模型
独热编码只将值视为“present”和“notpresent”。这不适用于文本。在许多文本应用中,词频起着重要作用。考虑以下两段:
狗是犬科的驯养食肉动物。它是类似狼的犬科动物的一部分,是分布最广的陆生食肉动物。狗和灰狼是姐妹类群,因为现代狼与最初被驯养的狼没有密切的关系,这意味着狗的直系祖先已经灭绝。这只狗是第一个被驯养的物种,几千年来一直有选择性地培育出各种各样的行为、感觉能力和身体特征。
今天我和我的狗出去玩,在公园里发现了美元。想到这些钱可以成为一个可怜的老太太一个星期的午餐钱,我很难过。
第一段是维基百科关于狗的文章的第一段,第二段是我写的一篇伪博客文章,目的是为了证明这个问题。问题:如果用户正在搜索一个带有“dog”这个词的假定引擎,你会推荐哪个网页?
一个独热编码会给两个条目中的“dog”提供相同的值,因此这不是一个好的方法。
再来看词袋模型!
这个模型建议使用词频向量代替布尔值向量。在上面的示例中,单词“dog”的列在第一个文本中将接收到值“4”,在第二个文本中只接收到“1”。现在,可以规范化这些值,但不是必需的(只为了更快地处理)。
这个模型被称为“袋”,因为它不符合“秩序”这个词(就像我们妈妈90年代的包总是凌乱不堪一样)。
凌乱的包包。图源自:CocoonInnovations,Pinterest
但是在讨论单词袋模型的缺点之前,让我们看看如何使用Python和Numpy实现它。
这很简单,但让我们一步一步来看看。我决定让它成为一个类,这样我就可以在一个模型中实例化多个BoW。这是类构造函数:
基本上,我们有一组单词和两个dict来存储单词索引。
下一步,我们准备好我们的词袋,通过安装它(一次添加所有文档,这样它就可以“学习”我们可以使用哪些单词)。
最后,我们可以转换新的输入,返回整个词汇表大小的数组,并计算单词出现的次数。为此,我使用了numpy,这是一个专门研究向量/矩阵代数的数学和代数库。它是python当前用于此类任务的默认库(并用作大多数机器学习库的输入格式)。
以下是使用和输出示例
既然我们已经了解了它是如何实现的,我们可以谈谈模型中的问题:
第一:它完全忽略了语序。您可以通过查看下图了解这一点:
图由作者提供
第二:它倾向于非常高的维度。根据牛津英语语料库,如果你的语料库至少只占90%最常见的英语单词一次,那么就会产生至少个维度的向量(其中大部分都是零,但却是很多维度)!
但是词袋很简单,可以为简单的问题带来快速的结果。如果您不确定在构建NLP解决方案时从何处着手,请尝试基本方法:使用词袋模型。它是一个很好的基线评估器。
要指出的是,有一种变体在大数据情况下非常有用,特别是在需要比较字符库中的文本(不考虑语义)的情况下。此方法使用文本木瓦(木瓦)。在这种情况下,不要将句子分解成单词,而是在每个k个字符处或每个停止单词处打断。阅读更多信息:
TF-IDFModel
这实际上并不是一个模型,而是在计算一个单词相对于文档的“相关性”方面的一个改进。为了简单起见,我称之为模型。
在TF-IDF模型中,我们不存储单词的频率,而是将TF-IDF算法的结果存储在输入数据上。TF表示术语频率,IDF表示反向文档频率。
简而言之,TF-IDF计算特定文档中单词的权重,同时考虑单词的总体分布情况。结果的呈现方式与单词包相同:稀疏向量(0表示未出现的单词,而有些则为float)。
当使用TF-IDF模型时,例如在情绪分析任务中,与单词袋相比,TF-IDF模型可以返回更好的结果。
为了更好地理解该算法,我们将该算法分成两部分:计算全局逆文档频率,然后计算单个TF-IDF分数。
反向文件频率
第一部分是计算每个单词的全局IDF值。这个值表示每个单词在所有文档中的权重(在整个语料库中)。这意味着,非常普通的单词总体上的权重较小,而稀有单词的权重更大(这甚至消除了停止删除单词的必要性,因为它们非常常见,所以权重会更小)。
有很多不同的方法来计算TF和IDF(例如,看看Wikipedia的算法页面)。我选择使用logscaleidf,它是用以下公式计算的:
D=文档总数
F=出现该术语的文档数
为了方便开始,我们定义一个辅助方法:
将一个句子转换成单词和频率的dict的简单方法(可以使用Pythoncollections“Counter”以获得最佳性能,但为了简单起见,我将使用旧的dict方法):
然后我们初始化IDF类,类似于BoW类:
为了进行拟合,我们计算了全局项频率,然后根据上面的公式计算每个词的IDF。
很好,我们的文件有全局IDF。现在,计算每个句子的TF-IDF,方法是找到每个句子中每个术语的词频得分,然后乘以全局术语IDF。
计算术语频率
简而言之,我们用一个句子得到TF-IDF分数
1.计算句子中术语的词频。
2.将每个术语的词频乘以逆文档频率。
下面是代码(请注意,我添加了一些条件和方法来解释批处理转换):
我们的TF-IDF特技化器就这样完成了!
现在,对于每个句子,我们得到一个数组,它是整个词汇表的大小,以及每个单词与该句子的相关性(如果缺失,则为0)。
下面是一个输出示例:
或者更“易读”:
您可以在这里找到用于生成上述“解释”的代码。
这是到目前为止实现的提交,请注意,代码中会有一些不同,因为我还将使用一些内置在工具集中的结构。
关于词袋和TF-IDF的一些讨论如我们所见,词袋和TF-IDF方法为一个句子生成一个整个词汇表大小的向量。这忽略了语序或位置,使得这些技术不利于对连续性敏感的应用程序(大多数NLP应用程序都是)。
一种可能的解决方法是对每个单词使用BoW/TFIDF数组,将它们堆叠并作为特征传递,如下图所示(示例为人工神经网络的输入层):
在上面的图片中,你有一个00*4的稀疏矩阵来表示一个由4个单词组成的句子(即使对每一个布尔值使用一个位,每个句子每个单词也会有大约1kb的空间!想象一下一个庞大的语料库。用于训练简单情感分析模型的计算时间和存储空间会使其过于昂贵或不可行(事实上,几年前,由于缺乏足够的内存和处理能力,当问题是机器学习时,文本几乎是一个未触及的话题)。
然而,这种方法允许我们保持词序。如果我们能减少这个向量的维数呢?
下面,要进入单词嵌入了!
单词嵌入
我不会深入解释单词嵌入,因为有几种计算方法,大多数都涉及深层神经网络,它们本身需要一段时间来解释(这不是本文的重点)。
但我会给你最基本和最重要的信息。
让我们这样说:
单词嵌入是从语境训练中学习到的单词的向量表示。它不是每个单词的分数,相反,它更像是单词的“坐标”。
因此,当训练一个模型而不是一个词汇表大小的热编码时,需要输入一个表示输入的单词嵌入数组。这个数组有一个预定义的d维深度,它通常远小于词汇表的大小。
生成单词嵌入的最著名的技术之一是Word2Vec,它起源于该方法。Word2Vec本身可以使用两种不同的技术进行计算,但是细节在这里并不那么重要。
相反,您最好知道训练/使用嵌入的方法有很多变化。以下是用于创建嵌入的技术摘要:
Word2vec(Google)-2techniques:ContinuousBagofWords(CBoW)andSkip-Gram;
GlobalVectorsorGloVe(Stanford);
fastText(Facebook)—interestingfact:accountsforoutofvocabularywords.
因为单词是用坐标来表示的,所以要对它们进行比较(以比较相似性)。如果使用诸如主成分分析(PCA)等技术适当地缩小维度,则可以绘制单词,并且绘图通常会将具有相似含义的单词显示在一起,如下图所示,图片取自IBMResearchBlog:
词嵌入能够在一定程度上捕捉词义。句子甚至可以与嵌入进行比较。图片来自IBM研究编辑部。
坐标通常以大量的维度给出,通常在8到之间。通过这种方式,我们得到了一个由8到个维度数组组成的堆栈,这些维度数组不是稀疏的(它们被大量的浮点填充)。这对计算机来说更好用。
下面是另一个很酷的例子,摘自DavidRozado在《PLOSONE》上的一篇文章:
在考虑人们如何使用嵌入时,必须指出单词嵌入可以通过两种不同的方式生成:
1.通过与正在进行的过程(如情绪分析任务)一起训练,并根据具体任务捕捉单词之间的关系。当您使用Keras、Pytorch或Trax等库定义嵌入层时,会发生这种情况。这些层将单词索引映射到嵌入值。
2.通过在一个巨大的语料库中预先训练来捕捉语言中最常见的关系。这些经过预训练的嵌入可以被加载到模型中,以帮助加快学习过程或获得更好的结果。这就是fastText、Word2vec或GloVe的用武之地。像spaCy这样的库提供了这种嵌入使用。
我不想在这里讨论如何对嵌入进行预训练,但我正在准备一篇专门针对这种做法的文章。我建议你订阅我的帐户,以便在它发布时收到通知,或者留意这一段,因为当它准备好时,我会在它下面贴出一个链接。
为了增加一点关于这个主题的内容,我们也可以在将文本转换为特征时进行特征工程。换句话说,数据科学家可以应用自己的规则(通常通过预处理)来定义在将文本转换为数字数组之前应该提取什么。
正如我们所看到的,将文本转换为特征可能是一件简单而琐碎的事情,但还有很多事情要考虑。
在输入到编码器之前,单词索引映射到它们各自的嵌入,这是训练过程中使用的真实值。图片取自Pythorchseq2seq模型教程。
目前,NLP中的大多数技术只使用单词嵌入,因为它们更健壮,并且能够以顺序方式使用。
当然,每个算法和问题都需要对输入文本进行特定的操作。例如,seq2seq模型通常具有固定的序列长度。为了加强这个长度,使用填充或压缩。但最终,填充和单词都被转换为嵌入。
既然我们已经完成了NLP预处理中最基本的主题,我们可以开始讨论应用程序和技术。别忘了订阅“保持
转载请注明:http://www.aideyishus.com/lkzp/2600.html