我正在寻找一个可以计算 tf-idf 计算的简单 java 类。我想对 2 个文档进行相似性测试。我发现了很多使用 tf-idf 类的 BIG API。我不想使用一个大的 jar 文件,只是为了做我的简单测试。请帮忙 !或者至少如果有人能告诉我如何找到 TF?和以色列国防军?我会计算结果 :) 或者如果你能告诉我一些好的 Java 教程。请不要告诉我寻找谷歌,我已经做了 3 天,但找不到任何东西 :( 也请不要将我推荐给 Lucene :(
3 回答
术语频率是术语在特定文档中出现的次数的平方根。
逆文档频率是((文档总数除以包含该术语的文档数)的对数)加一,以防该术语出现零次 - 如果确实如此,显然不要尝试除以零。
如果从该答案中不清楚,则每个文档每个术语都有一个 TF,每个术语有一个 IDF。
然后 TF-IDF(term, document) = TF(term, document) * IDF(term)
最后,您使用向量空间模型来比较文档,其中每个术语是一个新维度,向量中指向该维度的部分的“长度”是 TF-IDF 计算的。每个文档都是一个向量,因此计算两个向量,然后计算它们之间的距离。
因此,要在 Java 中执行此操作,请使用 FileReader 或其他工具一次读取一行文件,然后按空格或您要使用的任何其他分隔符进行拆分 - 每个单词都是一个术语。计算每个术语在每个文件中出现的次数,以及每个术语出现在文件中的数量。然后你就拥有了进行上述计算所需的一切。
由于我无事可做,我查找了矢量距离公式。干得好:
D=sqrt((x2-x1)^2+(y2-y1)^2+...+(n2-n1)^2)
为此,x1 是文档 1 中术语 x 的 TF-IDF。
编辑:针对您关于如何计算文档中单词数的问题:
- 使用阅读器逐行读取文件,例如
new BufferedReader(new FileReader(filename))
- 您可以BufferedReader.readLine()
在 while 循环中调用,每次检查是否为 null。 - 对于每一行,调用
line.split("\\s")
- 这会将您的行拆分为空格并为您提供所有单词的数组。 - 对于每个单词,将当前文档的单词计数加 1。这可以使用
HashMap
.
现在,在为每个文档计算 D 之后,您将有 X 个值,其中 X 是文档数。将所有文档相互比较只需进行 X^2 次比较 - 对于 10,000 次,这应该不会花费特别长的时间。请记住,如果两个文档的 D 值之间的差值的绝对值较低,则两个文档更相似。因此,您可以计算每对文档的 D 之间的差异,并将其存储在优先级队列或其他排序结构中,以便最相似的文档冒泡到顶部。有道理?
虽然您特别要求不要提及 Lucene,但请允许我指出确切的类。您正在寻找的课程是DefaultSimilarity。它有一个非常简单的 API 来计算 TF 和 IDF。请参阅此处的 java 代码。或者您可以按照 DefaultSimilarity 文档中的说明实现自己。
TF = sqrt(freq)
和
IDF = log(numDocs/(docFreq+1)) + 1.
log 和 sqrt 函数用于抑制实际值。使用原始值会显着扭曲结果。
agazerboy,Sujit Pal 的博客文章详细描述了计算 TF 和 IDF。WRT验证结果,我建议你从一个小的语料库(比如100个文档)开始,这样你就可以很容易地看到你是否正确。对于 10000 个文档,使用 Lucene 开始看起来是一个非常合理的选择。