elasticsearch打分機制


一、 文檔打分的運作機制:TF-IDF

1、Lucenees的打分機制是一個公式,將查詢作為輸入,使用不同的手段來確定每一篇文檔的得分,將每一個因素最后通過公式綜合起來,返回該文檔的最終得分,這個綜合考量的過程,就是希望相關的文檔被優先返回的考量過程,在Lucenees中這種相關性稱為得分

2、 在開始計算得分之前,es使用了被搜索詞條的頻率和它有多常見來影響得分,從兩個方面理解

①一個詞條在某篇文檔中出現的次數越多,該文檔就越相關,稱之為詞頻(term frequency),TF

②一個詞條如果在不同的文檔中出現的次數越多,它就越不相關,稱之為逆文檔頻率(inverse document frequency),IDF

3、詞頻:TF,考慮一篇文檔得分的首要方式,是查看一個詞條在文檔中出現的次數,比如某篇文章圍繞es的打分展開的,那么文章中肯定會多次出現相關字眼,當查詢時,我們認為該篇文檔更符合,所以,這篇文檔的得分會更高

4、逆文檔頻率:IDF

①相對於詞頻,逆文檔頻率稍顯復雜,如果一個詞條在索引中的不同文檔中出現的次數越多,那么它就越不重要

②示例,假如es索引中,有如下3篇文檔

The rules-which require employees to work from 9 am to 9 pm
In the weeks that followed the creation of 996.ICU in March
The 996.ICU page was soon blocked on multiple platforms including the messaging tool WeChat and the UC Browser.

③詞條ICU的文檔頻率是2,因為它出現在2篇文檔中,文檔的逆源自得分乘以1/DFDF是該詞條的文檔頻率,這就意味着,由於ICU詞條擁有更高的文檔頻率,所以,它的權重會降低

④詞條the的文檔頻率是3,它在3篇文檔中都出現了,注意,盡管the在后兩篇文檔出都出現兩次,但是它的詞頻是還是3,因為,逆文檔詞頻只檢查詞條是否出現在某篇文檔中,而不檢查它在這篇文檔中出現了多少次,那是詞頻該干的事兒**

⑤逆文檔詞頻是一個重要的因素,用來平衡詞條的詞頻,比如我們搜索the 996.ICU,單詞the幾乎出現在所有的文檔中(中文中比如),如果這個鬼東西要不被均衡一下,那么the的頻率將完全淹沒996.ICU,所以,逆文檔詞頻就有效的均衡了the這個常見詞的相關性影響,以達到實際的相關性得分將會對查詢的詞條有一個更准確地描述

5、當詞頻和逆文檔詞頻計算完成。就可以使用TF-IDF公式來計算文檔的得分了

二、其他的打分方法

1、TF-IDF結合向量空間模型的實用評分模式,是esLucene最為主流的評分機制,但這並不是唯一的,除了TF-IDF這種實用模型之外,還有其他模型

2、Okapi BM25

①k1和b是數值的設置,用於調整得分是如何計算的

②k1控制對於得分而言詞頻(TF)的重要性

③b是介於0 ~ 1之間的數值,它控制了文檔篇幅對於得分的影響程度

④默認情況下,k1設置為1.2,而b則被設置為0.75

discount_overlaps的設置用於告訴es,在某個字段中,多少個分詞出現在同一位置,是否應該影響長度的標准化,默認值是true

3、隨機性分歧(Divergence from randomness),即DFR相似度

4、LM Dirichlet相似度

5、LM Jelinek Mercer相似度

三、配置打分模型

1、簡要配置BM25打分模型

# `BM25`是一種基於概率的打分框架

PUT w2
{
  "mappings": {
    "doc": {
      "properties": {
        "title": {
          "type": "text",
          "similarity": "BM25"
        }
      }
    }
  }
}

PUT w2/doc/1
{
  "title":"The rules-which require employees to work from 9 am to 9 pm"
}

PUT w2/doc/2
{
  "title":"In the weeks that followed the creation of 996.ICU in March"
}

PUT w2/doc/3
{
  "title":"The 996.ICU page was soon blocked on multiple platforms including the messaging tool WeChat and the UC Browser."
}

GET w2/doc/_search
{
  "query": {
    "match": {
      "title": "the 996"
    }
  }
}

2、BM25高級配置

