# TF-IDF in a nutshell

![luhn](./tf-idf-in-a-nutshell/luhn.jpeg)早在1958年，Hans Peter Luhn在他的论文"The Automatic Creation of Literature Abstracts"中假设"文章中词语出现的频率可以提供一个有用的词语重要性度量"，这一假设至今可能是信息检索科学中最重要的内容之一，并且被所有知名的大中小型搜索引擎使用，从Google和Yahoo到定制搜索解决方案，如ElasticSearch和Manticore Search。



Luhn的假设的重要性无法被高估，许多后续的信息检索领域的科学研究都基于Luhn的假设，尽管并非所有研究都提到了这一点，可能随着时间的推移，它已成为公理。

在本文中，我将通过非常清晰的例子展示TF（词频）及其对应项IDF（逆文档频率）如何帮助找到你想要的内容。

让我们取5个文档：

```bash
1. My dog doesn't like all my pets, but me and my wife do love them all. A dog cannot be a cat lover
2. Cats and dogs do not like each other, but my cat does like dogs
3. Walking a dog is a good start of the day
4. Not all cats like walking, but some cats do
5. All dogs like walking, but mine doesn't like. It's like so weird

```

并尝试对它们进行排序（即找到最相关和最不相关的文档及其顺序）以应对不同的查询。
  
  
### 权重 = 如果词语出现则为1，否则为0


 **查询：'like'**。

请注意，我们不知道查询中的'like'具体是什么意思：比如"A is like B"或"I like smth"。那么我们能做些什么来对文档进行排序呢？

首先想到的是，如果一个文档中完全不包含'like'这个词，那么它可能不太相关。因此顺序可以是：

```bash
1. My dog doesn't <b>like</b> all my pets, but me and my wife do love them all. A dog cannot be a cat lover
2. Cats and dogs do not <b>like</b> each other, but my cat does <b>like</b> dogs
4. Not all cats <b>like</b> walking, but some cats do
5. All dogs <b>like</b> walking, but mine doesn't <b>like</b>. It's <b>like</b> so weird
3. Walking a dog is a good start of the day

```

我们将文档#3放在最后，因为它不包含'like'。至于其余文档，我们没有改变它们的顺序，因为它们都包含'like'。这种排序的质量足够好吗？我不这么认为，因为在前四个文档中，有2个（#5和#2）似乎比其他文档更相关，因为它们提供了更多与查询词'like'相关的事实（记住我们不知道查询中'like'的确切含义），但它们并不是前两名。那么我们能做些什么呢？
  
  
### 权重 = 词频


 **查询：'like'**。

正如之前所说，根据Luhn的假设，包含更多查询词出现次数的文档可能更相关。让我们按它们的词频对文档进行排序（注意在这里以及信息检索领域一般情况下，“频率”仅指计数，而不是像物理学中那样用计数除以某个数）：

```bash
5. All dogs <b>like</b> walking, but mine doesn't <b>like</b>. It's <b>like</b> so weird | tf = 3
2. Cats and dogs do not <b>like</b> each other, but my cat does <b>like</b> dogs | tf = 2
1. My dog doesn't <b>like</b> all my pets, but me and my wife do love them all. A dog cannot be a cat lover | tf = 1
4. Not all cats <b>like</b> walking, but some cats do | tf = 1
3. Walking a dog is a good start of the day | tf = 0

```

这解决了问题，现在文档#5和#2位于最前面。

但我们现在尝试另一个**查询 - 'my day'**：

```bash
1. <b>My</b> dog doesn't like all <b>my</b> pets, but me and <b>my</b> wife do love them all. A dog cannot be a cat lover | tf = 3
2. Cats and dogs do not like each other, but <b>my</b> cat does like dogs | tf = 1
3. Walking a dog is a good start of the <b>day</b> | tf = 1
4. Not all cats like walking, but some cats do | tf = 0
5. All dogs like walking, but mine doesn't like. It's like so weird | tf = 0

```

文档#1和#2获得了最高位置，但这是正确的吗？它们只提到了'my'，而没有提到'day'：我的宠物、我的妻子、我的猫，这可能在查询中也很重要，但很可能不是。文档#3的位置较低，而它似乎是最相关的。我们如何将其排得更高？

