電商站內搜尋筆記,以 elasticsearch 實踐

今年因為營運的目標,對搜尋的準確度要求越來越高,實際上要面對的商品數指數增加,所以在越來越多雜訊的情況下,搜尋的挑戰就變得更大了,一路下來認知到搜尋能努力的方向越來越多,所以就想寫一篇文來紀錄一下做了哪些改進,大致上能努力的方向就是中文斷詞、自訂排序、tag、Learning2rank..

前言

當然沒有辦法從零開始實作一個搜尋引擎,是基於 elasticsearch 來達成最基本的功能(以下簡稱 es),在這個框架之下在想辦法優化跟依照策略調整搜尋的排序,所以要大概理解 elasticsearch 能做的事,他本質就是一個透過 TF-IDF 可以快速計算分數的分散式搜尋引擎,讓你可以把上百萬筆資料丟進去,他可以幫你斷詞,建立索引,從中找到符合條件的資料,並且對這些資料計算相似度分數,返回一個排序過的結果,而這些事情在搜尋發生的瞬間只需要幾百毫秒,就可以處理完。

斷詞

當你裝好一套 es 的時候,第一個要面對的問題是他的中文斷詞,因為在英文上完全沒有斷詞的問題,而在中文搜尋上,斷詞的準確度會大大影響搜尋的結果,
因為使用者搜尋的意圖會因為斷詞的差異而有所改變,我最常舉的例子是衛生紙,當你把衛生紙盒的商品斷詞成「衛生紙、盒」,那使用者搜尋「衛生紙」的時候,搜尋引擎就無法區分衛生紙跟衛生紙盒的差異

所以需要先透過 jieba 這套斷詞套件來讓 es 具備中文斷詞的能力,他基本上有一個方式來達成最基本的中文斷詞,但是斷詞的演算法之下,最重要的是你的字典檔,當然在預設的詞庫之下,基本用詞的斷詞都不會有大問題,但是如果你是一個商品的網站,因為商品名稱跟形容詞的變化很快,像酷冰杯這種商品就不可能會在詞庫內

如果已經有一些使用者行為的話,就太好了,你可以搜尋使用者經常輸入的關鍵字,來建立你的自訂義字典檔,可以讓斷詞的精準度有很大的提升,如果沒有就只能先想辦法在網路上搜集接近你情境的詞庫。

自訂排序

在 es 內預設的搜尋分數,是透過 tf-idf 來計算的,概念上就是他會從關鍵字經常出現的頻率,跟關鍵字出現在這篇文章的頻率這兩個指標混合來計算出這個關鍵字跟目標的相似分數

實際上你會想要針對特定的欄位去加減分,例如某個廠商的表現很差,就不想要她排在第一頁,那你就可以透過 script_score 來自定義分數,他可以基於相似度去調節,例如 _score * (doc[‘merchant_score’].value < 0.5 ? 0.5: 1) ,當廠商分數低於 0.5 的話,相似度分數會被砍半,但是當你的這種條件很多的話,就要審慎評估一下每個權重的重要性

實務中自訂排序會有的挑戰是,如果你的搜尋結果不多的情況下,你希望搜尋結果不要太侷限,我們就會把搜尋的篩選門檻調低,再透過分數排序來顯示出比較多的結果,讓關鍵字只需要部分命中就可以進入候選名單中,如果你又過度調整排序分數的話,最後搜尋結果就會看起來很不精準,這就變成需要大量測試跟資料分析來解決的問題。

這邊有一個技術的重點是要搞清楚 es 中 score_modeboost_mode 是如何影響 score 的計算,要把計算的順序搞清楚,才可以真的依照期望的權重設計來影響分數。

tag

jieba 有支援兩種方式可以萃取關鍵字,一個是 tf-idf 一個是 textrank,當你有能力可以把一個文字取出最重要的關鍵字,拿來做加分,就可以賜予 es 更多參數調整的空間,如果你不滿意 es 幫你計算出來的分數,你可以讓你要被搜尋的商品,人工增加關鍵字,或者用 textrank 增加關鍵字,更進一步是透過使用者的點擊反饋來增加關鍵字

關於這個項目就有很多延伸的加強空間,後來我也嘗試 textrank + word2vec 來加強萃取出來的關鍵字精準度,當你有越多候選清單,後續就能用一些機器學習的方式來訓練你的排序參數的權重,就可以針對目標進行最佳化。

Learning2rank

最後如果你希望你的搜尋引擎像是有智慧一樣,可以依照使用者的點擊來影響排名,你可以研究這個演算法,如果深入研究,是可以花很多時間來改進模型的精準度的,但是實務上只要能夠套用到 es 中,只要把使用者的點擊行為直接作為結果進行排序,你的搜尋結果就會看起來還不錯了。

在 es 中可以透過不同的 type 來建立動態的 tag,就很像關聯式資料庫透過 has_child 讓商品可以 join 其關鍵字來取得數據並透過 script_score 拿到這些數字重新算分,就能實踐最基本的 learning2rank 演算法,不能完整實踐演算法的細節,但是至少能達到最基本的讓使用者點擊結果的量加入分數計算

結論

這篇文章沒有討論太多實作細節,但是包含我這幾年探索以後才陸續發現改進搜尋可以努力的方向,雖然改進完的瀏覽體感都有一些提升,但是還沒找到很關鍵的指標來衡量結果的改進。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *