搜索排序之線性模型

搜索排序一般分成粗排和精排,一般來說,粗排使用線性模型,可以快速迭代出結果。後續等有用戶行爲之後,則進行進一步的精排模型的接入, 可以進一步提升搜索排序的精準度。今天這裏主要介紹搜索排序的線性模型。

1. 背景

最近在看一本關於搜索相關的書籍《相關性搜索》, 非常適合搜索入門,特別是裏面的一些思想,給我感覺有挺多感觸的, 簡單來講,書上已經將相關性搜索的方方面面講的很清楚了。感覺挺有收穫的。有興趣的同學可以看一下。

2. 規則線性模型

其中印象最深刻的是,調整相關性函數的那一章。實際上,相關性函數的設計,是一個搜索功能必須具備的一個設計能力,它也是一個搜索系統靈魂所在。只有把相關函數設計好了,才能檢索出更具相關性的結果出來。

在設計相關函數,一般採用以下三種策略:

  • 加法放大: 在基準評價值的基礎之上疊加放大的效果。 總價值=基礎評價值+加法放大值。
  • **乘法放大:**根據放大倍數對基準評價值進行“”縮放“”。總價值=基礎評價值*乘法放大值。
  • yes/no: 在yes/no的基礎上,進行時效性和質量度的衰減調權。

首先來定義以下,什麼是基礎評價值,什麼是放大值。實際上,一般來說,基礎評價值,一般都是關於query和doc之間的相關性價值分,例如tf-idf/bm25等等因子,而放大值,則是一些時效性和質量度的分值。

首先來看一下加法放大:

total_score = (w1*bm25+w2*tf-idf) + (w3*quality+w4*score),

這種放大方式,比較容易出現,熱度擊穿的問題。

再來看一下乘法放大:

total_score = (w1*bm25+w2*tf-idf)*(w3*quality+w4*score)

這種方法方式,可以很好的解決熱度擊穿的問題,如果文本分較少的話,乘法相應的懲罰也會較大。所以工業界採用乘法放大的比較多。

最後看一下yes/no的方案, 實際上這種場景比較適合書上的電影場景(垂直搜索場景), 畢竟垂直搜索領域的術語比較有限,一般完全匹配可以解決80%的問題,剩下的問題,可能更多是通過時效性和質量度進行調優,特別是裏面的搜索導演名的場景。

實際上,在很多時候,會把上面三種的方案,組合成一個更多元化的實現方案,可以實現對業務更好的支持。例如書上舉出來的例子:

1. 精準匹配片名?————> 選擇該搜索結果
2. 精準匹配人名?————> 基於時效和評分進行排名
3. 部分匹配人名?————> 稍作放大
4. 加入基準查詢

實際上,使用以上這些策略,實現出來的基準也是可以已經很好滿足用戶的需求的。

2. 機器學習的線性模型

雖然上面的規則模型,可以很好的滿足用戶的需求,但是畢竟是人工規則,其中的調整參數是一個非常大的難題。具體如何調參, 可能需要相關性技術工程師,花費大量的人力物力根據top query,進行調整和嘗試, 才能最終調整出一個滿意的結果。

實際上,目前大部分的排序,更多的是採用機器學習的模型來實現, 權重的調整。目前業界比較流程的線性模型,主要包括LR模型和FM模型。

仔細想一想,單純模型的預測函數來講,上面講的加法放大的模型,實際上就是LR模型的預測函數,而乘法放大的模型,實際上就是FM模型的二階項的預測函數。

實際上,任何線性模型都是有跡可循的。哈哈哈。只是機器學習,使用了更加嚴謹的方法來實現對參數的權重進行調權和實現。不過機器學習的方法,更多的基礎,是在好的數據特徵和好的數據樣本,不然訓練出來的結果,還不如上面使用有經驗的拍腦袋拍出來的權重。

第一步是,要有好的樣本數據:一般是使用人工標註的數據,或者從用戶的搜索日誌裏面提取出來對應的樣本數據。對樣本進行0-4的評分。

第二步是,要有好的特徵,這裏就考究相關性技術工程師,是否能提取出好的特徵工程了,和推薦系統相比之下,推薦系統很多時候是根據用戶行爲進行特徵提取的。當然搜索的特徵工程,是一個比較核心的指標也是根據用戶行爲,推薦系統更多的是基於用戶的特徵,而搜索的項目更多是基於query的特徵。

例如bm25和tf-idf則是query和doc之間的一個交叉特徵。特徵工程的內容這裏就不展開敘述了,以後會做統一歸納。

舉個簡單的例子:我們根據某個query詞, 搜索,然後計算對應的在線特徵,包括標題分、摘要分,用戶打分。如下rocky.csv(工業界的做法還需要提取大量的query和人工標註評分):

grade,titleScore,overviewScore,ratingScore,comment:# <docid> keywords@movietitle
4,10.65,8.41,7.40,# 1366   rocky@Rocky
3,0.00,6.75,7.00,# 12412  rocky@Creed
3,8.22,9.72,6.60,# 1246   rocky@Rocky Balboa
3,8.22,8.41,0.00,# 1374   rocky@Rocky IV
3,8.22,7.68,6.90,# 1367   rocky@Rocky II
3,8.22,7.15,0.00,# 1375   rocky@Rocky V
3,8.22,5.28,0.00,# 1371   rocky@Rocky III
2,0.00,0.00,7.60,# 154019 rocky@Belarmino
2,0.00,0.00,7.10,# 1368   rocky@First Blood
2,0.00,0.00,6.70,# 13258  rocky@Son of Rambow
2,0.00,0.00,0.00,# 70808  rocky@Klitschko
2,0.00,0.00,0.00,# 64807  rocky@Grudge Match
2,0.00,0.00,0.00,# 47059  rocky@Boxing Gym
  • LR模型的訓練過程如下:
from sklearn.linear_model import LinearRegression
from math import sin
import numpy as np
import csv

rockyData = np.genfromtxt('rocky.csv', delimiter=',')[1:] # Remove the CSV header

rockyGrades = rockyData[:,0]   # Slice out column 0, where the grades are
rockySignals = rockyData[:,1:-1]  # Features in columns 1...all but last column (the comment)

butIRegress = LinearRegression()
butIRegress.fit(rockySignals, rockyGrades)

butIRegress.coef_  #boost for title, boost for overview, boost for rating


array([ 0.04999419,  0.22958357,  0.00573909])


butIRegress.intercept_



def relevanceScore(intercept, titleCoef, overviewCoef, ratingCoef, titleScore, overviewScore, movieRating):
    return intercept + (titleCoef * titleScore) + (overviewCoef * overviewScore) + (ratingCoef * movieRating)
    
    # Score Rambo
relevanceScore(butIRegress.intercept_, butIRegress.coef_[0], butIRegress.coef_[1], butIRegress.coef_[2],
               titleScore=12.28, overviewScore=9.82, movieRating=6.40)
# Score First Blood
relevanceScore(butIRegress.intercept_, butIRegress.coef_[0], butIRegress.coef_[1], butIRegress.coef_[2],
               titleScore=0.00, overviewScore=10.76, movieRating=7.10)

一般來說,現行模型常用的校驗指標是AUC指標,而不是ltr常用的ndcg的排序模型,畢竟這裏只是簡單的point wise。

今天就到這裏,後續補充一下fm的模型代碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章