搜索相关性算分
本文尝试描述搜索相关性算分的基本原理,并介绍在信息检索领域中最重要的发明:TF-IDF经典算法。 本节内容分为两部分:
- 第一部分介绍倒排索引形成的基本过程以及其基本形态;
- 第二部分介绍搜索相关性算分经典理论: TF-IDF理论
倒排索引
倒排索引又被称为反向索引,它记录了一个词(term)和文本的映射关系,在文本搜索中,通过倒排索引能够快速检索包含某些词的文本。 本节内容并不打算去详细讲解倒排索引的含义,我们假设读者对倒排索引已经有一定了解。
从之前的关于analyzer的介绍理解Elasticsearch 分析器 一节中,我们知道,文本内容经过 char_filter, tokenizer, token filter处理之后,形成一个term集合。为了满足特定的业务需求提升搜索精确率,我们可以自定义自己的analyzer。
假设现在有三个文本文件,里面的内容分别如下:
- Lucen is a powerful lib for fulltext search wrote by java.
- Elasticsearch is a distributed search and data statistics engine based on lucene.
- The author of hadoop and lucene is 'Doung Cutting'.
现在,我们假设通过自定义的analyzer,分别对下面三个句子进行处理,最后我们得到三个term集合:
| 文档id | term集合 |
|---|---|
| 1 | "luence", "search" |
| 2 | "elasticsearch", "search" , "lucene" |
| 3 | "hadoop","lucene" |
然后,我们将上面的表格进行翻转成下面的表格形式:
| term | 出现的文档 id |
|---|---|
| lucene | 1 |
| search | 1 |
| elasticsearch | 2 |
| search | 2 |
| lucene | 2 |
| hadoop | 3 |
| lucene | 3 |
最后,我们将上面的表格进行合并,并且按照term的正排序,得出下面的表格:
| term | 文档id列表 |
|---|---|
| elasticsearch | 2 |
| hadoop | 3 |
| lucene | 1,2,3 |
| search | 1,2 |
我们将上面的表格通过下图来表达:
其中:
- 橙色部分的document frequency字段 : 表示这个词在多少个文档中出现过,习惯被翻译为 文档频率,简称 DF
- 青色部分的frequency字段:表示一个词在该文档中出现过的次数,习惯被翻译为 词频(term frequency on per document),简称 TF
上图就是倒排索引的基本形态,可能在不同的搜索引擎中,技术上其倒排索引的存储格式会不一样,但是这不碍于我们去理解其基本原理以及建立倒排索引的基本过程。
现在,如果我们想知道哪些文件的文本内容包含了单词 elasticsearch,只需要从倒排索引中找到 elasticsearch这个term,取出起倒排链表(青色部分),即是检索的结果。
TF-IDF 经典理论
上一节倒排索引中,我们了解到两个重要的概念: TF & DF
不难知道,他们分别有以下特点:
- TF : TF 的值越大,表示其在文档中重要程度越高,每个词在每个document中都有一个TF值。
- DF: DF的值越大,表示它在越多的文本中出现过,其重要性就越低。
根据文档频率,我们引出一个重要的概念:
- IDF: IDF源自于DF,称为 逆文档频率。
IDF的计算公式可以表示为:
IDF(term) = log( all_doc_count / match_doc_count )
match_doc_count : 表示匹配上关键词的文档数 all_doc_count: 表示总文档数
显然,搜索过程中输入的词语其IDF的值越高越好,因为IDF表示了其稀有性,越高表示越稀有。
以上面倒排索引一节的例子,列举出每个term的TF,DF,IDF
| Term | TF1 | TF2 | TF3 | DF | IDF | 总文档数 |
|---|---|---|---|---|---|---|
| elasticsearch | 0 | 1 | 0 | 1 | log(3/1) | 3 |
| hadoop | 0 | 0 | 1 | 1 | log(3/1) | 3 |
| lucene | 1 | 1 | 1 | 3 | log(3/3)=0 | 3 |
| search | 1 | 1 | 0 | 2 | log(3/2) | 3 |
然后我们引入TF-IDF 经典算法的基本形态,可以表示为:
上面公式表示在一条搜索查询中,一个文档的相关性算分。一条查询会有多个term,分别对每个term应用IF-IDF理论进行求值,然后对所有的term的得分加权求和(boost因子表示每个term的权重),最后得到每个文档的得分,最后按照得分倒排序并且返回相关性 TopN结果。
!!!需要注意的是,上面的公式只是一个基本的形态,并不代表真正的,唯一的相关性计算公式。实际上不同的搜索引擎肯定会对上面的公式进行改造优化,比如引入文本长度作为一个影响因子,文本越短,表示该term越重要。
以上面的表格数据为例,假设现在需要搜索关键词 "elasticsearch OR lucene",返回相关性最高的一条文档,设定boost=1,也就是输入的每个term重要性都是相等的,那么根据上面的公式,可以知道每个文档和搜索条件的相关性得分。 下面表格描述了计算的过程:
| 文档id | 计算过程 | 相关性得分 |
|---|---|---|
| 1 | score = [ 0 * log(3) * log(3) * 1 ] + [ 1 * 0 * 0 * 1] | 0 |
| 2 | score = [ 1 * log(3) * log(3) * 1 ] + [ 1 * 0 * 0 * 1 ] | 0.228 |
| 3 | score = [ 0 * log(3) * log(3) * 1 ] + [ 1 * 0 * 0 * 1 ] | 0 |
最后,我们得到分数最好的文档是2,相关性分数为 0.228
从上面的计算过程,我们可以发现1个事实: lucene这个词因为在每个文档中都出现了,所以 Lucene这个关键词的贡献分数为0。这也是我们在处理文本数据的时候需要去掉停用词的原因。
总结:
- 倒排索引保存了 词-->文档 的映射关系,能够帮助我们快速实现文本查找。
- TF 表示一个词在一段文本中出现的频率,也叫词频。TF越高,表明该词语在文本中的重要性越高。
- IDF 表示逆文档频率,计算范围是全部的文档。IDF越高,表示该词在全部的文档中越稀缺,重要性越高。
- 经典TF-IDF理论基本思路是对每个词的 TF和IDF 进行加权求和算出每个文档的相关性得分,并将topN结果返回给用户。