Lucene 3.0 輸出類似度

http://www.cnblogs.com/ibook360/archive/2011/10/19/2217638.htmlhtml

 

Lucene3.0之結果排序(原理篇)
java

傳統上,人們將信息檢索系統返回結果的排序稱爲"相關排序" (relevance ranking) ,隱含其中各條目的順序反映結果和查詢的相關程度。 apache

一、 基本排序原理函數

     向量空間模型搜索引擎

Gerald Salton 等在 30 多年前提出的"向量空間模型" (Vector Space Model,VSM)[Salton and Lesk,1968, Salton,1971]。該模型的基礎是以下假設:文檔d和查詢q的相關性能夠由它們包含的共有詞彙狀況來刻畫。 spa

經典的TF*IDF詞項權重的計算公式: 設計

         給定某種權重的定量設計,求文檔和查詢的相關性就變成了求 d 和 q 向量的 3d

某種距離,最經常使用的是餘弦(cos)距離 htm

 

     連接分析PageRank原理對象

連接分析技術主要基於兩個假設:1)一個網頁被屢次引用,則它多是很重要的,若是被重要的網頁引用,說明自身也是重要的,網頁的重要性在網頁之間能夠傳遞。

2)隨機衝浪模型:認爲假定用戶一開始隨機地訪問網頁集合中的一個網頁,然和跟隨網頁的連接向前瀏覽網頁,不會退瀏覽,那麼瀏覽下一個網頁的機率是被瀏覽網頁的量化的重要程度值。

按照以上的用戶行爲模型,每一個網頁可能被訪問到的次數越多就越重要,這樣的"可能被訪問的次數"也就定義爲網頁的權值,PageRank值。如何計算這個權值呢?PageRank採用如下公式進行計算:

其中wj表明第j個網頁的權值;lij只取0、1值,表明從網頁i到網頁j是否存在連接;ni表明網頁i有多少個連向其它網頁的連接;d表明"隨機衝浪"中沿着連接訪問網頁的平均次數。選擇合適的初始數值,遞歸的使用上述公式,便可獲得理想的網頁權值。

二、 Lucene排序計算公式

Lucene的排序公式以下:

1),協調因子,表示文檔(d)中Term(t)出現的百分比,也就是計算查詢條件(q)中不一樣Term(t),以及在文檔中出現的數量之和,二者的數量之比。一般在文檔中出現查詢Term種類越多,分值越高。

2),調節因子,不影響索引排序狀況,只在檢索時使用,主要是用來讓排序結果在不一樣的查詢條件之間能夠比較。這個條件是在搜索時候計算。數值是根據每個查詢項權重的平方和計算獲得。計算公式以下:

            

3) ,文檔頻率,表示查詢詞中,每一個Term在對應的結果文檔中(d)中出現的次數。查詢詞出現的次數越多,表示出現頻率越高,文檔的檢索得分就越高。爲了不得到更大的相關性函數,實際中,使用次數的平方跟做爲文檔頻率tf的值,避免數值過分放大。

4) ,逆文檔頻率,檢索匹配文檔數量的反向函數。按照信息理論,文檔出現的次數越少,每一篇文檔的信息量就會越大。因此匹配的文檔數越少,得分就越高。而索引庫中文檔總數越多,找到一篇目標文檔難度越大,相應的信息量也會比較大。

5) ,長度因子,每一個索引詞彙在域中的整體長度決定的,這個參數在索引創建時肯定。數值根據文檔中實際具備的索引項個數肯定。檢索詞長度在文檔總長度中佔的比例越大,長度因子的數值也越大。

 

Lucene3.0之結果排序(操做篇)

 

一、 Lucene相關排序流程

二、 Lucene相關類

     Query類:一個抽象類,Lucene檢索結果最終評分的總控制中心。其它評分有關的類和對象都是由Query類來管理和生產。

     Weight類接口:定義Query權重計算的一個實現接口,能夠被重用。Weight類能夠用來生成Scorer類,也能夠解析評分的詳細信息,另外還定義了獲取Query權值的方法。

     Scorer類:Lucene評分機制的核心類。類的定義是抽象類,提供的一些抽象基本的計分功能方法提供全部的評分類實現,同時還定義了評分的詳細解析方法,Scorer類內部有一個Similarity對象,用來指明計算公式。

     Scorer類:Lucene類似度計算的核心抽象類。Similarity類主要處理評分計算,系統缺省使用類DefaultSimilarity類對象

