【问题标题】:Problem with Lucene scoringLucene评分问题
【发布时间】:2010-12-13 00:20:25
【问题描述】:

我对 Lucene 的评分功能有疑问,我无法弄清楚。到目前为止,我已经能够编写这段代码来重现它。

package lucenebug;

import java.util.Arrays;
import java.util.List;

import org.apache.lucene.analysis.SimpleAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;

public class Test {
    private static final String TMP_LUCENEBUG_INDEX = "/tmp/lucenebug_index";

    public static void main(String[] args) throws Throwable {
        SimpleAnalyzer analyzer = new SimpleAnalyzer();
        IndexWriter w = new IndexWriter(TMP_LUCENEBUG_INDEX, analyzer, true);
        List<String> names = Arrays
                .asList(new String[] { "the rolling stones",
                        "rolling stones (karaoke)",
                        "the rolling stones tribute",
                        "rolling stones tribute band",
                        "karaoke - the rolling stones" });
        try {
            for (String name : names) {
                System.out.println("#name: " + name);
                Document doc = new Document();
                doc.add(new Field("name", name, Field.Store.YES,
                        Field.Index.TOKENIZED));
                w.addDocument(doc);
            }
            System.out.println("finished adding docs, total size: "
                    + w.docCount());

        } finally {
            w.close();
        }

        IndexSearcher s = new IndexSearcher(TMP_LUCENEBUG_INDEX);
        QueryParser p = new QueryParser("name", analyzer);
        Query q = p.parse("name:(rolling stones)");
        System.out.println("--------\nquery: " + q);

        TopDocs topdocs = s.search(q, null, 10);
        for (ScoreDoc sd : topdocs.scoreDocs) {
            System.out.println("" + sd.score + "\t"
                    + s.doc(sd.doc).getField("name").stringValue());
        }
    }
}

我运行它得到的输出是:

finished adding docs, total size: 5
--------
query: name:rolling name:stones
0.578186    the rolling stones
0.578186    rolling stones (karaoke)
0.578186    the rolling stones tribute
0.578186    rolling stones tribute band
0.578186    karaoke - the rolling stones

我只是不明白为什么the rolling stonesthe rolling stones tribute 具有相同的相关性。根据lucene的documentation,一个字段的token越多,归一化因子越小,因此the rolling stones tribute的得分应该低于the rolling stones

有什么想法吗?

【问题讨论】:

  • 您使用的是哪个 Lucene 版本(您链接了 2.4 的 API 文档)?在 Lucene 2.9 中,默认不返回分数,你必须提供一个 TopFieldCollector:gossamer-threads.com/lists/lucene/java-user/86309
  • @gossamer:我已经针对 Lucene 2.3、2.4 和 2.9 运行了相同的代码。结果相同。

标签: lucene information-retrieval scoring


【解决方案1】:

我可以在 Lucene 2.3.1 上重现它,但不知道为什么会这样。

【讨论】:

    【解决方案2】:

    长度归一化因子计算为1 / sqrt(numTerms)(你可以在DefaultSimilarity看到这个

    此结果不直接存储在索引中。此值乘以指定字段的提升值。最终结果然后按照Similarity.encodeNorm() 中的说明以 8 位编码。这是一种有损编码,这意味着细节会丢失。

    如果您想查看实际的长度标准化,请尝试使用以下句子创建文档。

    the rolling stones tribute a b c d e f g h i j k 
    

    这将在您可以看到的长度标准化值中产生足够的差异。

    现在,如果根据您使用的示例,您的字段的标记很少,您可以根据自己的公式为文档/字段设置提升值,这对于短字段来说本质上是更高的提升。或者,您可以创建自定义相似度并覆盖 legthNorm() 方法。

    【讨论】:

    • 没错,8 位编码将boost*lengthNorm 向上取整并导致问题。在索引期间将字段提升设置为 100 对我来说是一个足够干净的解决方法。 @Shashikant Kore 谢谢!
    猜你喜欢
    • 2015-04-12
    • 1970-01-01
    • 2011-04-04
    • 2010-09-05
    • 2019-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-12
    相关资源
    最近更新 更多