1. 问题描述
给你若干篇文档,找出这些文档中最相似的两篇文档?
相似性,可以用距离来衡量。而在数学上,可使用余弦来计算两个向量的距离。
[cos(vec a, vec b)=frac {vec a*vec b}{||vec a||*||vec b||} ]
因此,用向量来表示文档,然后就可以用余弦来计算两篇文章之间的相似度了。
2. 词袋模型
一篇文档里面有很多很多句子,每个句子又是由一个个的词组成。词袋模型,通俗地讲,就是:把一篇文档看成词袋,里面装着一个个的词。
从而,将一篇文档转化成了一个个的词(或者称之为 term),显然地,文档转化成一个个的词之后,词与词之间的顺序关系丢失了。
3. TF-IDF
在计算文档之间相似度之前,会有一些前提条件:
- 我们有一个文档集合C,文档集合C里面一共有N篇文档
- 我们有一个词典D,或者叫词库(Vocabulary),词库里面一共有M个词
3.1 文档到向量的转化
向量是有长度的,向量中的每个元素是数值,比如一个三维实值向量:(1.2,2.8,4.5)
首先将文档通过词袋模型转化成一个个的词,一般地,由于文档中的词都会存在于词典D中,定义一个M维向量(M等于词典大小),若文档中的某个词在词典中出现了,就给这个词赋一个实数值。若未出现,则在相应位置处赋值为0
3.2 使用TF-IDF 衡量每个词(term)的权重
在给定的文档集合C和词典D的情况下,如何来衡量一个词(term)的权重呢?即如何计算这个实数值呢?
3.2.1 tf值
tf(term frequency),是指 term 在某篇文档中出现的频率。假设文档集合中共有10篇文章,词:''国家'',在文档1中出现了6次,那么对于文档1而言,'国家'这个词的tf值为6。因此,tf 是针对单篇文档而言的,即:某个词在这篇文档中出现了多少次。词频是计算文档得分的一个因子,因此为了计算某篇文档的得分,使用的词频指的就是term在这篇文档中出现的次数,而不是term在所有文档中出现的次数。
3.2.2 idf值
'国家'这个词在文档1中的idf值 由 词(term) 出现在各个文档中数目来决定,比如'国家'一共在8篇文档中出现了,那么对于文档1而言,'国家'这个词的idf值由如下公式计算:
[idf_t=logfrac{N}{df_t} ]
其中,N=10 表示文档集合中共有10篇文章。(df_t=8),表示 term 国家 在8篇文档中出现了。因此,idf 值是针对所有文档(文档集合)而言的,即:数一数这个词都出现在哪些文档中。
而TF-IDF,就是将tf值乘以idf值:
[TF-IDF=tf*idf ]
前面提到,将文档向量化,需要给文档中的每个词赋一个实数值,这个实数值,就是通过tf*idf得到。
4. 总结
在给定文档集合C和词典D的条件下,将某篇文档通过词袋模型表示成一个个的词,而后根据 TF-IDF 为每个词计算出一个实数值;
由于词典D的大小为M,因此将这篇文档转化成一个M维向量,如果词典中某个词未出现在文档中,则这个词的在向量中对应的元素为0,若某个词出现在文档中,则这个词在向量中对应的元素值为这个词的tf-idf值。这样,就把文档表示成向量了,而这就是 向量空间模型(vector space model)。从这里也可看出:向量空间模型并没有catch住词(term)与词(term)之间的关系,它假设各个term之间是相互独立的。即:VSM implies the assumption on the independence between terms
而有了文档向量,也就可以用余弦公式计算文档之间的相似度了。
由于词典一般比较大,比如20万个词左右的汉语词典,而一篇文档中一般只包含几百个词,因此可看出:文档向量是很稀疏的。
另外,由于对于文档而言,词与词之间是有顺序的,比如文档开头是哪些词,中间有哪些词,结尾又是哪些词,但表示成向量之后,这个 顺序 信息丢失了。比如下面2篇文档,它们的文档向量是一样的。
Mary is quick than John
John is quick than Mary
总之,在我看来,向量空间模型是一种将文档转化成向量的方式,文档转化成了向量,从而可以在同一维度的空间中表示一个个的文档。向量中的每个元素是一个个的实数,每个元素对应着一个 词(term),实数 是通过tf-idf计算出来的。由此看来,tf-idf也仅仅是一种将词(term)转化成实数的方式,当然我们也可以通过其他方法将 词 转化成实数。而这里的 词 则是由词典定义的,若词典中的某个词 在文档中,则计算这个词的tf-idf值,若某个词不在文档中,则这个词对应的向量元素为0。因此,得到的文档向量是M维的,其中M就是词典的大小---词典中词的个数。
将文档转化成了向量,文档之间的比较,就可以转化成向量的比较。因此,就能回答给定若干篇文档,哪两篇文档最相关这样的问题了。在实际应用中,比如Lucene中的TF-IDF Similarity就是基于VSM来实现的。从VSM Model到Lucene Conceptual Scoring Formula 再到 Lucene Practical Scoring Formula,解释了在实际应用中,我们输入一个查询字符串,Lucene是如何计算文档的得分,从而找出与查询字符串最相关的文档的。
5. 实际应用
在实际应用中,我们并不是直接使用 TF*IDF 这个理论模型,因为它计算出来的权重偏向于短文本,因此需要某种平滑。
举个例子来说,term1在docA中出现了3次,term2在docA中出现了9次,根据上面计算TF的方式,意味着:term2的tf权重(或者说重要性)比term1要大3倍,那真的是重要3倍么?因此,在Lucene的实际评分模型中,计算的是sqrt(tf),即通过 tf 开根号,起到一定的平滑作用。类似地,计算 idf 时,是取log对数,也是为了平滑。
参考资料:
- 《An Introduction to Information Retrieval》第6章
- bm25-the-next-generation-of-lucene-relevation
- Lucene JAVA API TF-IDF Similarity