排序算法(Learn to rank)的一些看法

回來自我隔離期,出不了小區加上倒春寒陰天;瘋與快瘋之間,重讀了微軟研究院Learn to Rank幾篇經典論文,參考的看了CSDN上不少博主的觀點。總覺得對於文章,有些思路上的點沒有點透;嘗試從排序更根本思路去講解排序類算法爲何如此、以及如此演進。

思路:

排序從冒泡法說起——打分、參考比較、決策

冒泡排序時候每個容器中默認是一個數,所以沒有從特徵到打分這個步驟

冒泡排序時候兩個數據大小比對,其實是用我們認爲認定的一套數字隨比隨大的標準;這個參考物就是我們規定好的那些數的順序,只是我們日用忽視了這個參考比較過程

冒泡排序當符合我們認爲的數的大小順序就認爲是對的(1)不需要調整兩數順序,不符合則認爲是不對的(-1)調整兩數順序

Ranknet根據query對Document排序步驟和原本思路和冒泡排序如出一撤:

根據文本、用戶特徵、query特徵利用一個函數對Document打分:F(特徵、用戶、query)

利用打好序列標籤的訓練樣本做參考,比較打完分的文本順序

決策,Ranknet通過分類的思路解決,如果打完分的兩個Documeng排序和大號標籤訓練樣本順序是一致則爲1,否則爲0

這就是Learn to Rank算法的最樸素思路、也是後續lambdaRank、lambdaMART、深度學習模型TF-Ranking的建模框架。

多說一句其實大部分現在看起來高深莫測的技術,其實最樸素的思路都來自於我們了無生趣的生活中;好的想法都是簡單樸實但是都是框架級別的存在,後續的變化不過是框架裏填入什麼東西后者小改動什麼東西。

問題:

1、Ranknet只考慮到了兩兩比較文檔對之間序列關係(給的是全局排序,它只學了倆倆關係,視野格局不夠)

2、lamdaRank引入NDCG或ERR全局序列參數,但NDCG、ERR是非凸在進行梯度求解時候計算複雜

3、lambdaMART通過MART多項式來你和含NDCG或ERR的lambda梯度解決梯度非凸問題,但對於圖像、文本、稀疏特徵打分效果不夠好

改進:

1、Ranknet梯度和deltaNDCG相乘,引入NDCG全局排序因子

2、用凸函數來擬合梯度,比如用MART多相似來擬合

3、引入對文本、圖像、稀疏特徵處理能力強的深度學習,替代MART或者淺層線性模型

所有的解決對策,都來源於對問題的認識。看到問題纔會有對策,難得在於往往牽一髮動全身,如何在簡單和有效中tade off。

