标准化 TF-IDF 结果

问题描述 投票:0回答:2

我想规范化从这个给定代码中获得的 tfidf 结果:

for (int docNum = 0; docNum < ir.numDocs(); docNum++) {
            TermFreqVector tfv = ir.getTermFreqVector(docNum, "contents");
            if (tfv == null) {
                // ignore empty fields
                continue;
            }
            String[] tterms = tfv.getTerms();
            int termCount = tterms.length;
            int[] freqs = tfv.getTermFrequencies();
            for (int t = 0; t < termCount; t++) {
                double idf = ir.numDocs() / ir.docFreq(new Term("contents", tterms[t]));
                System.out.println(" " + tterms[t] + " " + freqs[t]*Math.log(idf));
            }
        }

此代码的输出是:

area 0.0
areola 5.877735781779639
ari 3.9318256327243257
art 1.6094379124341003
artifici 1.0986122886681098
assign 2.1972245773362196
associ 3.295836866004329
assur 1.9459101490553132
averag 1.0986122886681098
avoid 0.6931471805599453
.
.
.

任何帮助将不胜感激。谢谢你

normalization normalize tf-idf
2个回答
10
投票

一种常见的方法是按文档大小进行标准化。即,您可以使用相对频率,而不是使用术语计数(或绝对频率)。

freqsum
为频率数组的总和。然后使用

freqs[t]/(double)freqsum*Math.log(idf)

为了避免这种类型的混淆,我建议使用术语:

  • 术语计数“绝对频率”
  • 文档中单词比率的相对频率
而不是模棱两可的术语“

术语频率”。

我知道,从历史上看,如果您查找 Salton,Yang,关于自动索引中术语值的规范(1973),它们指的是绝对计数。余弦相似度将消除比例,所以无论如何,这并不重要。像 Lucene 这样的现代系统会尝试更好地控制文档的影响。


0
投票
通过“归一化”,我假设您希望每个 TFIDF 值的范围在 0 到 1 之间。 然而,如何进行标准化取决于您想要实现的目标。

一种选择是找到所有文档中最大的 tfidf 值(Tmax,其中 T 是 TFIDF),并分别减去每个 TFIDF 值(Tnorm = Tmax - T)。这会导致优先级倒置,得分最小者获胜。您可以通过将 Tnorm 取为 1 - (Tmax - T) = T - Tmax + 1 来反转它,这将表现为正常的 TFIDF 评分,并且范围仍然为 0 到 1。

但是,有时在每个文档级别上进行标准化更方便,在这种情况下,您可以获得文档中 TFIDF 值的总和,并将每个 TFIDF 除以该总和。在这种情况下,最高分仍然获胜,具体取决于您的用例。

在每个文档级别在我的用例中更有用,这涉及对查询进行评分以识别文档。我在 0 和 1 之间进行归一化,以便 TF 和 TFIDF 处于相同的范围内,并且当分母小于或大于分子时,将两个随机分数相乘不会产生有时降低有时增加乘积的风险。

© www.soinside.com 2019 - 2024. All rights reserved.