Elasticsearch 如何實現相似推薦功能?

1、什麼是相似推薦?

拿我們身邊的算法 “投餵” 爲主的頭條、抖音、微信視頻號等舉例,如果你喜歡乒乓球,每天推送給你的都是乒乓球比賽視頻集錦;如果你喜歡成功人士演講,每天都是馬雲、馬化騰、劉強東等商業巨鱷的演講。

再拿電商的示例如下:比如我近期購買的吳軍老師推薦的科普經典鉅著《從一到無窮大》,京東會給我推薦樊登讀書帶火的書《微積分原理》。

其實,在實際業務實戰環節,或多或少也會有類似的功能,Elasticsearch 有沒有類似功能呢?

大家實戰環節遇到的問題也大致如下:

Q1:ES 有相似搜索這個功能吧?我記得有個 suggester 吧?

Q2:ES 有沒有處理相似文字的案例?把相似文章聚合起來。

來自《死磕 Elasticsearch 知識星球》微信羣

2、Elasticsearch 相似推薦功能實現

這裏不得不介紹:MLT 檢索。對!你沒看錯。不是:MIT(麻省理工學院),是 Elasticsearch 一種檢索類型 MLT(More Like This Query )。

看下圖,建立個全局認識。MLT 屬於:Query DSL 下的專業檢索(Specialized queries)的範疇。

3、More Like This 檢索介紹

More Like This 檢索定義:查找與給定文檔 “相似” 的文檔。

4、More Like This 底層邏輯

MLT 查詢簡單地從輸入的待查詢文本中提取文本,對其進行分析,通常在字段中使用相同的分析器,然後選擇具有最高 tf-idf 的前 K 個詞組以形成這些詞組的組合查詢語句。

假設我們想找到與給定輸入文檔相似的所有文檔。顯然,輸入文檔本身應該是該類型查詢的最佳匹配。爲什麼呢?基於 Lucene tf-idf 評分公式計算得出的呀。

如下就是 Lucene tf-idf 評分模型。

如果對此評分不瞭解的同學,推薦閱讀:

乾貨 | 一步步拆解 Elasticsearch BM25 模型評分細節

實戰 | Elasticsearch 自定義評分的 N 種方法

MLT 查詢的本質是:從待檢索語句中提取文本,然後用分詞器切分,選擇 tf-idf 分值高的前 K 個術語形成檢索語句。基於檢索語句返回的結果就是相似度查詢結果。

爲避免歧義,對照的英文如下:

The MLT query simply extracts the text from the input document, analyzes it, usually using the same analyzer at the field, then selects the top K terms with highest tf-idf to form a disjunctive query of these terms.

如果原理還不夠清晰,我將核心 Lucene 源碼的邏輯簡要說明如下:

抽取詞時會過濾掉停用詞、不滿足最小詞頻的詞等不滿足限定條件的詞。

Lucene 源碼部分截圖

循環超過最大查詢詞數目,則停止構建查詢語句。

最大查詢數據值 max_query_terms 默認是:25。增加此值會以犧牲查詢執行速度爲代價提供更高的準確性。

返回結果就是類似推薦功能的相似文章。

看的出來,這比我們常見的精準匹配 term query 和全文檢索 match query、match_pharse query 都要複雜很多。

5、More Like This 前置條件

執行 MLT 的字段必須被索引並且類型爲 text 或 keyword。此外,當對文檔使用相似度檢索時,必須啓用 _source 或設置爲 stored 或存儲爲 term_vector。爲了加快分析速度,可以在索引時存儲 terrm vectors。

讀者看到這裏可能會疑惑:啥叫 term vectors ?

有必要解釋一下:

term vectors 組成:

給了一堆術語,還是看不懂,再來?!

給個例子,一看就明白了。

PUT my-index-0000012
{
  "mappings"{
    "properties"{
      "text"{
        "type""text",
        "term_vector""with_positions_offsets"
      }
    }
  }
}

PUT my-index-0000012/_doc/1
{
  "text""Quick brown fox fox"
}
GET /my-index-0000012/_termvectors/1

position 更精確的說法是:序號。

6、More Like This 實戰一把

光說不練是假把式,實戰一把,一探究竟。

插入一批數據,數據來源:百度熱點新聞 。

DELETE news
PUT news
{
  "mappings"{
    "properties"{
      "title"{
        "type""text",
        "analyzer""ik_smart"
      }
    }
  }
}