三、 排序控制

使用Sort對象定製排序,經過改變文檔Boost值來改變排序結果以及使用自定義的Similarity方法更改排序

四、 文檔Boost加權排序

     Boost是指索引創建過程當中,給整篇文檔或者文檔的某一特定域設定的權值因子,在檢索時,優先返回分數高的。

Document和Field兩重Boosting參數。經過Document對象的setBoost()方法和Field對象的setBoost()方法。不一樣在於前者對文檔中每個域都修改了參數,然後者只針對指定域進行修改。

文檔加權=Document-boosting*Field-boosting,默認狀況下爲1,通常不作修改。

     Sort對象檢索排序

Sort使用時經過實例化對象做爲參數,經過Searcher類的search接口來實現。Sort支持的排序功能以文檔當中的域爲單位,經過這種方法,能夠實現一個或者多個不一樣域的多形式的值排序。

實際使用排序對象Sort進行排序。主要有兩種模式,一種是以字符串表示文檔域的名稱做爲參數指定域排序,一種是直接以排序域的包裝域的包裝類做爲參數進行排序。

Sort對象使用比較簡單,只須要在對文檔索引進行檢索時,在檢索器的Search方法中帶Sort對象做爲參數便可。

1)       Sort對象相關性排序

按照相關性排序時最基本的結果排序方法,使用Sort對象無參數構造函數完成的排序效果至關於Lucene默認的按相關性降序排序。

2)       Sort對象文檔編號排序

某些應用場合須要對全部符合匹配度的結果,按照文檔內部編號排序輸出。使用Sort對象的靜態實例Sort.INDEXORDER來實現

3)       Sort對象獨立域排序

在檢索過程當中,把檢索結果按照某一個特定域排 序,很是重要。在使用搜索引擎過程當中,有時會選擇使用時間排序,而在搜索引擎庫中,檢索詞徹底是另一個域的內容,與時間沒有任何關係。這種應用中,檢索 關鍵詞的匹配仍然是首要因素,匹配過低或者不匹配的文檔直接沒必要處理,而匹配的文檔則需進一步排序輸出。

    指定的排序域並無進行特別限制,能夠是檢索詞的關聯域,也能夠是文檔中的任意其它域。

4)       Sort對象聯合域排序

多個文檔域聯合排序時,須要注意文檔域的添加次序。排序的結果先按照第一個域排序,而後第二個域做爲次要關鍵字排序。開發時,須要根據本身的須要選擇合適的次序。

5)       Sort對象逆向排序

Sort(field,true)或者Sort(field,false)實現升降序排序。

 

Lucene3.0之結果排序(示例篇)

 

這個例子是根據《開發本身的搜索引擎:Lucene2.0+Heritrix》中的例子改的,因爲原書中是使用Lucene2.0,因此代碼有部分改動。

package sortApp;

import java.io.File;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

