天天看點

飛豬的“猜你喜歡”如何排序?

引言

俗話說有多少米,就下多大鍋。在特征體系建構上,我們已經準備了很多米了,并且線上性模型 FTRL 上拿到了一些甜頭。下一階段我們換了鍋,對模型進行了更新,從線性模型轉為 end-to-end 的深度模型,并進行了多個版本的疊代,包括 pure deep 模型(Pure Adaptive L2 Model,PALM),引入實時點選和實時未點選行為(FeedBack-PALM,FB-PALM),引入全網序列特征(Global Local Attention-PALM,GLA),并拿到了一些收益。下面對這個階段的技術細節進行介紹。

飛豬的“猜你喜歡”如何排序?

問題分析

固定的特征體系下精巧的模型結構也能顯著發揮現有特征的潛力。end-to-end 的深度模型一方面可以隐式和顯示的進行特征交叉增加特征的表達能力。另一方面可以很 flexible 的引入真實行為序列特征等複雜結構特征。但是任何事情都有兩面性,end-to-end 的深度模型相較于 FTRL 雖然對特征組合要求較少,但是對特征的篩選要求精細,數值型特征以及 id 類特征的選擇和處理方法都會對最後的模型效果起決定性的作用。另外模型泛化性,訓練過拟合問題以及模型複雜度和線上 rt 的關系也是需要關注的問題。經過多個版本的疊代,包括對現有的多種點選率深度積木模型的複現,引入使用者實時點選和未點選 set 特征,引入使用者全網序列特征,引入寶貝一階近鄰和預訓練向量,加入 time-aware attention 等。下面分階段進行介紹,包括面對的問題,模型結構,模型離線/線上效果,以及一些思考。

模型疊代

PALM (Pure Adaptive L2 Model) 模型

問題

  

在新的特征體系下,我們在 FTRL 上拿到不錯的結果,很自然的想法是把 FTRL 上的特征複用到 Wide and deep 模型上,然後增加隐式高階交叉的 deep 側,來在原來的基礎上增加模型表達能力。但是經過幾輪的調試,離線名額一直和 FTRL 相比微正向,這不符合對 deep 模型的期望。後來發現把 wide 側上的特征慢慢遷移到 deep 側,包括 id 特征,數值特征,命中特征等,離線評測名額漲幅較大,後面也沿用這個思路,采用 pure deep 模型,将所有的特征都遷移到 deep 側,并拿到了一些收益。但是 pure deep 模型和 wide and deep 模型相比,非常容易過拟合,并且對數值特征以及命中特征的處理方式有一定的要求。其中對離線名額提升較明顯的幾個點如下:

1)寶貝 id,使用者 id,trigger id 等高維 id 類特征需要謹慎加入。航旅這種低頻場景,這種高維 id 特征分布一般長尾較嚴重,大部分 id 的訓練資料非常少,噪聲較多,模型容易過拟合。在嘗試中,正則以及 dropout 等常用抑制過拟合的方式一直沒有較好的效果。後續借鑒 DIN 中介紹的 adaptive l2 regularization 的方式,挑選了一批類似使用者id這種高維稀疏 id 類特征做動态正則。對正則系數做适當調整後,模型訓練正常,全量資料過 5 個 epoch 也不會出現過拟合現象。

飛豬的“猜你喜歡”如何排序?

2)命中特征(lookup 特征)在目前的 rtp fg 過程中如果沒有命中的話,是不存在這個特征結果的,也沒有預設值。反映到模型中,如果沒有命中,那麼 dense 類型輸出為 0,id 類型經過 embedding 操作之後輸出全零的向量。在神經網絡這種對資料分布敏感的模型中,我們考慮了兩種使用方式。第一種是采用 dense 類型,命中之後有大于零的值,沒有命中的話為零,符合正常資料分布。第二種是 id 類型,命中之後輸出一個 id,經過 embedding 操作之後輸出均值為零的向量,沒有命中的話輸出全零向量,也是符合正常資料分布的。經過試驗第二種優于第一種,但是第二種方式 embedding 的次元不适合選擇太大,因為命中特征本身較稀疏,輸出全零向量的可能性較多,會影響模型訓練過程。

