# 浅谈词袋模型

原文链接：[A Gentle Introduction to the Bag-of-Words Model](A Gentle Introduction to the Bag-of-Words Model)

词袋模型是一种在使用机器学习算法建模文本时表示文本数据的方式。

词袋模型易于理解和实现，并且在语言建模和文档分类等问题上取得了巨大成功。

在本教程中，您将发现用于自然语言处理中的特征提取的词袋模型。

完成本教程后，您将了解：

- 词袋模型是什么以及为什么需要表示文本。
- 如何为一组文档开发一个词袋模型。
- 如何使用不同的技巧来准备词汇和得分词。

让我们开始吧。

[Do8y](https://www.flickr.com/photos/beorn_ours/5675267679/) 对袋子模型照片的温和介绍（解释权归作者所有）。



## 教程概述

------

本教程分为6个部分：

1. 关于文本的问题
2. 什么是字袋？
3. 词袋模型的例子
4. 管理词汇
5. 得分词
6. 词袋的局限性



### 在文本数据深度学习方面需要帮助？

立即参加我的免费7天电子邮件速成课程（附代码）。

点击注册并获得免费的PDF电子书版课程。

[开始免费速成课程](https://machinelearningmastery.lpages.co/leadbox/144855173f72a2%3A164f8be4f346dc/5655638436741120/)



## **1.文本问题**

------

建模文本的一个问题是它很乱，机器学习算法等技术更喜欢定义明确的固定长度输入和输出。

机器学习算法无法直接使用原始文本; 文本必须转换为数字。具体而言，是数字的向量。

> 在语言处理中，向量x从文本数据导出，以反映文本的各种语言属性。

\- 第65页，[自然语言处理中的神经网络方法](http://amzn.to/2wycQKA)，2017年。

这称为特征提取或特征编码。

使用文本数据进行特征提取的一种流行且简单的方法称为文本的词袋模型。



## **2.什么是词袋？**

------

词袋模型（简称BoW）是一种从文本中提取特征的方法，用于建模，例如机器学习算法。

该方法非常简单和灵活，并且可以以多种方式用于从文档中提取特征。

词袋是文本的表示，用于描述文档中出现的单词。它涉及两件事：

1. 已知单词的词汇。
2. 衡量已知单词的存在。

它被称为单词的“*包* ”，因为有关文档中单词的顺序或结构的任何信息都被丢弃。该模型仅关注文档中是否出现已知单词，而不是文档中的位置。

> 句子和文档的一个非常常见的特征提取过程是词袋方法（BOW）。在这种方法中，我们查看文本中单词的直方图，即将每个单词计数视为一个特征。

\- 第69页，[自然语言处理中的神经网络方法](http://amzn.to/2wycQKA)，2017年。

直觉是如果文档具有相似的内容，则文档是相似的。此外，仅从内容中我们可以了解文档的含义。

这个词袋可以像你想的那样简单或复杂。复杂性在于决定如何设计已知单词（或标记）的词汇以及如何对已知单词的存在进行评分。

我们将仔细研究这两个问题。



## **3.词袋模型的例子**

------

让我们用一个具体例子来使用词袋模型。

### **第1步：收集数据**

下面是查尔斯·狄更斯（Charles Dickens）的“ [双城记”](https://www.gutenberg.org/ebooks/98) [(The Tale of Two Cities）](https://www.gutenberg.org/ebooks/98)中的前几行文本摘录，摘自Project Gutenberg。

> It was the best of times, 
>
> it was the worst of times,
>
>  it was the age of wisdom, 
>
> it was the age of foolishness

> 这是一个最好的年代,

> 也是一个最坏的年代,
>
> 这是一个智慧的年代,
>
> 这是一个愚蠢的年代

对于这个小例子，让我们将每一行视为一个单独的“文档”，将4行视为完整的文档集。



### **第2步：设计词汇表**

现在我们可以列出模型词汇表中的所有单词。

这里不同的单词（忽略大小写和标点符号）是：

- “it”
- “was”
- “the”
- “best”
- “of”
- “times”
- “worst”
- “age”
- “wisdom”
- “foolishness”

现在这是一个包含24个单词的语料库中10个单词。



### **第3步：创建文本向量**

下一步是对每个文档中的单词进行评分。

目标是将每个自由文本文档转换为一个矢量，我们可以将其用作机器学习模型的输入或输出。

因为我们知道词汇表有10个单词，所以我们可以使用10的固定长度文档表示，在向量中有一个位置来对每个单词进行评分。

最简单的评分方法是将单词的存在标记为布尔值，0表示不存在，1表示存在。

使用我们词汇表中上面列出的单词的任意排序，我们可以逐步浏览第一个文档（“ *it was the best of times* ”）并将其转换为二进制向量。

该文件的评分如下：

- “it” = 1
- “was” = 1
- “the” = 1
- “best” = 1
- “of” = 1
- “times” = 1
- “worst” = 0
- “age” = 0
- “wisdom” = 0
- “foolishness” = 0

作为二进制向量，这将如下所示：

```
[1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
```

其他三份文档如下：

```
"it was the worst of times" = [1, 1, 1, 0, 1, 1, 1, 0, 0, 0]
"it was the age of wisdom" = [1, 1, 1, 0, 1, 0, 0, 1, 1, 0]
"it was the age of foolishness" = [1, 1, 1, 0, 1, 0, 0, 1, 0, 1]
```

所有单词的排序名义上都被丢弃了，我们有一致的方法从我们语料库中的任何文档中提取特征，准备用于建模。

与已知单词的词汇重叠但可能包含词汇表之外的单词的新文档仍然可以被编码，其中仅对已知单词的出现进行评分并且忽略未知单词。

您可以看到这可能会自然地扩展到大型词汇表和更大的文档。



## **4.管理词汇**

------

随着词汇量的增加，文档的向量表示也会增加。

在前面的示例中，文档向量的长度等于已知单词的个数。

你可以想象，对于一个非常大的语料库，例如数千本书，矢量的长度可能是数千或数百万个位置。此外，每个文档可能包含很多词汇表中没有的单词。

这导致向量中有许多0，称为稀疏向量或稀疏表示。

稀疏向量在建模时需要更多的存储器和计算资源，并且大量的位置或维度将使建模过程对于传统算法非常具有挑战性。

因此，当使用词袋模型时，减小词汇量存在一定的压力。

有一些简单的文本清理技术可用作预备处理，例如：

- Ignoring case（无视案例？）
- 忽略标点符号
- 忽略不包含太多信息的常用词，称为停用词（stop words），如“a”，“of”等。
- 修复拼写错误的单词。
- 使用 stemming algorithms ( 阻塞算法 干扰算法 )将单词减少到词干（例如，playing-->play）。

更复杂的方法是创建分组的词汇表。这既改变了词汇表的范围，又允许词袋从文档中捕获更多的含义。

在这种方法中，每个单词或标记称为“克”。反过来，创建双字对词汇表称为二元组模型。同样，只有出现在语料库中的词组（或短语）才被建模，而不是所有可能的词组。

> N-gram是一个N-token单词序列：2-gram（通常称为bigram）是一个双字序列的单词，如“ please turn（请转）”，“ turn your（转动你的）”或“ your homework（你的作业）”，以及一个3克（通常称为三元音）是一个三字词序列，如“请转动你的”，或“转动你的作业”。

\- 第85页，[语音和语言处理](http://amzn.to/2vaEb7T)，2009年。

例如，上一节中第一行文字中的双字母组：“这是最好的时间”如下：

- “it was”       “它是”
- “was the”    “是的”
- “the best”    “最好的”
- “best of”      “最好”
- “of times”    “时代”

然后跟踪词汇三元组的词汇表称为三元组模型，一般方法称为n-gram模型，其中n表示分组词的数量。

对于像文档分类这样的任务，通常一个简单的二元组方法比一组1克的词袋模型更好。

> 一个袋子的bigrams表示比词袋更强大，并且在许多情况下证明非常难以击败。

\- 第75页，[自然语言处理中的神经网络原理](http://amzn.to/2wycQKA)，2017年。



## 5.得分词

一旦选择了词汇表，就需要对示例文档中的单词进行评分。

在工作示例中，我们已经看到了一种非常简单的评分方法：对单词存在与否的二进制评分。

一些额外的简单评分方法包括：

- **（个别）计数**。计算每个单词在文档中出现的次数。
- **（整体）频率**。计算文档中所有单词中每个单词出现在文档中的频率。



### 字哈希（Word Hashing）

您可能还记得计算机科学中的[哈希算法](https://en.wikipedia.org/wiki/Hash_function)是一种将数据映射到固定大小的数字集的数学运算。

例如，我们在编程时在哈希表中使用它们，其中可能将名称转换为数字以进行快速查找。

我们可以在词汇表中使用已知单词的哈希表示。这解决了对于大文本语料库具有非常大的词汇表的问题，因为我们可以选择哈希空间的大小，该大小又是文档的向量表示的大小。

单词被确定性地散列到目标散列空间中的相同整数索引。然后可以使用二进制分数或计数来对单词进行评分。

这称为“ *哈希技巧* ”或“ *功能哈希* ”（ “*hash trick*” or “*feature hashing*“）。

挑战在于选择一个哈希空间来容纳所选择的词汇量大小，以最大限度地减少冲突和权衡稀疏性出现的可能性。



### TF-IDF ( Term Frequency – Inverse Document Frequency )

对单词频率进行评分的问题在于，高频率的单词在文档中开始占主导地位（得分越高），但可能由于一些特殊的单词（词组）从而不包含与模型的“信息内容”。

一种方法是通过它们在所有文档中出现的频率来重新调整单词的频率，使得在所有文档中频繁出现的频繁单词（如“the”）的分数受到惩罚。

这种评分方法称为 **术语频率 - 反向文档频率**，或简称为TF-IDF，其中：

- **术语频率**：是当前文档中单词频率的得分。
- **反向文档频率**：是对文档中单词的罕见程度的评分。

分数是一个权重，并非所有单词都同样重要或有趣。

分数具有突出显示给定文档中不同（包含有用信息）的单词的效果。

> 因此，罕见术语的idf很高，而常用术语的idf可能很低。

\- 第118页，[信息检索简介](http://amzn.to/2hAR7PH)，2008年。

（译者注：[一篇关于TF-IDF的中文博客可能可以帮助您了解更多](https://www.cnblogs.com/daneres/p/5673762.html)）



## 6.词袋的局限性

------

词袋模型非常易于理解和实现，并为您的特定文本数据提供了很大的灵活性。

它在语言建模和文档分类等预测问题上取得了巨大成功。

然而，它有一些缺点，例如：

- **词汇**：词汇表需要精心设计，最重要的是为了管理大小，这会影响文档表示的稀疏性。
- **稀疏性**：由于计算原因（空间和时间复杂性）以及信息原因，稀疏表示更难以建模，其中挑战是模型在如此大的代表空间中利用如此少的信息。
- **含义**：丢弃单词顺序忽略了上下文，而忽略了文档中单词的含义（语义）。上下文和意义可以为模型提供很多东西，如果建模可以说出不同排列的相同单词之间的区别（“this is interesting” 与 “is this interesting”），同义词（“旧自行车”与“二手自行车”） ， 以及更多。



## 进一步阅读

如果您要深入了解，本节将提供有关该主题的更多资源。

### 文章

- [维基百科上的词袋模型](https://en.wikipedia.org/wiki/N-gram)
- [维基百科上的N-gram](https://en.wikipedia.org/wiki/N-gram)
- [维基百科上的功能哈希](https://en.wikipedia.org/wiki/Feature_hashing)
- [维基百科上的tf-idf](https://en.wikipedia.org/wiki/Tf%E2%80%93idf)



### 图书

- 第6章，[自然语言处理中的神经网络方法](http://amzn.to/2wycQKA)，2017。
- 第4章，[语音和语言处理](http://amzn.to/2vaEb7T)，2009年。
- 第6章，[信息检索简介](http://amzn.to/2vvnPHP)，2008年。
- 第6章，[统计自然语言处理基础](http://amzn.to/2vvnPHP)，1999年。



你有任何问题吗？在下面的评论中提出您的问题，我会尽力回答。