zoukankan      html  css  js  c++  java
  • 搜索引擎查询扩展

    查询扩展

    查询扩展的动机:提高召回率

    问题:考虑查询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] 

    作者:God bless you
    本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    注册表
    windows.location.href在IE6下停止工作
    LINUX配置IP的三种方式
    InnoSetup 打包代码 检测.netFramework
    SQLiteHelper
    黑马程序员_看视频记笔记_C#编程基础02
    通过注册表来检测是否安装Office
    SQLiteHelper
    TSQL
    IIS下发布关于Excel导入导出时遇到的问题集锦
  • 原文地址:https://www.cnblogs.com/god_bless_you/p/2700075.html
Copyright © 2011-2022 走看看