3)Warm-up+Adam+learning rate decay 的方式相較于其他優化方法對離線名額的提升較大,非常值得一試。

4)batch normalization 在模型訓練中起了非常大的作用。由于 deep 側包括大量的高階 look up 特征和歸一化之後的數值型特征,離散化之後的數值型 id 特征以及普通 id 類特征的 embedding 結果,輸入到網絡中的數值非常不規範。後面發現 batch normalization 能有效規範這種多種來源的特征組合輸入,保證網絡的正常收斂。經過嘗試在 embedding 層之後加前置 BN,後續接 fully_connected + BN + relu 的這種形式在離線名額上表現最好。

模型結構

最終的網絡結構如圖:

飛豬的“猜你喜歡”如何排序?

圖中的模型細節就不累述了。該模型的 loss function 和後續的疊代版本都是采用 pointwise 的形式。離線評測都采用同樣時間區間的訓練資料的 T + 1 評測 AUC。

飛豬的“猜你喜歡”如何排序?

模型效果分析

同樣的時間視窗,采用 30 天資料訓練,T + 1 評測,離線名額如下,提升還是很明顯的。

飛豬的“猜你喜歡”如何排序?

效果

上線實驗觀察 4 天,相較于新特征的 FTRL,uctr 平均提升 3.2%,pctr 平均提升 3.2%。

飛豬的“猜你喜歡”如何排序?

FB-PALM (FeedBack-PALM) 模型

前一個版本在 pure deep 模型上拿到不錯的收益。很自然的想法是嘗試各種點選率深度積木模型,比如 DCN,DeepFM,XDeepFM,PNN,Autoint,FGCNN 等,但是經過幾版實作以及調優,發現這些 model 結構和上一個版本相比提升微弱,如下圖。本來以為是模型複雜度高了,于是對于 FGCNN 多訓練了 20k 步,發現模型處于收斂狀态。猜想原因為目前 pure deep 模型中已經包含了大量高階特征,特征不變的情況下,特征的隐式高階組合已經足夠了,顯示的高階組合帶來的收益較少。

飛豬的“猜你喜歡”如何排序?

但是模型還是要繼續疊代的,于是切換了思路,通過引入原始特征體系中沒有的更多複雜結構特征來實作模型的性能提升。這一版主要添加了使用者短期全網實時寶貝點選序列以及使用者短期場景内寶貝曝光未點選序列特征,序列中的寶貝考慮 Id,目的地,類目, Poi,Tag 以及行為類型和行為次數等屬性。模型結構上沒有太多的創新,對于兩組序列特征,以待推薦寶貝的 Id,目的地,類目,Poi,Tag 綜合起來作為 query,對兩組序列進行 attention pooling。然後将 pooling 的結果加入 Pure deep 的輸入層,其他結構不變。其中對離線名額提升較明顯的幾個點如下:

1)對于序列特征中的寶貝并不是考慮越多的屬性效果會更好,選擇的屬性需要覆寫度高,不然序列中太多的屬性預設值會導緻模型訓練不佳。

2)這裡對于兩組序列,因為同樣采用寶貝 id 特征,是以為了防止過拟合,也加入了動态正則的技巧。但是這裡需要注意的是雖然待推薦寶貝 id,點選寶貝 id 以及曝光未點選寶貝 id 都是寶貝 id,但是由于來源不同,id 出現的頻次也會不同,是以這三類 id 都采用自己各自出現的頻次分布進行動态正則。另外這三類寶貝 id 也都采用不同的 embedding matrix,避免正則之間的影響。

飛豬的“猜你喜歡”如何排序?