到此其實文章就可以結束了,因爲對於learn to rank具體技術細節的文章有太多,具體可見下文參考。但出於文章完整性考慮,我簡單介紹Ranknet、lambdaRank、lambdaMART。

    • 2. RANKNET

    • 2.1 算法基礎定義

      RankNet解決如下搜索排序問題:給定query集合,每個query都對應着一個文檔集合,如何對每個query返回排序後的文檔集合。可以想象這樣的場景:某位高考生在得知自己的成績後,準備報考志願。聽說最近西湖大學辦得不錯,所以就想到網上搜搜關於西湖大學的資料。他打開一個搜索引擎,輸入“西湖大學”四個字,然後點擊“搜索”,頁面從上到下顯示了10條搜索結果,他認爲排在上面的肯定比下面的相關,所以就開始從上往下一個個地瀏覽。所以RankNet的目標就是對所有query,都能將其返回的文檔按照相關性進行排序。

      RankNet網絡將輸入query的特徵向量𝑥∈ℝ𝑛x∈Rn映射爲一個實數𝑓(𝑥)∈ℝf(x)∈R。RankNet採用pairwise的方法進行模型訓練。具體地,給定特定query下的兩個文檔𝑈𝑖Ui和𝑈𝑗Uj,其特徵向量分別爲𝑥𝑖xi和𝑥𝑗xj,經過RankNet進行前向計算得到對應的分數爲𝑠𝑖=𝑓(𝑥𝑖)si=f(xi)和𝑠𝑗=𝑓(𝑥𝑗)sj=f(xj)。用𝑈𝑖⊳𝑈𝑗Ui⊳Uj表示𝑈𝑖Ui比𝑈𝑗Uj排序更靠前(如對某個query來說,𝑈𝑖Ui被標記爲“good”,𝑈𝑗Uj被標記爲“bad”)。繼而可以用下面的公式來表示𝑈𝑖Ui應該比𝑈𝑗Uj排序更靠前的概率:

      𝑃𝑖𝑗≡𝑃(𝑈𝑖⊳𝑈𝑗)≡11+𝑒−𝜎(𝑠𝑖−𝑠𝑗)

      這個概率實際上就是深度學習中經常使用的sigmoid函數,參數𝜎σ決定sigmoid函數的形狀。對於特定的query,定義𝑆𝑖𝑗∈{0,±1}Sij∈{0,±1}爲文檔𝑖i和文檔𝑗j被標記的標籤之間的關聯,即

       

      𝑆𝑖𝑗=⎧⎩⎨⎪⎪10−1文檔𝑖比文檔𝑗更相關文檔𝑖和文檔𝑗相關性一致文檔𝑗比文檔𝑖更相關Sij={1文檔i比文檔j更相關0文檔i和文檔j相關性一致−1文檔j比文檔i更相關

      定義𝑃⎯⎯⎯⎯𝑖𝑗=12(1+𝑆𝑖𝑗)P¯ij=12(1+Sij)表示𝑈𝑖Ui應該比𝑈𝑗Uj排序更靠前的已知概率,則可以用交叉熵定義優化目標的損失函數:

      𝐶=−𝑃⎯⎯⎯⎯𝑖𝑗𝑙𝑜𝑔𝑃𝑖𝑗−(1−𝑃⎯⎯⎯⎯𝑖𝑗)𝑙𝑜𝑔(1−𝑃𝑖𝑗)C=−P¯ijlogPij−(1−P¯ij)log(1−Pij)

      如果不太熟悉什麼是交叉熵,可以參考宗成慶老師的《統計自然語言處理》2.2節“信息論基本概念”,裏面將熵、聯合熵、互信息、相對熵、交叉熵和困惑度等概念都講得相當清楚。

      結合以上多個公式,可以改寫損失函數𝐶C爲:

      𝐶=12(1−𝑆𝑖𝑗)𝜎(𝑠𝑖−𝑠𝑗)+𝑙𝑜𝑔(1+𝑒−𝜎(𝑠𝑖−𝑠𝑗))C=12(1−Sij)σ(si−sj)+log(1+e−σ(si−sj))

      對於𝑆𝑖𝑗=1Sij=1,

      𝐶=𝑙𝑜𝑔(1+𝑒−𝜎(𝑠𝑖−𝑠𝑗))C=log(1+e−σ(si−sj))

      然而對於𝑆𝑖𝑗=−1Sij=−1,

      𝐶=𝑙𝑜𝑔(1+𝑒−𝜎(𝑠𝑗−𝑠𝑖))C=log(1+e−σ(sj−si))

      可以看出損失函數𝐶C具有對稱性,也即交換𝑖i和𝑗j的位置,損失函數的值不變。

      分析損失函數𝐶C的趨勢發現,如果對文檔𝑈𝑖Ui和𝑈𝑗Uj的打分可以正確地擬合標記的標籤,則𝐶C趨向於0,否則𝐶C趨向於線性函數。具體地,假如𝑆𝑖𝑗=1Sij=1,也即𝑈𝑖Ui應該比𝑈𝑗Uj排序高,如果𝑠𝑖>𝑠𝑗si>sj,則擬合的分數可以正確排序文檔𝑖i和文檔𝑗j,

      lim𝑠𝑖−𝑠𝑗→∞𝐶=lim𝑠𝑖−𝑠𝑗→∞𝑙𝑜𝑔(1+𝑒−𝜎(𝑠𝑖−𝑠𝑗))=𝑙𝑜𝑔1=0limsi−sj→∞C=limsi−sj→∞log(1+e−σ(si−sj))=log1=0

      如果𝑠𝑖<𝑠𝑗si<sj,則擬合的分數不能正確排序文檔𝑖i和文檔𝑗j,

      lim𝑠𝑖−𝑠𝑗→∞𝐶=lim𝑠𝑖−𝑠𝑗→∞𝑙𝑜𝑔(1+𝑒−𝜎(𝑠𝑖−𝑠𝑗))=𝑙𝑜𝑔(𝑒−𝜎(𝑠𝑖−𝑠𝑗))=−𝜎(𝑠𝑖−𝑠𝑗)limsi−sj→∞C=limsi−sj→∞log(1+e−σ(si−sj))=log(e−σ(si−sj))=−σ(si−sj)

      利用神經網絡對模型進行訓練,目前最有效的方法就是反向傳播算法。反向傳播算法中最核心部分就是損失函數對模型參數的求導,然後可以使用下面的公式對模型參數進行迭代更新:

      𝑤𝑘←𝑤𝑘−𝜂∂𝐶∂𝑤𝑘=𝑤𝑘−𝜂(∂𝐶∂𝑠𝑖∂𝑠𝑖∂𝑤𝑘+∂𝐶∂𝑠𝑗∂𝑠𝑗∂𝑤𝑘)wk←wk−η∂C∂wk=wk−η(∂C∂si∂si∂wk+∂C∂sj∂sj∂wk)

      損失函數𝐶C對𝑠𝑖si和𝑠𝑗sj的偏導數爲:

      ∂𝐶∂𝑠𝑖=𝜎(12(1−𝑆𝑖𝑗)−11+𝑒𝜎(𝑠𝑖−𝑠𝑗))=−∂𝐶∂𝑠𝑗∂C∂si=σ(12(1−Sij)−11+eσ(si−sj))=−∂C∂sj

      𝑠𝑖si和𝑠𝑗sj對𝑤𝑘wk的偏導數可根據神經網絡求偏導數的方式求得。求得了損失函數𝐶C對神經網絡模型參數𝑤𝑘wk的偏導數之後,就可以使用梯度下降算法對其更新。這裏的學習率𝜂η也是一個正數,因爲𝜂η需要滿足下面的不等式:

      𝛿𝐶=∑𝑘∂𝐶∂𝑤𝑘𝛿𝑤𝑘=∑𝑘∂𝐶∂𝑤𝑘(−𝜂∂𝐶∂𝑤𝑘)=−𝜂∑𝑘(∂𝐶∂𝑤𝑘)2<0

    • 2.2 RankNet分解形式:加速RankNet訓練過程

      2.1節中定義的RankNet,對於每一個文檔對(𝑈𝑖(Ui,𝑈𝑗)Uj)都將計算損失函數對神經網絡的參數𝑤𝑘wk的偏導數,然後更新模型參數𝑤𝑘wk。這樣做的缺點在於,對模型參數更新慢,耗時長。所以本節講解如何通過分解組合的方式加快這一訓練過程。

      對於給定的文檔對𝑈𝑖Ui和𝑈𝑗Uj,損失函數𝐶C對參數𝑤𝑘wk的偏導數爲:

      ∂𝐶∂𝑤𝑘=∂𝐶∂𝑠𝑖∂𝑠𝑖∂𝑤𝑘+∂𝐶∂𝑠𝑗∂𝑠𝑗∂𝑤𝑘=𝜎(12(1−𝑆𝑖𝑗)−11+𝑒𝜎(𝑠𝑖−𝑠𝑗))(∂𝑠𝑖∂𝑤𝑘−∂𝑠𝑗∂𝑤𝑘)=𝜆𝑖𝑗(∂𝑠𝑖∂𝑤𝑘−∂𝑠𝑗∂𝑤𝑘)∂C∂wk=∂C∂si∂si∂wk+∂C∂sj∂sj∂wk=σ(12(1−Sij)−11+eσ(si−sj))(∂si∂wk−∂sj∂wk)=λij(∂si∂wk−∂sj∂wk)

      其中:

      𝜆𝑖𝑗=∂𝐶(𝑠𝑖−𝑠𝑗)∂𝑠𝑖=𝜎(12(1−𝑆𝑖𝑗)−11+𝑒𝜎(𝑠𝑖−𝑠𝑗))λij=∂C(si−sj)∂si=σ(12(1−Sij)−11+eσ(si−sj))

      定義𝐼I爲索引對{𝑖,𝑗}{i,j}的集合,在不損失信息量的情況下,可以將集合𝐼I中的索引對都轉換成滿足𝑈𝑖⊳𝑈𝑗Ui⊳Uj的形式。另外集合𝐼I中的索引對還應該滿足最多隻出現一次的條件。在此基礎上,累加權重參數𝑤𝑘wk的更新量:

      𝛿𝑤𝑘=−𝜂∑(𝑖,𝑗)∈𝐼(𝜆𝑖𝑗∂𝑠𝑖∂𝑤𝑘−𝜆𝑖𝑗∂𝑠𝑗∂𝑤𝑘)=−𝜂∑𝑖𝜆𝑖∂𝑠𝑖∂𝑤𝑘δwk=−η∑(i,j)∈I(λij∂si∂wk−λij∂sj∂wk)=−η∑iλi∂si∂wk

      其中:

      𝜆𝑖=∑𝑗:{𝑖,𝑗}∈𝐼𝜆𝑖𝑗−∑𝑗:{𝑗,𝑖}∈𝐼𝜆𝑖𝑗λi=∑j:{i,j}∈Iλij−∑j:{j,i}∈Iλij

      𝜆𝑖λi可以看成是作用在排序文檔上的力,其正負代表了方向,長度代表了力的大小。最初的實現是對每個文檔對,都計算一遍梯度並且更新神經網絡的參數值,而這裏則是將同一個query下的所有文檔對進行疊加,然後更新一次網絡的權重參數。這種分解組合形式實際上就是一種小批量學習方法,不僅可以加快迭代速度,還可以爲後面使用非連續的梯度模型打下基礎。

    • 3.LAMBDARANK

    • 3.1 爲什麼需要LambdaRank

      先看一張論文原文中的圖,如下所示。這是一組用二元等級相關性進行排序的鏈接地址,其中淺灰色代表鏈接與query不相關,深藍色代表鏈接與query相關。 對於左邊來說,總的pairwise誤差爲13,而右邊總的pairwise誤差爲11。但是大多數情況下我們更期望能得到左邊的結果。這說明最基本的pairwise誤差計算方式並不能很好地模擬用戶對搜索引擎的期望。右邊黑色箭頭代表RankNet計算出的梯度大小,紅色箭頭是期望的梯度大小。NDCG和ERR在計算誤差時,排名越靠前權重越大,可以很好地解決RankNet計算誤差時的缺點。但是NDCG和ERR均是不可導的函數,如何加入到RankNet的梯度計算中去?

      圖1

       

      3.2  LambdaRank定義

      RankNet中的𝜆𝑖𝑗λij可以看成是𝑈𝑖Ui和𝑈𝑗Uj中間的作用力,如果𝑈𝑖⊳𝑈𝑗Ui⊳Uj,則𝑈𝑗Uj會給予𝑈𝑖Ui向上的大小爲|𝜆𝑖𝑗||λij|的推動力,而對應地𝑈𝑖Ui會給予𝑈𝑗Uj向下的大小爲|𝜆𝑖𝑗||λij|的推動力。如何將NDCG等類似更關注排名靠前的搜索結果的評價指標加入到排序結果之間的推動力中去呢?實驗表明,直接用|Δ𝑁𝐷𝐶𝐺||ΔNDCG|乘以原來的𝜆𝑖𝑗λij就可以得到很好的效果,也即:

       

      𝜆𝑖𝑗=∂𝐶(𝑠𝑖−𝑠𝑗)∂𝑠𝑖=−𝜎1+𝑒𝜎(𝑠𝑖−𝑠𝑗)|Δ𝑁𝐷𝐶𝐺|λij=∂C(si−sj)∂si=−σ1+eσ(si−sj)|ΔNDCG|

      其中|Δ𝑁𝐷𝐶𝐺||ΔNDCG|是交換排序結果𝑈𝑖Ui和𝑈𝑗Uj得到的NDCG差值。NDCG傾向於將排名高並且相關性高的文檔更快地向上推動,而排名地而且相關性較低的文檔較慢地向上推動。

      另外還可以將|Δ𝑁𝐷𝐶𝐺||ΔNDCG|替換成其他的評價指標。

4. LambdaMART

4.1 邏輯迴歸+MART進行二分類

瞭解了MART之後,下面舉一個MART實際應用的例子:使用MART和邏輯迴歸進行二分類。用於分類的樣本𝑥𝑖∈ℝ𝑛xi∈Rn,標籤𝑦𝑖∈{±1}yi∈{±1},擬合函數𝐹(𝑥)F(x)。爲了簡化表示,我們表示條件概率如下:

 

𝑃+≡𝑃(𝑦=1|𝑥)P+≡P(y=1|x)

 

𝑃−≡𝑃(𝑦=−1|𝑥)P−≡P(y=−1|x)

用交叉熵表示損失函數:

𝐿(𝑦,𝐹)=−𝑦𝑙𝑜𝑔(𝑃+)−(1−𝑦)𝑙𝑜𝑔(𝑃−)L(y,F)=−ylog(P+)−(1−y)log(P−)

邏輯迴歸使用對數機率(屬於正例概率/屬於負例概率)進行建模,

𝐹𝑛(𝑥)=12𝑙𝑜𝑔(𝑃+𝑃−)Fn(x)=12log(P+P−)

𝑃+=11+𝑒−2𝜎𝐹𝑛(𝑥)P+=11+e−2σFn(x)

𝑃−=1−𝑃+=11+𝑒2𝜎𝐹𝑛(𝑥)P−=1−P+=11+e2σFn(x)

將𝑃+P+和𝑃−P−帶入𝐿(𝑦,𝐹)L(y,F)中,得到:

𝐿(𝑦,𝐹𝑛)=𝑙𝑜𝑔(1+𝑒−2𝑦𝜎𝐹𝑛)L(y,Fn)=log(1+e−2yσFn)

𝑅𝑗𝑚Rjm表示落入第𝑚m棵樹的第𝑗j個葉子節點中的樣例集合,可以通過下式對該葉子節點的值進行優化:

𝛾𝑗𝑚=𝑎𝑟𝑔min𝛾∑𝑥𝑖∈𝑅𝑗𝑚log(1+𝑒−2𝜎𝑦𝑖(𝐹𝑚−1(𝑥𝑖)+𝛾))γjm=argminγ∑xi∈Rjmlog⁡(1+e−2σyi(Fm−1(xi)+γ))

上式可以使用Newton-Raphson方法按照下面的公式進行迭代求解:

𝛾𝑛+1=𝛾𝑛−𝑔′(𝛾𝑛)𝑔″(𝛾𝑛)γn+1=γn−g′(γn)g″(γn)

4.2 LambdaMART基本定義

LambdaMART基於MART,優化𝜆λ梯度。根據上面的定義,對於任意𝑈𝑖Ui和𝑈𝑗Uj,有:

𝜆𝑖𝑗=∂𝐶(𝑠𝑖−𝑠𝑗)∂𝑠𝑖=−𝜎|Δ𝑍𝑖𝑗|1+𝑒𝜎(𝑠𝑖−𝑠𝑗)λij=∂C(si−sj)∂si=−σ|ΔZij|1+eσ(si−sj)

|Δ𝑍𝑖𝑗||ΔZij|表示交換𝑈𝑖Ui和𝑈𝑗Uj的位置產生的評價指標差值,𝑍Z可以是𝑁𝐷𝐶𝐺NDCG或者𝐸𝑅𝑅ERR等。對於特定𝑈𝑖Ui,累加其他所有排序項的影響,得到:

𝜆𝑖=∑𝑗:{𝑖,𝑗}∈𝐼𝜆𝑖𝑗−∑𝑗:{𝑗,𝑖}∈𝐼𝜆𝑖𝑗λi=∑j:{i,j}∈Iλij−∑j:{j,i}∈Iλij

 爲了簡化表示:

∑{𝑖,𝑗}⇌𝐼𝜆𝑖𝑗=∑𝑗:{𝑖,𝑗}∈𝐼𝜆𝑖𝑗−∑𝑗:{𝑗,𝑖}∈𝐼𝜆𝑖𝑗∑{i,j}⇌Iλij=∑j:{i,j}∈Iλij−∑j:{j,i}∈Iλij

於是我們可以更新損失函數:

∂𝐶∂𝑠𝑖=∑𝑗:{𝑖,𝑗}∈𝐼−𝜎|Δ𝑍𝑖𝑗|1+𝑒𝜎(𝑠𝑖−𝑠𝑗)=∑𝑗:{𝑖,𝑗}∈𝐼−𝜎|Δ𝑍𝑖𝑗|𝜌𝑖𝑗∂C∂si=∑j:{i,j}∈I−σ|ΔZij|1+eσ(si−sj)=∑j:{i,j}∈I−σ|ΔZij|ρij

其中,我們定義:

𝜌𝑖𝑗=11+𝑒𝜎(𝑠𝑖−𝑠𝑗)=−𝜆𝑖𝑗𝜎|Δ𝑍𝑖𝑗|ρij=11+eσ(si−sj)=−λijσ|ΔZij|

然後可以得到:

∂2𝐶∂𝑠2𝑖=∑{𝑖,𝑗}⇌𝐼𝜎2|Δ𝑍𝑖𝑗|𝜌𝑖𝑗(1−𝜌𝑖𝑗)∂2C∂si2=∑{i,j}⇌Iσ2|ΔZij|ρij(1−ρij)

所以我們可以用下面的公式計算第𝑚m棵樹的第𝑘k個葉子節點上的值:

𝛾𝑘𝑚=∑𝑥𝑖∈𝑅𝑘𝑚∂𝐶∂𝑠𝑖∑𝑥𝑖∈𝑅𝑘𝑚∂2𝐶∂𝑠2𝑖=−∑𝑥𝑖∈𝑅𝑘𝑚∑{𝑖,𝑗}⇌𝐼|Δ𝑍𝑖𝑗|𝜌𝑖𝑗∑𝑥𝑖∈𝑅𝑘𝑚∑{𝑖,𝑗}⇌𝐼|Δ𝑍𝑖𝑗|𝜎𝜌𝑖𝑗(1−𝜌𝑖𝑗)

  • 5. 參考

https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/MSR-TR-2010-82.pdf

https://www.microsoft.com/en-us/research/wp-content/uploads/2005/08/icml_ranking.pdf

https://liam.page/uploads/slides/lambdamart.pdf

https://www.cnblogs.com/genyuan/p/9788294.html

https://ai.googleblog.com/2018/12/tf-ranking-scalable-tensorflow-library.html

https://github.com/shiba24/learning2rank

 

 

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