我有一个场景,我从互联网上检索信息/原始数据并将它们放入各自的 json 或 .txt 文件中。
从那时起,我想通过使用 tf-idf 计算每个文档中每个术语的频率及其余弦相似度。
例如:有 50 个不同的文档/文本文件,每个文件包含 5000 个单词/字符串对于所有 50 个文档/文本,依此类推。
每个频率的预期输出将从 0 -1
我怎么能这样做。我一直在指 sklear 包,但它们中的大多数在每次比较中只包含几个字符串。
我有一个场景,我从互联网上检索信息/原始数据并将它们放入各自的 json 或 .txt 文件中。
从那时起,我想通过使用 tf-idf 计算每个文档中每个术语的频率及其余弦相似度。
例如:有 50 个不同的文档/文本文件,每个文件包含 5000 个单词/字符串对于所有 50 个文档/文本,依此类推。
每个频率的预期输出将从 0 -1
我怎么能这样做。我一直在指 sklear 包,但它们中的大多数在每次比较中只包含几个字符串。
您确实应该向我们展示您的代码并更详细地解释您遇到问题的部分。
你所描述的通常不是它是如何完成的。您通常做的是将文档向量化,然后比较向量,从而得出此模型下任意两个文档之间的相似性。由于您询问的是 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
那么输入文档“a fruit flies like abanana”将产生一个包含六个元素的向量,如下所示:
[2, 0, 1, 1, 1, 1]
因为在词典中索引为零的单词出现了两次,索引一的单词出现了零次,索引二的单词出现了一次,等等。这是一个 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 轴上绘制“a”的(IDF 缩放)数量,在 Y 轴上绘制“土豚”出现的数量,以及“香蕉”出现的数量在 Z 轴上。端点 [0.002, 0, 1] 与 [0.003, 0, 1] 仅相差一点点,而 [0, 1, 0] 最终在我们想象的立方体的另一个角落,所以余弦距离很大。(归一化意味着 1.0 是任何元素的最大值,所以我们实际上是在谈论一个角。)
现在,回到词典,如果您添加一个新文档并且其中包含词典中不存在的单词,它们将被添加到词典中,因此从现在开始向量将需要更长的时间。(您已经创建但现在太短的向量可以简单地扩展;迄今为止未见过的术语的术语权重显然总是为零。)如果您将文档添加到语料库中,语料库中将再有一个向量进行比较反对。但是算法不需要改变;它总是会为每个词典条目创建一个元素的向量,您可以继续使用与以前相同的方法来比较这些向量。
您当然可以遍历这些术语,并为每个术语合成一个仅由该单个术语组成的“文档”。将其与其他单项“文档”进行比较将产生 0.0 的相似度(或 1.0 的相似度与包含相同术语但没有其他内容的文档),因此这不是很有用,但与真实世界的文档进行比较将基本上揭示每个文档中包含您正在检查的术语的比例。
原始 IDF 向量告诉您每个术语的相对频率。它通常表示每个术语出现在多少个文档中(因此即使一个术语在文档中出现多次,它也只会将 1 加到该术语的 DF 上),尽管某些实现还允许您使用裸术语计数。