下面對模型的核心部分進行較長的描述:

1)對于寶貝次元,模型存在三類資訊,包括點選寶貝行為,曝光未點選的寶貝行為以及待推薦寶貝。除了寶貝id以外,我們将行為類型,目的地,類目,tag,poi 等 side information 加入模型中。這裡融合采用 concat 的方式。令待推薦寶貝的多個特征經過 embedding 之後得到的向量分别為:

飛豬的“猜你喜歡”如何排序?

,其中 L 為特征的類型數,則可以得到待推薦寶貝的表達為:

飛豬的“猜你喜歡”如何排序?

類似的可以得到點選寶貝行為以及曝光未點選寶貝行為的表達為 和 ,其中 M 和 N 分别為點選寶貝行為和曝光未點選寶貝行為的個數。

2)通過待推薦寶貝作為 query,對點選寶貝行為以及曝光未點選寶貝行為進行 attention pooling。這裡由于次元不一緻的原因,采用複雜度較高的加性 attention。attention 的過程如下,其中函數 H 為多層前饋神經網絡。這裡以點選寶貝行為為例,曝光未點選寶貝行為類似。需要注意的是由于這兩類序列資訊意義相差較大,是以兩個 attention pooling 操作參數是不 sharing 的。

飛豬的“猜你喜歡”如何排序?

3)最後将點選寶貝行為以及曝光未點選寶貝行為的 pooling 結果 和 與 pure deep 模型的輸入層特征進行 concat 一起送入到多層前饋神經網絡,輸出最後的打分 logit,并進行相應 loss 計算。

飛豬的“猜你喜歡”如何排序?

上線實驗觀察7天,包括三天正向桶以及四天反向桶,相較于 pure deep 模型,uctr 平均提升 1.0%,pctr 平均提升 1.5%。

飛豬的“猜你喜歡”如何排序?

GLA(Global Local Attention-PALM) 模型

上一個版本主要添加了使用者短期全網實時寶貝點選序列以及使用者短期場景内寶貝曝光未點選序列特征,并拿到了不錯的效果。但是分析特征組成以及模型結構之後,發現還存在一些不足:

1)寶貝行為序列隻能覆寫一部分航旅使用者,另外一部分航旅使用者沒有寶貝相關行為,隻有機票、火車票、酒店等行業下的行為,但是目前模型中考慮的序列還沒有 cover 這部分使用者。

2)上一版模型對寶貝點選序列以及寶貝曝光未點選序列隻是做了加性 attention pooling 的操作,隻考慮了 query(待推薦寶貝)和序列中的每一個元素的相關性。我們還應該考慮序列中每一個元素之間的相關性。

針對上述不足,在這一版本疊代過程中:

1)加入使用者全網行為序列,包括機票,火車票,酒店,寶貝等行業。需要注意的是在實踐過程中,發現全網行為序列中的 id 屬性次元會造成模型的過拟合現象,加入動态正則之後還是沒能緩解。分析原因有可能是 id 屬性在機票、火車票、酒店以及寶貝的混合序列中分布太雜亂,是以去除 id 屬性,隻考慮覆寫度高的目的地、類目、Poi、Tag 以及行為類型等屬性。使用者全網行為序列的 pooling 方式采用在意圖模型中積累的 Multi-CNN + attention 的方式,具體細節可參考飛豬使用者旅行意圖。

2)對寶貝點選序列以及寶貝曝光未點選序列的 pooling 方式,我們采用 transformer + attention 的形式,在原來加性 attention 的上一層,我們先通過 transformer 對序列中個體之間的相關性通過 self-attention 進行描述,然後再通過 attention 進行 pooling。當然和上一個版本一樣寶貝點選序列以及寶貝曝光未點選序列的 pooling network 的參數是不 sharing 的。

飛豬的“猜你喜歡”如何排序?