public class SortTest {
public static void makeItem(IndexWriter writer, String bookNumber,
    String bookName, String publishDate) throws Exception {
   writer.setUseCompoundFile(false);
   Document doc = new Document();
   Field f1 = new Field("bookNumber", bookNumber, Field.Store.YES,
     Field.Index.NOT_ANALYZED);
   Field f2 = new Field("bookName", bookName, Field.Store.YES,
     Field.Index.ANALYZED);
   Field f3 = new Field("publishDate", publishDate, Field.Store.YES,
     Field.Index.NOT_ANALYZED);
   doc.add(f1);
   doc.add(f2);
   doc.add(f3);
   writer.addDocument(doc);
}

public static void main(String[] args) {
   String Index_Store_Path = "D:/index/1";
   File file = new File(Index_Store_Path);

   try {
    Directory Index = FSDirectory.open(file);
    IndexWriter writer = new IndexWriter(Index, new StandardAnalyzer(Version.LUCENE_CURRENT), true,
      MaxFieldLength.LIMITED);
    writer.setUseCompoundFile(false);
   
    Document doc1 = new Document();
    Field f11 = new Field("bookNumber", "0000001", Field.Store.YES, Field.Index.NOT_ANALYZED);
    Field f12 = new Field("bookName", "鋼鐵是怎樣煉成的", Field.Store.YES, Field.Index.ANALYZED);
    Field f13 = new Field("publishDate", "1970-01-01", Field.Store.YES, Field.Index.NOT_ANALYZED);
    doc1.add(f11);
    doc1.add(f12);
    doc1.add(f13);
   
    Document doc2 = new Document();
    Field f21 = new Field("bookNumber", "0000002", Field.Store.YES, Field.Index.NOT_ANALYZED);
    Field f22 = new Field("bookName", "鋼鐵戰士", Field.Store.YES, Field.Index.ANALYZED);
    Field f23 = new Field("publishDate", "1970-01-01", Field.Store.YES, Field.Index.NOT_ANALYZED);
    doc2.add(f21);
    doc2.add(f22);
    doc2.add(f23);
   
    Document doc3 = new Document();
    Field f31 = new Field("bookNumber", "0000003", Field.Store.YES, Field.Index.NOT_ANALYZED);
    Field f32 = new Field("bookName", "籬笆女人和狗", Field.Store.YES, Field.Index.ANALYZED);
    Field f33 = new Field("publishDate", "1970-01-01", Field.Store.YES, Field.Index.NOT_ANALYZED);
    doc3.add(f31);
    doc3.add(f32);
    doc3.add(f33);
   
    Document doc4 = new Document();
    Field f41 = new Field("bookNumber", "0000004", Field.Store.YES, Field.Index.NOT_ANALYZED);
    Field f42 = new Field("bookName", "女人是水作的", Field.Store.YES, Field.Index.ANALYZED);
    Field f43 = new Field("publishDate", "1970-01-01", Field.Store.YES, Field.Index.NOT_ANALYZED);
    doc4.add(f41);
    doc4.add(f42);
    doc4.add(f43);
   
    Document doc5 = new Document();
    Field f51 = new Field("bookNumber", "0000005", Field.Store.YES, Field.Index.NOT_ANALYZED);
    Field f52 = new Field("bookName", "英雄兒女", Field.Store.YES, Field.Index.ANALYZED);
    Field f53 = new Field("publishDate", "1970-01-01", Field.Store.YES, Field.Index.NOT_ANALYZED);
    doc5.add(f51);
    doc5.add(f52);
    doc5.add(f53);
   
    Document doc6 = new Document();
    Field f61 = new Field("bookNumber", "0000006", Field.Store.YES, Field.Index.NOT_ANALYZED);
    Field f62 = new Field("bookName", "白毛女", Field.Store.YES, Field.Index.ANALYZED);
    Field f63 = new Field("publishDate", "1970-01-01", Field.Store.YES, Field.Index.NOT_ANALYZED);
    doc6.add(f61);
    doc6.add(f62);
    doc6.add(f63);
   
    Document doc7 = new Document();
    Field f71 = new Field("bookNumber", "0000007", Field.Store.YES, Field.Index.NOT_ANALYZED);
    Field f72 = new Field("bookName", "個人兄弟和女兒", Field.Store.YES, Field.Index.ANALYZED);
    Field f73 = new Field("publishDate", "1970-01-01", Field.Store.YES, Field.Index.NOT_ANALYZED);
    doc7.add(f71);
    doc7.add(f72);
    doc7.add(f73);
   
    writer.addDocument(doc1);
    writer.addDocument(doc2);
    writer.addDocument(doc3);
    writer.addDocument(doc4);
    writer.addDocument(doc5);
    writer.addDocument(doc6);
    writer.addDocument(doc7);
    writer.optimize();
    writer.close();
    IndexSearcher searcher = new IndexSearcher(Index);
    TermQuery q = new TermQuery(new Term("bookName", ""));   
    ScoreDoc[] hits = searcher.search(q, null, 1000, Sort.RELEVANCE).scoreDocs;
    for (int i = 0; i < hits.length; i++) {
     Document hitDoc = searcher.doc(hits[i].doc);
     System.out.print("書名");
     System.out.println(hitDoc.get("bookName"));
     System.out.print("得分");
     System.out.println(hits[i].score);
     System.out.print("內部ID ");
     System.out.println(hits[i].doc);
     System.out.print("書號");
     System.out.println(hitDoc.get("bookNumber"));
     System.out.print("發行日期");
     System.out.println(hitDoc.get("publishDate"));
    }
   } catch (Exception e) {
    e.printStackTrace();
   }
}
}
運行結果:

Sort屬性設爲RELEVANCE

Sort屬性設爲INDEXORDE


去除Sort參數後:

相關文章
相關標籤/搜索