PUT w3
{
  "settings": {
    "index": {
      "analysis": {
        "analyzer":"ik_smart"
      }
    },
    "similarity": {
      "my_custom_similarity": {
        "type": "BM25",
        "k1": 1.2,
        "b": 0.75,
        "discount_overlaps": false
      }
    }
  },
  "mappings": {
    "doc": {
      "properties": {
        "title": {
          "type": "text",
          "similarity":"my_custom_similarity"
        }
      }
    }
  }
}

PUT w3/doc/1
{
  "title":"The rules-which require employees to work from 9 am to 9 pm"
}

PUT w3/doc/2
{
  "title":"In the weeks that followed the creation of 996.ICU in March"
}

PUT w3/doc/3
{
  "title":"The 996.ICU page was soon blocked on multiple platforms including the messaging tool WeChat and the UC Browser."
}

GET w3/doc/_search
{
  "query": {
    "match": {
      "title": "the 996"
    }
  }
}

3、配置全局打分模型:如果要使用某種特定的打分模型,並且希望應用到全局,那么就在elasticsearch.yml配置文件中加入

index.similarity.default.type: BM25

四、boosting

1、簡介

boosting是一個用來修改文檔相關性的程序,boosting有兩種使用場景

②索引的時候,比如在定義mappings的時候

③查詢一篇文檔的時候

④以上兩種方式都可以提升一個篇文檔的得分,需要注意的是,在索引期間修改的文檔boosting是存儲在索引中的,要想修改boosting必須重新索引該篇文檔

2、索引期間的boosting

PUT w4
{
  "mappings": {
    "doc": {
      "properties": {
        "name": {
          "boost": 2.0,
          "type": "text"
        },
        "age": {
          "type": "long"
        }
      }
    }
  }
}

①一勞永逸是沒錯,但一般不這么推薦

②原因之一是因為一旦映射建立完成,那么所有name字段都會自動擁有一個boost值,要想修改這個值,那就必須重新索引文檔

③另一個原因是,boost值是以降低精度的數值存儲在Lucene內部的索引結構中,只有一個字節用於存儲浮點型數值(存不下就損失精度了),所以,計算文檔的最終得分時可能會損失精度

④最后,boost是應用與詞條的,因此,再被boost的字段中如果匹配上了多個詞條,就意味着計算多次的boost,這將會進一步增加字段的權重,可能會影響最終的文檔得分

3、查詢期間的boosting

①在es中,幾乎所有的查詢類型都支持boost,正如那些match、multi_match等等

②示例,在查詢期間,使用match查詢進行boosting

PUT w5
{
  "mappings":{
    "doc":{
      "properties": {
        "title": {
          "type": "text",
          "analyzer": "ik_max_word"
        },
        "content": {
          "type": "text",
          "analyzer": "ik_max_word"
        }
      }
    }
  }
}

PUT w5/doc/1
{
  "title":"Lucene is cool",
  "content": "Lucene is cool"
}

PUT w5/doc/2
{
  "title":"Elasticsearch builds on top of lucene",
  "content":"Elasticsearch builds on top of lucene"
}

PUT w5/doc/3
{
  "title":"Elasticsearch rocks",
  "content":"Elasticsearch rocks"
}

GET w5/doc/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title":{
              "query": "elasticserach rocks",
              "boost": 2.5
            }
          }
        },
        {
          "match": {
            "content": "elasticserach rocks"
          }
        }
      ]
    }
  }
}

# 就對於最終得分而言,`content`字段,加了`boost`的`title`查詢更有影響力,也只有在`bool`查詢中,`boost`更有意義

4、跨越多個字段的查詢

boost也可以用於multi_match查詢

GET w5/doc/_search
{
  "query": {
    "multi_match": {
      "query": "elasticserach rocks",
      "fields": ["title", "content"],
      "boost": 2.5
    }
  }
}

②除此之外,還可以使用特殊的語法,只為特定的字段指定一個boost,通過在字段名稱后添加一個^符號和boost的值,告訴es只需對那個字段進行boost

GET w5/doc/_search
{
  "query": {
    "multi_match": {
      "query": "elasticserach rocks",
      "fields": ["title^3", "content"]
    }
  }
}

# `title`字段被`boost`了3倍
# 在使用`boost`的時候,無論是字段或者詞條,都是按照相對值來`boost`的,而不是乘以乘數
# 如果對於所有的待搜索詞條`boost`了同樣的值,那么就好像沒有`boost`一樣
# 因為Lucene會標准化`boost`的值,如果`boost`一個字段`4`倍,不是意味着該字段的得分就是乘以`4`的結果
# 所以,如果你的得分不是按照嚴格的乘法結果,也不要擔心


免責聲明!

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



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