Lucene fieldNorm相似度计算和查询时间值之间存在差异

时间:2013-02-28 12:43:56

标签: lucene indexing metrics

我试图理解如何计算fieldNorm(在索引时),然后在查询时使用(并且明显重新计算)。

在所有示例中,我使用的是StandardAnalyzer,没有停用词。

在索引内容时,对DefaultSimilarity的{​​{1}}方法进行了取消,我注意到它返回了2个特定文档:

    文件A(其字段中有4个令牌)
  • 0.5
  • 文件B的
  • 0.70710677(其字段中有2个令牌)

它通过使用公式来实现:

computeNorm

其中助力总是1

之后,当我查询这些文档时,我看到在查询说明中我得到了

    文件A的
  • state.getBoost() * ((float) (1.0 / Math.sqrt(numTerms)));
  • 文件B的
  • 0.5 = fieldNorm(field=titre, doc=0)

这已经很奇怪了(对我来说,我确定是我丢失了什么)。为什么我没有得到与索引时计算的字段规范相同的值?这是“查询规范化”的事情吗?如果是这样,它是如何工作的?

然而,这或多或少都可以,因为两个查询时间fieldNorms提供的顺序与索引时计算的顺序相同(具有较短值的字段在两种情况下都具有较高的fieldNorm)

然后我创建了自己的Similarity类,我已经实现了computeNorms方法,如下所示:

0.625 = fieldNorm(field=titre, doc=1)

在索引时我现在得到:

  • 1.5用于文档A(在其字段中有4个令牌)
  • 1.7071068,文件B(其领域有2个代币)

但是现在,当我查询这些文档时,我可以看到它们都具有与explain函数报告的相同的字段规范:

    文件A的
  • public float computeNorm(String pField, FieldInvertState state) { norm = (float) (state.getBoost() + (1.0d / Math.sqrt(state.getLength()))); return norm; }
  • 文件B的
  • 1.5 = fieldNorm(field=titre, doc=0)

对我来说,现在真的很奇怪,如果我在索引时使用一个明显好的相似度来计算fieldNorm,为什么会给我一个与令牌数量成正比的值,稍后在查询时,所有这些丢失了,查询sais两个文件都有相同的字段规范?

所以我的问题是:

  • 为什么Similarity的computeNorm方法报告的索引时间fieldNorm与查询解释报告的不一致?
  • 为什么,对于在索引时获得的两个不同的fieldNorm值(通过相似度computeNorm),我在查询时得到相同的fieldNorm值?

==更新

好的,我在Lucene's docs中找到了一些内容,澄清了我的一些问题,但并非全部问题:

但是,生成的标准值在存储之前被编码为单个字节。在搜索时,从索引目录中读取范数字节值并将其解码回浮点范数值。这种编码/解码虽然减小了索引大小,但却带来了精确丢失的代价 - 无法保证解码(encode(x))= x。例如,decode(encode(0.89))= 0.75。

有多少精度损失?我们应该在不同的值之间存在最小间隙,以便即使在精确损失重新计算之后它们仍然不同吗?

1 个答案:

答案 0 :(得分:4)

encodeNormValue的文档描述了编码步骤(精度丢失的地方),特别是值的最终表示:

  

编码使用三位尾数,五位指数和零指数点15,因此表示大约7x10 ^ 9到2x10 ^ -9的值,具有大约一个精确的十进制十进制数字。零也代表。负数向上舍入为零。值太大而无法表示的值向下舍入到最大可表示值。值太小而无法表示的正值会向上舍入到最小的正可表示值。

最相关的部分是要了解尾数只有3位,这意味着精度约为一个有效十进制数。

关于理由的重要说明是在你的报价结束之后的几句话,Lucene文档说:

  

支持规范值的这种有损压缩的基本原理是,鉴于用户通过查询表达其真实信息需求的困难(和不准确性),只有重大差异