使用python 2.7计算文档中的tf-idf

时间:2014-12-16 04:29:07

标签: python-2.7 nltk information-retrieval tf-idf cosine-similarity

我有一个场景,我从互联网上检索信息/原始数据,并将它们放入各自的json或.txt文件中。

从那时起,我想通过使用tf-idf来计算每个文档中每个术语的频率及其余弦相似度。

例如: 有50个不同的文档/文本文件,每个文件包含5000个单词/字符串 我想从第一个文件/文本中取出第一个单词并比较所有总共250000个单词找到它的频率,然后对第二个单词进行比较,依此类推所有50个文档/文本。

每个频率的预期输出将是0 -1

我怎么能这样做。我一直指的是sklear包,但是大多数只包含每个比较中的几个字符串。

1 个答案:

答案 0 :(得分:8)

您真的应该向我们展示您的代码并更详细地解释您遇到问题的部分。

您所描述的通常不是如何完成的。你通常做的是矢量化文档,然后比较矢量,这会产生这个模型下任何两个文档之间的相似性。既然你在询问NLTK,我会假设你想要这种常规的传统方法。

无论如何,对于传统的单词表示,两个单词之间的余弦相似性毫无意义 - 两个单词是相同的,或者它们不相同。但肯定有其他方法可以处理术语相似性或文档相似性。

https://stackoverflow.com/a/23796566/874188复制代码,以便我们有一个基线:

from sklearn.feature_extraction.text import TfidfVectorizer
corpus = ["This is very strange",
          "This is very nice"]
vectorizer = TfidfVectorizer(min_df=1)
X = vectorizer.fit_transform(corpus)
idf = vectorizer._tfidf.idf_
print dict(zip(vectorizer.get_feature_names(), idf))

此处没有任何内容取决于输入的长度。如果您有更长的文档,idf中的要素数量会更大,如果您有更多文档,则在语料库中会有更多的要素,但这样的算法根本不需要更改以容纳更多或更长的文件。

如果您不想了解原因,可以在这里停止阅读。

向量基本上是每个单词形式的计数数组。每个矢量的长度是字形的数量(即特征的数量)。所以如果你有一个包含六个条目的词典:

0: a
1: aardvark
2: banana
3: fruit
4: flies
5: like

然后输入文档“像香蕉一样的果蝇”会产生六个元素的向量,如下所示:

[2, 0, 1, 1, 1, 1]

因为在词典中在索引零处出现两个单词,在索引1处出现零,在索引2处出现一个,等等。这是TF(术语频率)向量。它已经是一个有用的载体;您可以使用余弦距离比较其中两个,并获得它们相似性的度量。

IDF因素的目的是使其正常化。正常化带来三个好处;从计算上讲,您不需要执行任何每个文档或每个比较的规范化,因此它更快;并且该算法还对频繁的单词进行归一化,以便如果大多数文档包含多个单词的出现(因此您不必进行明确的停用词过滤),则许多出现的“a”被认为是无关紧要的,而许多出现的“aardvark” “在标准化向量中立即显然是显着的。此外,归一化的输出可以很容易地解释,而对于普通的TF矢量,你必须考虑文件长度等,以正确理解余弦相似性比较的结果。

因此,如果“a”的DF(文档频率)为1000,并且词典中其他单词的DF为1,则缩放矢量将为

[0.002, 0, 1, 1, 1, 1]

(因为我们采用文档频率的倒数,即TF(“a”)* IDF(“a”)= TF(“a”)/ DF(“a”)= 2/1000)。

余弦相似性基本上解释了 n 维空间中的这些向量(这里, n = 6)并且看到它们的箭头彼此有多远。为简单起见,让我们将其缩小到三维,并在X轴上绘制(IDF缩放的)“a”数,在Y轴上绘制“aardvark”次数,以及“香蕉”出现次数在Z轴上。终点[0.002,0,1]与[0.003,0,1]相差一点点,而[0,1,0]终止于我们想象的立方体的另一个角落,所以余弦距离很大。 (归一化意味着1.0是任何元素的最大值,所以我们正在谈论一个角落。)

现在,返回到词典,如果你添加一个新文档并且它的单词还没有在词典中,它们将被添加到词典中,因此从现在开始向量需要更长。 (你已经创建的现在太短的向量可以简单地扩展;迄今看不见的术语的术语权重显然总是为零。)如果你将文档添加到语料库中,语料库中还会有一个向量来比较反对。但算法不需要改变;它将始终创建每个词典条目包含一个元素的向量,并且您可以使用与以前相同的方法继续比较这些向量。

您当然可以循环使用这些术语,并为每个术语合成一个仅由该单个术语组成的“文档”。将其与其他单项“文档”进行比较将产生0.0与其他文档的相似性(或与包含相同术语的文档的1.0相似性,而不是其他内容),因此这不太有用,但与现实世界文档的比较将基本揭示每个文件的比例由您正在检查的术语组成。

原始IDF向量告诉您每个术语的相对频率。它通常表示每个术语出现的文档数量(因此,即使术语在文档中出现多次,它只会在此术语的DF中加1),尽管某些实现也允许您使用术语计数。 / p>