搜索引擎查詢擴展


查詢擴展

查詢擴展的動機:提高召回率

問題:考慮查詢q: [aircraft],某篇文檔d包含“plane”, 但是不包含“aircraft”,顯然對於查詢q,一個簡單的IR系統不會返回文檔d,即使d是和q最相關的文檔。我們試圖改變這種做法:也就是說,我們會返回不包含查詢詞項的相關文檔。

方法:不考慮查詢(即與查詢無關)及其返回文檔情況下對初始查詢進行擴展和重構,即進行一次性的全局分析(比如分析整個文檔集)來產生同/近義詞詞典。(對於查詢q: [aircraft],查詢擴展為[aircraft、plane])。

注:對於查詢中的每個查詢詞項t,可以通過在詞典中找出t 的同義詞或者相關詞對查詢進行自動擴展。同義詞詞典的使用可以與詞項的權重計算相結合,比如對增加的查詢詞項賦予一個低於原始查詢詞項的權重。

 

詞典生成方法

人工構建的同(近)義詞詞典(人工編輯人員維護的詞典)

自動導出的同(近)義詞詞典(比如,基於詞語的共現統計信息)
基於查詢日志挖掘出的查詢等價類(Web上很普遍)

 

同義詞詞典的自動構建

人工構建同義詞詞典的代價很大,一種取代思路是通過分析文檔集來自動構造這種詞典,讓機器來構造詞典。

 

通過分析文檔集中的詞項分布來自動生成同(近)義詞詞典,基本的想法是計算詞語之間的相似度。

基於詞的共現信息: 如果兩個詞各自的上下文共現詞類似,那么它們類似
例子:“car” ≈ “motorcycle” ,因為它們都與“road”、“gas” 及“license”之類的詞共現,因此它們類似。

 

基於語法關系: 兩個詞,如果它們同某些一樣的詞具有某種給定的語法關系的話,那么它們類似

比如,我們可以認為可生長、可烹調、可取食和可消化的實體很可能是食品, 因此蘋果和梨肯定彼此類似

 

簡單地采用詞共現信息更具魯棒性(它不可能會產生語法分析器出錯所導致的錯誤),但是采用語法關系有可能會更精確。

 

搜索引擎中的查詢擴展

搜索引擎進行查詢擴展主要依賴的資源:查詢日志(query log)
例1: 提交查詢[herbs] (草葯)后,用戶常常搜索[herbal remedies] (草本療法) → “herbal remedies” 是“herb”的潛在擴展查詢
例2: 用戶搜索[flower pix] 時常常點擊URL photobucket.com/flower,而用戶搜索[flower clipart]常常點擊同樣的URL→ “flower clipart”和“flower pix” 可能互為擴展查詢

 

Lucene中同義詞分析器的簡單實現

回顧Lucene的分析過程,自定義同義詞分析器主要注意兩點:

1. 構建自定義的分析器鏈(analyzer chain)

2. PositionIncrementAttribute設置為0,0增量表示詞項與前一詞項之間是同義詞

 

代碼實現

SynonymAnalyzer 

//自定義同義詞Analyzer

public class SynonymAnalyzer extends Analyzer {

private SynonymEngine engine ;

public SynonymAnalyzer(SynonymEngine engine) {

this.engine = engine;

      }

@Override

//LetterTokenizer->LowerCaseFilter->StopFilter->SynonymFilter分析器鏈

public TokenStream tokenStream(String fieldName, Reader reader) {

            TokenStream result = new SynonymFilter(

new StopFilter(Version.LUCENE_36,

new LowerCaseFilter(Version.LUCENE_36,

new LetterTokenizer(Version.LUCENE_36, reader)),

                             StopAnalyzer. ENGLISH_STOP_WORDS_SET), engine );

return result;

      }

}

 

SynonymEngine

//獲得同義詞列表接口
public interface SynonymEngine {
    String[] getSynonyms(String s) throws IOException;
}
 

SimpleSynonymEngine 

//硬編碼同義詞列表

public class SimpleSynonymEngine implements SynonymEngine {

private static HashMap<String, String[]> map = new HashMap<String, String[]>();

static {

map.put( "quick", new String[] {"fast", "speedy"});

map.put( "jumps", new String[] {"leaps", "hops"});

map.put( "over", new String[] {"above"});

map.put( "lazy", new String[] {"apathetic", "sluggish"});

map.put( "dog", new String[] {"canine", "pooch"});

  }

public String[] getSynonyms(String s) {

return map.get(s);

  }

}

 

SynonymFilter

//自定義同義詞TokenFilter

public class SynonymFilter extends TokenFilter {

public static final String TOKEN_TYPE_SYNONYM = "SYNONYM";

private Stack<String> synonymStack ;

private SynonymEngine engine ;

private AttributeSource.State current;

private final CharTermAttribute termAtt;

private final PositionIncrementAttribute posIncrAtt;

public SynonymFilter(TokenStream in, SynonymEngine engine) {

    super(in);

    synonymStack = new Stack<String>();

    this.engine = engine;

    this.termAtt = addAttribute(CharTermAttribute.class);

    this.posIncrAtt = addAttribute(PositionIncrementAttribute.class);

}

public boolean incrementToken() throws IOException {

    if (synonymStack .size() > 0) {

        char[] syn = synonymStack .pop().toCharArray();

        termAtt.copyBuffer(syn, 0, syn.length );

        //同義詞位置增量設為0

        posIncrAtt.setPositionIncrement(0);

        return true ;

        }

        if (!input .incrementToken())

            return false ;

        addAliasesToStack();

        return true ;

}

private String getTerm(CharTermAttribute term) {

    return new String(term.buffer(), 0, term.length());

}

private boolean addAliasesToStack() throws IOException {

    String[] synonyms = engine.getSynonyms(getTerm(termAtt ));

    if (synonyms == null) {

        return false ;

    }

    for (String synonym : synonyms) {

        synonymStack.push(synonym);

    }

    return true ;

}

}

 

SynonymAnalyzer測試

 

public static void main(String[] args) throws IOException {

    SynonymEngine engine = new SimpleSynonymEngine();

    AnalyzerUtils. displayTokensWithFullDetails(new SynonymAnalyzer(engine),

"The quick brown fox jumps over the lazy dog" );

}

 

結果輸出

2: [quick:4->9:word] [speedy:4->9:word] [fast:4->9:word]

3: [brown:10->15:word]

4: [fox:16->19:word]

5: [jumps:20->25:word] [hops:20->25:word] [leaps:20->25:word]

6: [over:26->30:word] [above:26->30:word]

8: [lazy:35->39:word] [sluggish:35->39:word] [apathetic:35->39:word]

9: [dog:40->43:word] [pooch:40->43:word] [canine:40->43:word] 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM