在lucene的ranking算法中使用Language Model

 

最近,网体作业要求改进Lucene的ranking算法,我使用了语言模型来进行改进,下面都是我个人的想法,很多地方还不成熟。

Lucenceranking算法是基于VSM模型的,把文档和查询表示成向量空间模型中的向量,通过计算向量之间的余弦值来给文档排序。在这里,ranking算法使用Language Model来替代

1Language Model的思想

query的产生当作一个随机过程,每个文档看成是一个语言模型生成的,估计每个文档模型产生这个query的概率,根据这个概率对文档排序。概率公式如下:

P(Q,d)=p(d)p(Q|d)p(d)p(Q|Md)

因为p(d)=1/|doc|,每个doc的概率都相同,所以可以省略。

p(Q|Md)用最大似然估计,p(Q|Md)=  ,其中tf(t,d)表示term t在文档d中出现的次数, 表示文档d中总词数。

因为数据不足可能出现tf(t,d)=0导致概率为0,因此采用文档多项式分布和集合多项式分布的混合模型,

所以,最后得到计算公式p(Q|Md)=

2、代码修改

         tf(t,d)VSM中已经计算,可以直接用,主要需要计算

(1)       Lucene的搜索排序主要在IndexSearch.search()方法里完成。在search方法中,调用Weight.scorer()得到一个Scorer,然后调用Scorerscore方法,就完成了排序。因此,我们的代码修改主要在Weight.scorer()Scorer.score()中。

(2)       得到

这是整个改进过程中最麻烦的地方,因为VSM中没有用到文档的词数,在一番搜索之后,我发现TermFreqVector中存储了每个term的频率,只要把它相加就是文档的词数。但是调用了indexReader.getTermFreqVectors()得到的却是null,也就是说建索引的时候没有构造TermFreqVector。在Google论坛上求助无果之后,我开始分析索引代码,打算在建索引的时候统计出文档的词数。代码如下:

FieldInvertState的字段length是一个字段的所有词数,通过它也可以统计出一个文档的总次数。但是需要修改索引的代码,还涉及到读写磁盘,修改的代码量比较大。就在这时,Google论坛上有同学介绍了TermFreqVector的使用方法,非常感谢这位同学,使用了TermFreqVector后,只需要修改几十行代码就可以实现语言模型。Lucene默认建索引时不构造TermFreqVector,需要在添加Fielddocument里时,添加Field.TermVcoter.YES参数,这样就可以使用TermFreqVector了。

 

int doclen=0;

       TermFreqVector[] termF;

        try {

               termF = reader.getTermFreqVectors(doc);         

               for(int i=0;i<termF.length;i++)

               {

                    int fre[]=termF[i].getTermFrequencies();

                    for(int j=0;j<fre.length;j++)             doclen+=fre[j];

               }

         } catch (IOException e) {

                   e.printStackTrace();

}

(3)       计算

在检索一开始,计算所有文档的词数。代码如下

       int collSize = 0;

    TermFreqVector[] termF;

       for (int doc = 0; doc < reader.maxDoc(); ++doc) {

                   collSize+=getDocLength(doc);

}

getDocLength()就是上面的得到文档次数的方法。

得到文档的词数之后,还需要把它传给排序的函数。我在Query中加了一个字段collLength,通过set函数把所有文档的词数传进去,排序时再通过get方法得到。

(4)       计算 tf(t,c)

遍历包含该term的所有文档,把term在每个文档中的频率加起来,代码如下:

TermDocs termDocs = reader.termDocs(term);

int tfColl= termDocs.freq();

       while (termDocs.next()) {

          tfColl += termDocs.freq();

      }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值