让我们思考'my'与'day'和其他词有什么不同。'day'似乎更加具体，而'my'可以适用于几乎所有事物，并且**在文档中'my'出现的频率远高于'day'和其他更具体的术语**。这就是所谓的“**文档频率**”——公式中的另一个重要部分，也是词权重的第二个基石。

![ksj](./tf-idf-in-a-nutshell/ksj.jpg)1972年，英国计算机科学家Karen Spärck Jones在她的一篇学术论文中说：“文档描述的完备性是它包含的术语数量，而术语的特异性是它所适用的文档数量”。

我们已经讨论了前者，现在让我们看看如果我们计算后者，文档顺序会如何变化。
  
  
### 权重 = 词频 \* (文档总数 / 文档频率)
**查询：'my day'**。

'my'出现在2个文档中，'day'只出现在1个文档中，因此'my'的IDF（逆文档频率）是5（总文档数）/ 2 = 2.5，'day'是5/1 = 5。

```bash
1. <b>My</b> dog doesn't like all <b>my</b> pets, but me and <b>my</b> wife do love them all. A dog cannot be a cat lover
Weight = 3(tf of 'my') * 2,5(idf of 'my') + 0(tf of 'day') * 5 (its idf) = 7,5
3. Walking a dog is a good start of the <b>day</b>
Weight = 0 * 2,5 + 1 * 5 = 5
2. Cats and dogs do not like each other, but <b>my</b> cat does like dogs
Weight = 2,5
4. Not all cats like walking, but some cats do
Weight = 0
5. All dogs like walking, but mine doesn't like. It's like so weird
Weight = 0

```

借助IDF，我们可以将相关文档“Walking a dog is a good start of the day”提升一个位置，但它仍然不在最前面。原因是什么？这是因为'my'出现得太多了，这抵消了'day'的IDF的重要性。我们如何解决这个问题？我们需要某种方法来降低TF的贡献。多年来，人们提出了并研究了多种TF归一化的变体，从简单的log(TF)到所谓的“词频饱和曲线”。为了简单起见，我们只采用对数变体。
  
  
### 权重 = log(1+TF) \* (N/df)


![log](./tf-idf-in-a-nutshell/log.png)与线性函数相比，对数平滑的整体思想是，随着参数的增加，增长速度会变慢，即对于较小的x增长较快，对于较大的x增长较慢。函数中的'1+x'是为了在词频为0时避免参数为0，因为log(0)是未定义的，而log(0+1)是0，这正是我们对tf=0所需的结果。

让我们看看它是否解决了问题：
**查询：'my day'**。

```bash
3. Walking a dog is a good start of the <b>day</b>
Weight = log(1+0) * 2,5 + log(1+1) * 5 = 0 + 3,47 = 3,47
1. <b>My</b> dog doesn't like all <b>my</b> pets, but me and <b>my</b> wife do love them all. A dog cannot be a cat lover
Weight = log(1+3) * 2,5 + log(1+0) * 5 = 3,47 + 0 = 3,47
2. Cats and dogs do not like each other, but <b>my</b> cat does like dogs
Weight = 1,73
4. Not all cats like walking, but some cats do
Weight = 0
5. All dogs like walking, but mine doesn't like. It's like so weird
Weight = 0

```

正如我们所见，最相关的文档终于排在了第一位，但它与另一个权重为3.47的文档并列。这是对还是错？这是一个很难回答的问题，因为我们永远无法确定请求者认为什么相关。有可能通过询问“my day”，他或她也会认为第二个文档相关，因为它为'my'提供了多个事实，而第一个文档只提到了'day'的一个事实。因此，它们获得相同的权重可能是相当公平的。

由于这种不确定性，这可能就是为什么搜索引擎通常返回的不是单一结果，而是多个结果：10个、20个或类似数量，这样用户就可以自己做出最终决定。
  
  
### 结论


在本文中，我简明扼要地展示了TF-IDF加权公式的思维演变过程，这证明了它有效，且每个组成部分都很重要。

TF-IDF 的一种延续称为 BM25，它基于之前提到的“词频饱和曲线”，并且更多地采用概率方法来定义加权公式（再次提醒我们永远无法确定什么才是真正相关的，因此采用了概率方法）。总体而言，它仍然是 TF-IDF（通过文档长度进行归一化），但其根源完全不同。它将在另一篇文章中进行详细讲解。请继续关注我们并订阅我们的电子通讯，以免错过。