下面對模型的核心部分進行較長的描述,一些通用性的子產品的細節不詳細介紹。

1)對于使用者全網行為序列,我們隻考慮行為類型,目的地,類目,tag,poi 等覆寫度高的粗粒度屬性,不考慮 id 這一維屬性,防止過拟合。融合的方式采用 concat 的方式。

2)使用者全網行為序列的 pooling 方式采用 Multi-CNN + attention 的方式。通過 Multi-CNN 抽取不同區間範圍内的局部特征(units),同時考慮 local 和 global 資訊。區間越小,更加關注于局部,區間越大,更加關注于全局。比如區間為 1 時,考慮的是 point level。unit 中包含多種目的地類型,包括酒店,寶貝,火車票,機票等。通過 d 個形狀為 d ∗ h 的 filters 對輸入 進行步長為1的卷積,卷積方式為 SAME。經過 m 次類似的操作,每一次操作filter的形狀為 ,最後輸出為 m 個和輸入形狀一緻的序列向量,。因為混合序列的形式,序列長度過長,如果采用RNN的形式一方面計算量大,另一方面長時依賴較弱。然後複用上一版模型中的加性 attention 對 Multi-CNN 抽取出來的多組序列進行 attention pooling,并将 pooling 的結果和 pure deep 模型的輸入層 concat。需要注意的是這裡多組序列的 attention pooling 參數是共享的。

對于點選寶貝行為,曝光未點選的寶貝行為的 pooling 過程,在 attention 之前添加一層 transformer 操作,通過 self-attention 來捕獲序列内個體之間的關系,然後再進行加性 attention pooling。其他的操作不變。

同樣的時間視窗,采用 30 天資料訓練,T + 1 評測,離線名額如下,提升還是很明顯的。這裡和上一版模型的離線結果圖在 AUC 範圍上有所不同是因為切換了時間視窗。

飛豬的“猜你喜歡”如何排序?

上線實驗觀察,相較于 FB-PALM 模型,uctr 平均提升 1.0%,pctr 平均提升 3.0%。

飛豬的“猜你喜歡”如何排序?

其他的嘗試

寶貝的一階近鄰資訊和寶貝 pretrain embedding

前面後兩版模型是在使用者側增加了複雜序列特征,而寶貝側一直很薄弱。是以考慮增加寶貝的一階近鄰資訊和寶貝的 pretrain embedding 向量。一階近鄰通過統計曆史一年使用者 session 行為中寶貝的共現關系來獲得。而寶貝的 pretrain embedding 向量包括文本向量,圖像向量以及基于随機遊走産出的 deepwalk 向量。實驗下來單獨增加這些 trick 和 pure deep 模型相比能拿到很大的提升,但是疊加到後續的模型版本上效果不明顯。應該需要再探索更加精細的融合方式,而不是直接都 concat 到輸入層。兩次實驗結果如下,确實很微弱,是以沒有上線驗證。

飛豬的“猜你喜歡”如何排序?
飛豬的“猜你喜歡”如何排序?

time-aware attention

前幾個版本的模型中 time 的資訊都是通過 side information 的方式加入,類似于 pos embedding。但是 time 的資訊在行為序列刻畫過程中十分重要。調研了一些方法,包括 time-LSTM 等,但是由于 RNN 的計算複雜度太高,也放棄了。後續嘗試将 time 的資訊後置,直接加到 attention 的過程中,在離線表現上有一些收益,但是也不明顯,暫時沒有上線,後續這個也是值得探索的。

飛豬的“猜你喜歡”如何排序?

未來展望

目前飛豬首頁猜你喜歡資料來源非常多,如何在不同資料來源的混合資料集下學習出在多場景下都很 solid 的模型是值得探索的。

目前幾版模型在特征顯示交叉的模型結構上沒有拿到多少收益,後續需要探索這個問題,從特征體系,到模型結構,到資料來源上一起分析這個問題。

繼續閱讀