Lucene评分机制

时间:2016-02-23 22:33:03

标签: lucene

我有3个产品名称,它们是

  1. Bounty Select-A-Size白色纸巾12 Mega Rolls
  2. Bounty Select-A-Size纸巾(12卷)
  3. Bounty Select-A-Size纸巾白色12 Mega Rolls
  4. 正如您所看到的,第1和第3项除了单词" White"的位置外是相同的。第二个词缺少" White"和" Mega"

    现在,当我运行以下代码时:

    public static void main(String[] args) throws IOException, ParseException {
        StandardAnalyzer analyzer = new StandardAnalyzer();
    
        // 1. create the index
        Directory index = new RAMDirectory();
    
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
    
        IndexWriter w = new IndexWriter(index, config);
        addDoc(w, "Bounty Select-A-Size White Paper Towels 12 Mega Rolls");
        addDoc(w, "Bounty Select-A-Size Paper Towels (12 rolls)");
        addDoc(w, "Bounty Select-A-Size Paper Towels White 12 Mega Rolls");
        w.close();
    
        // 2. query
        String querystr = "Bounty Select-A-Size White Paper Towels 12 Mega Rolls";
    
        Query q = new QueryParser("title", analyzer).parse(querystr);
    
        // 3. search
        IndexReader reader = DirectoryReader.open(index);
        IndexSearcher searcher = new IndexSearcher(reader);
        ScoreDoc[] hits = searcher.search(q, 4).scoreDocs;
    
        // 4. display results
        System.out.println("Found " + hits.length + " hits.");
        for(int i=0;i<hits.length;++i) {
            int docId = hits[i].doc;
            Document d = searcher.doc(docId);
            System.out.println((i + 1) + ". " + d.get("title") + "\t score " + hits[i].score);
        }
    
        reader.close();
    }
    
    private static void addDoc(IndexWriter w, String title) throws IOException {
        Document doc = new Document();
        doc.add(new TextField("title", title, Field.Store.YES));
        w.addDocument(doc);
    }
    

    结果是:

     1. Bounty Select-A-Size White Paper Towels 12 Mega Rolls    score 0.7363191
     2. Bounty Select-A-Size Paper Towels White 12 Mega Rolls    score 0.7363191
     3. Bounty Select-A-Size Paper Towels (12 rolls)     score 0.42395753
    

    到目前为止,这么好,前两个词的成分相同,所以得分相同。

    然而,当我扩展要搜索的术语数量时(相同的代码,但不是静态输入3,我从文件中获得了大约5000个),得分发生了变化。

     1. Bounty Select-A-Size White Paper Towels 12 Mega Rolls             4.1677103
     2. Bounty Select-A-Size Paper Towels (12 rolls)                     4.1677103
     3. Bounty Select-A-Size Paper Towels White 12 Mega Rolls            2.874553
    

    我的问题是:

    当数据集发生变化时,分数是否有可能以这种方式改变?

    若然,怎么样?

    如果没有,那么我知道我的代码中存在错误......

1 个答案:

答案 0 :(得分:1)

这完全正常,并且完全没有指示代码中的错误。

当索引内容发生变化时,分数可能会发生变化,即使这些变化似乎 与您的特定查询有很大关系。分数实际上仅在特定搜索执行的上下文中有效,因此它们的绝对值并不是真正重要的事情,但是这些值相对于查询的其他结果是有意义的。在两个结果集中,前两个得分相等,另一个显着降低。

此处更改的主要原因是idf (inverse document frequency)得分因素。这意味着权衡整个指数中不那么频繁出现的更严格的术语,这种想法就像一个常见的术语,如&#34;&#34;作为一个搜索结果,它不像一个不常见的那样,如#34; geronimo&#34;。

在你的情况下,你的最佳结果和第三个结果之间的比例已经缩小了一点,其余的语料库可用,所以它似乎是&#34; white&#34;和&#34; mega&#34;比查询中的其他一些术语更常见(因而也不那么有趣)。

附加说明:您可以使用Lucene的IndexSearcher.explain方法获取有关文档为何如此评分的详细信息:

System.out.println(searcher.explain(query, docNumber).toString());