浏览 14693 次
该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2008-04-11
在Lucene中score简单说是由 tf * idf * boost * lengthNorm计算得出的。 tf:是查询的词在文档中出现的次数的平方根 idf:表示反转文档频率,观察了一下所有的文档都一样,所以那就没什么用处,不会起什么决定作用。 boost:激励因子,可以通过setBoost方法设置,需要说明的通过field和doc都可以设置,所设置的值会同时起作用 lengthNorm:是由搜索的field的长度决定了,越长文档的分值越低。 所以我们编程能够控制score的就是设置boost值。 还有个问题,为什么一次查询后最大的分值总是1.0呢? 因为Lucene会把计算后,最大分值超过1.0的分值作为分母,其他的文档的分值都除以这个最大值,计算出最终的得分。 下面用代码和运行结果来进行说明: public class ScoreSortTest { public final static String INDEX_STORE_PATH = "index"; public static void main(String[] args) throws Exception { IndexWriter writer = new IndexWriter(INDEX_STORE_PATH, new StandardAnalyzer(), true); writer.setUseCompoundFile(false); Document doc1 = new Document(); Document doc2 = new Document(); Document doc3 = new Document(); Field f1 = new Field("bookname","bc bc", Field.Store.YES, Field.Index.TOKENIZED); Field f2 = new Field("bookname","ab bc", Field.Store.YES, Field.Index.TOKENIZED); Field f3 = new Field("bookname","ab bc cd", Field.Store.YES, Field.Index.TOKENIZED); doc1.add(f1); doc2.add(f2); doc3.add(f3); writer.addDocument(doc1); writer.addDocument(doc2); writer.addDocument(doc3); writer.close(); IndexSearcher searcher = new IndexSearcher(INDEX_STORE_PATH); TermQuery q = new TermQuery(new Term("bookname", "bc")); q.setBoost(2f); Hits hits = searcher.search(q); for(int i=0; i<hits.length();i++){ Document doc = hits.doc(i); System.out.print(doc.get("bookname") + "\t\t"); System.out.println(hits.score(i)); System.out.println(searcher.explain(q, hits.id(i)));// } } } 运行结果: 引用 bc bc 0.629606
0.629606 = (MATCH) fieldWeight(bookname:bc in 0), product of: 1.4142135 = tf(termFreq(bookname:bc)=2) 0.71231794 = idf(docFreq=3, numDocs=3) 0.625 = fieldNorm(field=bookname, doc=0) ab bc 0.4451987 0.4451987 = (MATCH) fieldWeight(bookname:bc in 1), product of: 1.0 = tf(termFreq(bookname:bc)=1) 0.71231794 = idf(docFreq=3, numDocs=3) 0.625 = fieldNorm(field=bookname, doc=1) ab bc cd 0.35615897 0.35615897 = (MATCH) fieldWeight(bookname:bc in 2), product of: 1.0 = tf(termFreq(bookname:bc)=1) 0.71231794 = idf(docFreq=3, numDocs=3) 0.5 = fieldNorm(field=bookname, doc=2) 从结果中我们可以看到: bc bc文档中bc出现了2次,tf为2的平方根,所以是1.4142135。而其他的两个文档出现了一次,所以是1.0 所有的三个文档的idf值都是一样的,是0.71231794 默认情况下,boost的值都是1.0,所以lengthNorm就是当前的fieldNorm的值。前两个文档的长度一致,为0.625,而排在最后的文档,因为长度要长一些,所以分值要低,为0.5 现在对f2这个字段增加激励因子:f2.setBoost(2.0f); 运行结果变为: 引用 ab bc 0.8903974
0.8903974 = (MATCH) fieldWeight(bookname:bc in 1), product of: 1.0 = tf(termFreq(bookname:bc)=1) 0.71231794 = idf(docFreq=3, numDocs=3) 1.25 = fieldNorm(field=bookname, doc=1) 发现fieldNorm值有0.625变成了1.25,所以就是乘以了2.0 接下来再对第二个文档增加激励因子:doc2.setBoost(2.0f); 运行结果变为: 引用 ab bc 1.0
1.7807949 = (MATCH) fieldWeight(bookname:bc in 1), product of: 1.0 = tf(termFreq(bookname:bc)=1) 0.71231794 = idf(docFreq=3, numDocs=3) 2.5 = fieldNorm(field=bookname, doc=1) 发现fieldNorm又乘以了2,所以说对于Document和Field的setBoost都会乘到一起。 因为该文档的最终的score超过了1.0变成1.7807949,所以其他的两个文档的最终得分都要除以该值, 分别变成: 引用 bc bc 0.35355335
ab bc cd 0.19999999 相信通过上面的解释,大家就可以形象得理解Lucene的打分机制,同时也知道如何来改变文档的得分。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-04-13
grantbb 写道 在Lucene中score简单说是由 tf * idf * boost * lengthNorm计算得出的。 tf:是查询的词在文档中出现的次数的平方根 idf:表示反转文档频率,观察了一下所有的文档都一样,所以那就没什么用处,不会起什么决定作用。 boost:激励因子,可以通过setBoost方法设置,需要说明的通过field和doc都可以设置,所设置的值会同时起作用 lengthNorm:是由搜索的field的长度决定了,越长文档的分值越低。 太过简单了 - lucene不错,但是,包括另外一大堆的额外东西,距离作为商业或可用性的搜索引擎还是太远了。 |
|
返回顶楼 | |
发表时间:2008-04-13
我不知道楼上所说的商业应用是指什么呢?据我所知,很多大的互联网公司都在使用Lucene做搜索引擎的开发。
在Java领域,Lucene算是一个很不错的选择。 |
|
返回顶楼 | |
发表时间:2008-04-14
lot1 写道 grantbb 写道 在Lucene中score简单说是由 tf * idf * boost * lengthNorm计算得出的。 tf:是查询的词在文档中出现的次数的平方根 idf:表示反转文档频率,观察了一下所有的文档都一样,所以那就没什么用处,不会起什么决定作用。 boost:激励因子,可以通过setBoost方法设置,需要说明的通过field和doc都可以设置,所设置的值会同时起作用 lengthNorm:是由搜索的field的长度决定了,越长文档的分值越低。 太过简单了 - lucene不错,但是,包括另外一大堆的额外东西,距离作为商业或可用性的搜索引擎还是太远了。 恩,的确有点距离,但不敢苟同“太远”。至少我觉得现在距离还行把,有了些扩展。 任何开源到商业应用都需要定制,不同商业应用,不同级别规模也会产生出不一样的定制。商业的一般都有商业性限制,无法开源的。即便有开源,和实际使用还是有一定差距的。 可用性的搜索引擎,我觉得lucene应该达到了。很多大网站都用的是lucene,有些所谓的自己开发的,也是基于lucene而作的。 可能大家看待事物标准不同把,希望能听到你比较详细观点。 |
|
返回顶楼 | |
发表时间:2008-04-14
顶楼主一下。
很早就在做这块的实验了,lucene的score机制更面向与算法数据结构层面的,要设计业务层面的是另一套方式。主要在Document的建档和搜索关键字分词后的Query生成上下功夫,在这个方面来提高搜索结果的匹配度,要比通过对sroce的调整相对有效。 可惜一年前做搜索的时候没在这里建blog,现在要分享,还要花一定时间整理一下资料 |
|
返回顶楼 | |
发表时间:2008-10-15
Lucene计算相似度的score值哟可能<0.0f或是>1.0f吗?我最近在查询时出现了一个异常:Exception in thread "main" org.apache.lucene.queryParser.ParseException: Cannot parse '睿格总经理祝永进谈到,“大学生购买笔记本电脑的主流价格段是5000~6000元,3999没人买。甚至有44%的女大学生,购买了15寸的笔记本电脑,这让人感觉不可思议。”': Minimum similarity for a FuzzyQuery has to be between 0.0f and 1.0f !
at org.apache.lucene.queryParser.QueryParser.parse(QueryParser.java:149) 什么情况会导致score值不在0.0f与1.0f之间哪? |
|
返回顶楼 | |