本文将讨论如何通过矢量化、哈希、标记化和其他技术来准备文本,以便与机器学习( ML )和其他数值算法兼容。我将解释并演示该过程。
自然语言处理( NLP )将 机器学习 ( ML )和其他技术应用于语言。然而,机器学习和其他技术通常在被称为向量的数字数组上工作,这些向量表示数据集中的每个实例(有时称为观察、实体、实例或行)。我们称所有这些数组的集合为矩阵;矩阵中的每一行表示一个实例。按列查看矩阵,每列表示一个特征(或属性)。
到目前为止,如果不习惯数学语言,这种语言可能看起来相当抽象。然而,在处理表格数据时,数据专业人员已经接触过这种类型的数据结构,包括电子表格程序和关系数据库。
毕竟,当人们将行视为实例,将列视为特征时,电子表格就是矩阵。例如,考虑包含过去和现在雇员的数据集,其中每行(或实例)具有表示雇员的年龄、任期、工资、资历级别等的列(或特征)。
术语
NLP 必须解决的第一个问题是将文本实例集合转换为矩阵形式,其中每一行都是文本实例的数值表示——向量。但是,为了开始学习 NLP ,有几个术语很有用。让我们来介绍一下。
在 NLP 中,单个实例称为 document ,而 corpus 指的是实例的集合。根据手头的问题,文档可能简单到一个短语或名称,也可能复杂到整本书。
我们必须选择如何将文档分解为更小的部分,这一过程称为 tokenizing 文档。因此,这个过程产生 tokens 。令牌是算法可以考虑的意义单位。在整个语料库中看到的所有标记集称为 vocabulary 。
一种常见的代词选择是简单地取单词;在这种情况下,文档表示为 字里行间(鞠躬) 。更准确地说, BoW 模型在单词级别扫描整个语料库中的词汇,这意味着词汇是语料库中看到的所有单词的集合。然后,对于每个文档,算法计算语料库中每个单词的出现次数。
语料库中的大多数单词不会出现在大多数文档中,因此在一个特定文档中,许多标记的计数将为零。从概念上讲,这基本上就是它,但是一个重要的实际考虑是,当我们从这些计数形成向量时,确保每行的列以相同的方式对齐。换句话说,对于任意两行,给定任何索引 k ,每行的第 k 个元素表示相同的单词是至关重要的。
一个例子
在深入了解如何确保行对齐的细节之前,让我们快速查看一个手工完成的示例。我们将看到,作为一个简短的例子,作为一个人,确保这种一致性是相当容易的。最后,我们还必须考虑算法的散列部分,以便彻底实现。
假设我们的语料库是以下四个句子1:
预处理
让我们应用一些预处理来删除大小写和标点符号:
符号化
让我们通过将每个单词指定为标记来标记预处理的文档:
掌握词汇
扫描语料库并获得每个独特的单词,我们可以形成我们的词汇:
矢量化
让我们计算每个文档中每个单词出现的次数。
让我们把这个收集到一张桌子里。
This | is | the | first | document | second | and | third | one |
1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
1 | 1 | 1 | 0 | 2 | 1 | 0 | 0 | 0 |
1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 1 |
1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
如果我们忽略标题,这就是我们要寻找的矩阵。
散列
值得注意的是,排列此矩阵的行和任何其他设计矩阵(将实例表示为行,将特征表示为列的矩阵)不会改变其含义。列置换也是如此。根据我们将标记映射到列索引的方式,我们将获得不同的列顺序,但表示形式没有任何有意义的变化。
这种将令牌映射到索引的过程称为散列,这样就不会有两个令牌映射到同一个索引2特定的实现称为哈希、哈希函数或哈希函数。
基于词汇的哈希
在手工进行矢量化时,我们隐式地创建了一个哈希函数。假设采用 0 索引系统,我们将第一个索引 0 分配给我们没有看到的第一个单词。然后我们增加索引并重复这个过程。我们的哈希函数将“ this ”映射到 0 索引列,“ is ”映射到 1 索引列,“ the ”映射到 3 索引列。基于词汇表的哈希函数有一定的优点和缺点。
基于词汇表的哈希的优点
将词汇表用作散列函数,可以反转散列。这意味着,给定特征(或列)的索引,我们可以确定相应的标记。一个有用的结果是,一旦我们训练了一个模型,我们就可以看到某些标记(单词、短语、字符、前缀、后缀或其他单词部分)如何影响模型及其预测。因此,我们可以通过查看模型如何使用令牌进行预测来解释、解释、排除故障或微调模型。我们还可以检查重要的标记,以辨别它们的包含是否给模型带来了不适当的偏差。
让我们考虑由一些机器学习模型产生的伪影。例如,如果我们使用逻辑回归模型,我们可以将与每个特征相关的系数解释为其对模型预测的影响。随机林模型产生特征重要性,它告诉我们随机林中的决策树使用每个特征进行决策的频率。类似地,朴素贝叶斯模型会产生特定类的特征不为零的概率。
基于词汇表的矢量化的力量在于理解每个特征代表哪个标记。因此,相反,通过逻辑回归模型,我们可以看到每个 token 对预测的影响有多大。对于随机林,我们得到与每个 token 相关的特征重要性,这告诉我们随机林中的决策树使用每个 token 进行决策的频率。使用朴素贝叶斯,我们可以提取某个 token 出现在每个类的文档中的概率。
如果我们发现看似不相关或不恰当的偏见 tokens 对预测有可疑的影响,我们可以将其从词汇表中删除。如果我们观察到某些标记对我们的预测的影响可以忽略不计,我们可以将它们从词汇表中删除,以获得更小、更高效和更简洁的模型。
基于词汇表的哈希的缺点
基于词汇表的哈希有一些缺点,在训练和预测中使用的内存量相对较大,在分布式训练中会造成瓶颈。
基于词汇表的哈希的一个缺点是算法必须存储词汇表。对于较大的微粒,更多的文档通常会产生更多的单词,从而产生更多的标记。较长的文档也会导致词汇表的大小增加。
在单个线程上,可以编写算法来创建词汇表,并在单个过程中对标记进行散列。然而,有效地并行执行一次传递的算法是不现实的,因为每个线程必须等待其他线程检查词汇表(存储在公共内存中)中是否添加了单词。如果不将词汇表存储在公共内存中,每个线程的词汇表将导致不同的散列,并且无法将它们收集到一个正确对齐的矩阵中。
并行化矢量化算法的一个更好的方法是在第一次遍历中形成词汇表,然后将词汇表放入公共内存中,最后并行散列。然而,这种方法并没有充分利用并行化的好处。此外,如前所述,词汇表可以很快变大,特别是对于包含大型文档的大型语料库。
数学散列
幸运的是,还有另一种散列令牌的方法:使用非加密数学散列函数散列每个实例。这种类型的散列函数使用算术、模算术和代数的组合将对象(由其位表示)映射到已知范围的整数或(位)。由于范围已知,因此最大值确定矩阵中有多少列。通常,范围相当大,但对于大多数行,大多数列将为 0 。因此,使用稀疏表示,存储矩阵所需的内存将是最小的,并且算法可以有效地处理基于稀疏矩阵的操作。
此外,由于没有词汇表,使用数学哈希函数进行矢量化不需要词汇表的任何存储开销。没有词汇表意味着并行化没有任何限制,因此语料库可以划分为任意数量的过程,允许独立地对每个部分进行矢量化。一旦每个过程完成对其所占微粒的矢量化,生成的矩阵就可以堆叠起来形成最终矩阵。这种并行化是通过使用数学哈希函数实现的,它可以通过消除瓶颈显著加快训练过程。
尽管使用数学散列函数可以减少生成特征向量所需的时间,但它确实是有代价的,即失去可解释性和可解释性。因为在使用散列函数时,不可能有效地从功能的索引映射回相应的标记,所以我们无法确定哪个标记对应于哪个功能。所以我们失去了这些信息,因此失去了可解释性和可解释性。
结论
在本文中,我们看到了计算机用来将文本转换为向量的基本算法。我们已经解开了需要数字输入的算法如何与文本输入协同工作的谜团。
文本数据集通常非常大,因此我们需要注意速度。因此,我们考虑了一些改进,使我们能够并行执行矢量化。我们还考虑了可解释性、速度和内存使用之间的一些折衷。
通过将机器学习应用于这些向量,我们打开了自然语言处理领域。此外,矢量化还允许我们将相似性度量应用于文本,从而实现全文搜索和改进的模糊匹配应用程序。
1此示例来自 SciKit 学习文档: sklearn.feature_extraction.text .CountVectorizer
2通常,哈希函数 can 将两个实体映射到同一索引。这称为冲突,对于散列函数来说应该是极为罕见的。碰撞是不可取的。