POST news/_bulk
{ "index":  { "_id":1 }}
{"title":"演唱會突發意外!知名男星受傷,本人最新迴應"}
{ "index":  { "_id":2 }}
{"title":"張傑演唱會主辦方道歉:舞臺升降設備出現故障"}
{ "index":  { "_id":3 }}
{"title":"謝娜發文迴應張傑受傷"}
{ "index":  { "_id":4 }}
{"title":"張傑迴應受傷:不會有大礙,請歌迷和家人朋友們放寬心"}
{ "index":  { "_id":5 }}
{"title":"張傑表演時從電梯墜落 手指血流不止"}
{ "index":  { "_id":6 }}
{"title":"謝娜迴應張傑受傷:他問的第一句話就是怕嚇到女兒"}
{ "index":  { "_id":7 }}
{"title":"張傑演唱會出意外後,髮長文給粉絲報平安,謝娜透露張傑本人..."}
{ "index":  { "_id":8}}
{"title":"張傑明星資料大全愛奇藝泡泡"}

PS:以上僅是百度公開的熱點新聞,以此舉例相似查詢,別無其他用途,特此說明。

執行 MLT:

POST news/_search
{
  "query"{
    "more_like_this"{
      "fields"[
        "title"
      ],
      "like"[
        "張傑開演唱會從升降機上掉落"
      ],
      "analyzer""ik_smart",
      "min_doc_freq": 2,
      "min_term_freq"1
    }
  }
}

返回結果如下:

以如上截圖最後一條數據爲例,強調說明一下:注意到一個細節,返回結果只是相似,並沒有真正做到語義相關。

7、More Like This 核心語法詳解

參數看着很好解釋,但着實非常難理解,特此解讀如下:

最小的文檔頻率,默認爲 5。

什麼意思呢?

就拿上面的示例來說,至少得有兩篇文章纔可以,不管這兩篇文章與輸入相關與否。

更具體點說,如果 bulk 寫入僅一篇 document,哪怕和標題一致也無法返回結果。

文檔中詞組的最低頻率,默認是 2,低於此頻率的會被忽略。

什麼意思呢?

就是待檢索語句的其中一個分詞單元的詞頻的最小值。

PUT news
{
  "mappings"{
    "properties"{
      "title"{
        "type""text",
        "analyzer""ik_smart"
      }
    }
  }
}
POST news/_bulk
{ "index":  { "_id":1 }}
{"title":"張傑演唱會突發意外!知名男星受傷,本人最新迴應"}
{ "index":  { "_id":2 }}
{"title":"hello kitty"}

POST news/_search
{
  "query"{
    "more_like_this"{
      "fields"[
        "title"
      ],
      "like"[
        "張傑迴應張傑受傷"
      ],
      "analyzer""ik_smart",
      "min_doc_freq": 1,
      "min_term_freq"2
    }
  }
}

上面的例子更有說服力。

更爲具體的說,like 部分待檢索語句的分詞詞頻要至少有一個 >=2 。

更多參數建議參考官方文檔,不再贅述。

8、Elasticsearch 相似推薦其他的實現方案

在第 6 部分提及,more like this 並沒有實現完全的相關度推薦,出現了 “噪音” 數據。

所以,實戰環節使用 more like this 多半基於燃眉之急。

如果想深入的實現相似度推薦,推薦方案:

基於類似 simhash 的方式,給每個文檔打上 hash 值,基於海明距離實現相似度推薦。

如果想再深入就需要藉助:

基於協同過濾的推薦算法、基於關聯規則的推薦算法、基於知識的推理算法或者組合推理算法實現。

9、小結

本文介紹了 Elasticsearch 中實現相似推薦的 More Like This 檢索方法、實現原理、案例解讀。

目的是給大家業務系統實現相似推薦提供了理論和實踐支撐。

大家實戰環節如何實現的相似推薦呢?歡迎留言討論細節。

參考

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-mlt-query.html

https://spoon-elastic.com/all-elastic-search-post/more-like-this-query-mlt-suggest-similar-content-with-elasticsearch/

https://qbox.io/blog/mlt-similar-documents-in-elasticsearch-more-like-this-query/

https://spoon-elastic.com/all-elastic-search-post/more-like-this-query-mlt-suggest-similar-content-with-elasticsearch/

https://newbedev.com/elasticsearch-more-like-this-query

https://www.linkedin.com/pulse/finding-similar-documents-elasticsearch-morelikethis-fl%C3%A1vio-knob?articleId=6657988773374111744

《Lucene 原理與代碼分析》

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/apPGngRQx6bJEmR82XlXhQ