Lucene计算平均期限频率

时间:2017-12-09 22:50:48

标签: solr lucene similarity information-retrieval tf-idf

我目前正在根据以下BM25 similarity对Lucene的标准paper进行修改。实际公式的实现很简单,但我正在努力计算必要的统计数据。

我需要以下两个统计数据:

  • 文档的平均字词频率length of document / # unique terms of the document,(即文件重复性的指标 - 对于没有重复的文件,这将是1,每个术语发生两次,它将是2,依此类推)
  • 平均平均频率:这是对集合所有文档的上述度量的算术平均值。这可以看作是整个语料库的平均重复性。

我发现,我可以通过覆盖我的Similarity实现的computeNorm方法来计算索引时的每文档平均术语频率。我可以通过位操作将值与标准值一起存储(不是特别漂亮,但到目前为止它有效)。在查询时,我可以提取文档的平均术语频率和长度。

然而,这无助于找到平均平均词频。它显然是一个集合范围的值,因此据我所知,应该在Similarity.computeWeight中计算,但我不知道如何根据函数的参数来完成这项工作。

哪个是计算这些统计数据的理想位置?

我是Lucene的新手,所以可能有一个我尚未看到的明显解决方案。我很感激任何意见。

2 个答案:

答案 0 :(得分:0)

Similarity.computeWeight方法包含CollectionStatistics param,其中包含maxDoc(返回文档总数,无论它们是否都包含此字段的值),以及TermStatistics ,其中包含termtotalTermFreq(返回此术语的总出现次数),除以它,您可以得到平均词频

答案 1 :(得分:0)

您需要计算自己的"规范"坚持Lucene的索引。基本上,您可以使用NumericDocValuesField存储要在评分中使用的其他功能。

这意味着,在索引时,您希望自己对文本进行标记。我有一些示例代码,(在Kotlin中,但如果您更喜欢Java,我很乐意回答后续问题)

基于任何Lucene分析器的Tokenize :(表示为Kotlin扩展函数,假设this是这个静态方法作为分析器的第一个参数,如果你在Java中更舒服的话。

fun Analyzer.tokenize(field: String, input: String): List<String> {
    val tokens = arrayListOf<String>()
    this.tokenStream(field, input).use { body ->
        val charTermAttr = body.addAttribute(CharTermAttribute::class.java)

        // iterate over tokenized field:
        body.reset()
        while(body.incrementToken()) {
            tokens.add(charTermAttr.toString())
        }
    }
    return tokens
}

然后您获取标记化文本,并根据它计算您需要的信息。我使用的代码希望它们分开,但是这样的东西应该让你去。

    fun setTextField(field: String, text: String, terms: List<String>): List<IndexableField> {
        val length = terms.size
        val uniqLength = terms.toSet().size

        val keep = ArrayList<IndexableField>()
        keep.add(TextField(field, text, Field.Store.YES))
        keep.add(NumericDocValuesField("lengths:$field", length.toLong()))
        keep.add(NumericDocValuesField("unique:$field", uniqLength.toLong()))
        return keep
    }

这是每个文档的统计信息,因此您可以在索引时跟踪平均值并将其与Lucene分开存储,即我通常创建一个&#34; meta.json&#34;靠近这些事物的指数。

我不熟悉SOLR本身,但是当您在Lucene中实现Weight子类时,您可以访问以下数字doc值:

class SpecialBM25(...) : Weight(...) {
    ...
    override fun scorer(context: LeafReaderContext): Scorer {
        val uniq = context.reader().getNumericDocValues("unique:$field")
        val lengths = context.reader().getNumericDocValues("lengths:$field")
        ... generate Scorer and give it your additional features ...
    }
}