查询向量(query vector)与搜索出来的文档向量(document vector) 形成N个夹角,计算q 和d 之间的夹角,最小的 就是相
似度最高的。
看下lucene的打分公式:
tf: 一个term在一个文档中出现的次数
idf:一个term在多少个文档中出现过
t.getBoost:lucene自有的权重配置,默认为1
norm:字段标准化。
在Lucene中score简单说是由 tf * idf * boost * norm 计算得出的。
代码实现,必要时可以重写代码。在Lucene的DefaultSimilarity类
1:协调coord(q,d)
@Override public float coord(int overlap, int maxOverlap) { return overlap / (float)maxOverlap; }
/** Implemented as <code>1/sqrt(sumOfSquaredWeights)</code>. */ @Override public float queryNorm(float sumOfSquaredWeights) { return (float)(1.0 / Math.sqrt(sumOfSquaredWeights)); }
函数图:
只在商品名称中出现了1次。。他的tf =1
Math.sqrt 取平方根 Math.sqrt(9)=3.0
@Override public float tf(float freq) { return (float)Math.sqrt(freq); }
numDocs 总文档数 docFreq 在多少文档中出现过
如果搜索“笔记本” ,总文档有1000个 ,,出现100次。。那么idf=2
如果出现10次 那么其idf =3
idf 越高、在总文档数中 该词出现的频率越低
5:t.getBoost() 权重
6:norm(t,d) 标准化
对term和文档的字段长度进行标准化计算 ,如果字段的长度越长,那么该值越低。
@Override public float lengthNorm(FieldInvertState state) { final int numTerms; if (discountOverlaps) numTerms = state.getLength() - state.getNumOverlap(); else numTerms = state.getLength(); return state.getBoost() * ((float) (1.0 / Math.sqrt(numTerms))); }