天天看點

【論文解讀】YouTube采樣修正的雙塔模型論文精讀

「本文概覽」

【論文解讀】YouTube采樣修正的雙塔模型論文精讀

《Sampling-Bias-Corrected Neural Modeling for Large Corpus Item Recommendations》是谷歌在2019年的RecSys上發表的一篇非常具有工業風的論文,介紹了在大規模推薦系統中使用雙塔模型來做召回的一些經驗,值得細細品讀。

1. 這篇文章要解決什麼問題?

大規模推薦系統一般分為兩個階段,即召回和排序階段。本文的重點就在于為一個有百萬量級物品的個性化推薦建構一個召回系統。

給定{使用者,上下文,物品}的三元組,召回模型通用的方法是:

  • 1)分别計算{使用者,上下文} 和 {物品} 的向量表示;
  • 2)利用一個簡單的打分函數(例如點積)來計算二者的比對得分。

“上下文”通常是有動态性質的變量,例如一天裡的時間、使用者的裝置等等。這種基于表示學習的方法通常面臨兩個方面的挑戰:

  • 1)工業級推薦系統的物品集通常很大;
  • 2)從使用者回報中收集的訓練資料通常很稀疏,導緻對長尾内容的預測過拟合。對于cold-start問題,推薦系統需要适應資料分布的變化來更好地推薦新内容(fresh content)。

工業界現有的推薦系統都需要從一個超大規模的候選集中拉取item進行打分排序。解決資料稀疏和大規模候選集分布的一種通用做法是從item的内容特征中學習出item的稠密表示。這裡很自然地就想到了工業界大名鼎鼎且應用廣泛的雙塔神經網絡結構,其中的一塔就是從豐富的item内容特征中學習到item的表示。雙塔網絡結構如下所示:

【論文解讀】YouTube采樣修正的雙塔模型論文精讀

上圖中雙塔模型兩側分别對 {使用者,上下文}  和  {物品}  進行模組化,并在最後一層計算二者的内積。模型訓練好後用圖中的兩個向量

求dot,對相似度高的item做推薦。其中分兩部分:左側user塔後面的user embedding需要在請求來的時候實時計算;右側item塔訓練的時候預計算好,然後灌入一個向量檢索工具中,首先建立索引,然後轉化為一個向量檢索問題,這方面基本做推薦的各家大公司都有自己的開源工具,比如faiss,annoy等。

YouTube将視訊召回看做一個多分類問題,多分類問題中最常使用的激活函數就是Softmax,但是要知道YouTube上視訊素材庫中的視訊數量是巨大的,當類别數量特别大時,使用Softmax來訓練模型是比較耗時的。是以一種常用的方法就是進行采樣,工業界目前采用流式訓練雙塔結構一般是通過随機mini-batch内負采樣的方式來優化損失函數。這種訓練方式存在的一個顯著問題就是in-batch loss會因為随機采樣偏差而導緻模型效果不好,尤其是當樣本分布出現明顯傾斜的時候。這種batch内負采樣的方法具有采樣偏差,無法保證采樣後的分布和原始資料分布是一樣的,這樣模型學習到的将會是錯誤的分布進而影響模型的效果。

為此,作者一方面對損失函數進行了改進(權重對數似然函數),另一方面提出了一種對采樣機率進行自适應修正的算法,可以從流式資料中預估item的頻率。通過理論分析和實驗結果表明,該算法有能力在不知道候選集全部的詞典情況下做出無偏差的估計并且可以自适應候選集分布的變化。随後,作者采用了這種“采樣偏差修正”的方法為 YouTube 建立了一個基于神經網絡的大型檢索(召回)系統,該系統用于從包含數千萬個視訊的語料庫中提供個性化服務。

Microstrong在嘗試采用流式訓練資料做雙塔召回時,思考以下問題:

  • 流式訓練中,batch内随機負采樣效果不佳,如何能拿到item的出現頻次,做Negative Sampling呢?我們知道流式訓練,訓練資料是以滾動的方式輸入到網絡模型中的,我們無法維護一個動态且占高記憶體的詞表及item頻次資訊。如果無法拿到item出現的頻次,就不能準确的進行負采樣操作。
  • 在batch内如何采樣,才能使用batch softmax 損失函數呢?召回場景下batch softmax與交叉墒相比,優勢在哪裡?
  • 當我們進行batch内負采樣的時候,item被采作負樣本的機率約等于其出現在原始樣本中的機率。這樣會導緻一些熱門的受歡迎的item更容易被當成負樣本。而在大多數推薦場景中有很明顯的熱點效應,對于這些熱門item的過度打壓會使得模型傾向于推薦一些冷門的item,進而影響線上表現。是否可以使用這篇論文提出的修正loss解決此問題呢?

以上三個問題,都促使我精讀Google在YouTube視訊推薦中具有落地指導意義的這篇論文。

2. 用了什麼方法解決?

2.1 采樣機率修正

整個召回系統采用的是雙塔結構,即分别建構使用者側的Embedding和視訊側的Embedding,兩個塔的輸出就是各自的embedding向量,最終模型的輸出為兩個Embedding内積後的結果,即:

θ

θ

假設有

條訓練樣本,模型的目标是從這些訓練樣本中學習模型參數

其中,

表示使用者特征和上下文特征,

表示物品特征,

這篇論文将視訊召回看做一個多分類的問題,通常各個類别的權重都為

,但是在該場景中,論文中引入了一個使用者偏好的權重

(使用者觀看某視訊的播放比例)。給定一個使用者

,從

個物品的候選集

基于上述Softmax函數的輸出和使用者偏好權重,損失函數采用權重對數似然函數的形式,具體如下:

「接下來就是這篇論文的第一個核心點了」,上述的做法相當于把該樣本中的

作為正樣本,其餘所有的物品當作負樣本。當視訊素材庫的視訊數量巨大時(

非常大),計算上述的Softmax函數是十分低效且不太現實的。一種通用的做法是通過随機mini-batch的方式來優化損失函數。假設一個包含

這種做法相當于把一個batch中此條資料之外物品當作負樣本。但是這種做法存在的缺點就是會因為随機采樣偏差而導緻模型效果不好。對于熱門物品來說,由于采樣到的機率非常高,當作負樣本的次數也會相應變多,熱門物品會被“過度懲罰”。是以論文對user和item的embedding向量計算得到的内積

上式中,

代表第

條樣本對應的物品

在一個mini-batch中被采樣到的機率。這裡埋下一個伏筆,

以及修正後的損失函數如下所示:

然後利用優化器SGD進行參數的更新。具體的模型訓練算法如下所示:

【論文解讀】YouTube采樣修正的雙塔模型論文精讀

「上述模型訓練過程可以歸納為:」

  • 從實時資料流中得到一個batch的樣本;
  • 基于下文即将提到的采樣機率估計算法得到采樣機率
  • 計算上文介紹的修正後的損失函數;
  • 利用SGD更新模型參數;

2.2 Streaming Frequency Estimation

「這篇論文的第二個核心問題是如何得到

和 設計一個算法維護更新

上文中提出的采樣機率修正方法,核心思想在于通過采樣頻率來估計采樣機率,如果某個item的采樣頻率為

,則其采樣機率為

,按照這樣的想法,

其中,

代表什麼呢?

又是一個怎麼的函數呢?這裡我猜測

肯定代表

的采樣頻率,帶着這些問題,我們接着看

由于YouTube中采用流式訓練,是以不斷會有新物品出現,那麼使用固定長度的詞表不太合适,是以采用

的方式來對物品的采樣機率

具體來說,首先定義一個

函數

,把所有視訊

都映射到

之間。這裡

一下是因為視訊是動态的,随時都可能有新的視訊進入系統,是以用

函數映射一下固定住視訊庫大小。同時使用兩個長度為

的數組

,通過

來得到給定的

在數組

  • : 表示
  • : 表示

當第

步物品

被采樣到,基于如下的公式更新

其中,

則被賦予目前的訓練步數

。當訓練完成時,預估的物品

的采樣機率是

。從數組

的定義可以看出,

越小,即在訓練樣本中采樣到的機率越高,比如

,每兩次就會被采樣到一次,那麼

會比較大,就代表比較熱門。接着就是更新

,其中

可看作學習率,剩下的就是帶入到損失函數

θ

這裡還有一個問題,既然是

過程,當

時,就會存在沖突的情況。沖突的情況會導緻

較小,因為

會較小,進而導緻采樣機率預估過高。這裡的改進方案是使用​

​Multiple Hashings​

​。即使用多組

方程和數組

。當訓練完成後,線上推理時,使用最大的一個

當然論文裡還給出來了"Streaming Frequency Estimation"算法的分布式計算方法,這裡把用于估計流式資料中,每個batch下item被采樣的機率的算法引申到深度學習的分布式訓練中,真的是把這個算法運用到工業中落地的細節也講到了,想詳細了解這一塊的知識可以讀原論文。

這裡說到分布式訓練模型,我就想給大家聊一下分布式訓練在工業界的重要性。我們都知道,現在稍微複雜的業務,都是分布式訓練模型的。這裡我必須要強調一下,在工業界中大規模分布式推薦算法工程師的一些必備技能:

  • 「對分布式架構的了解。」 掌握分布式訓練這個技能非常重要,比如Tensorflow架構中的ps/worker/chief是怎麼協同工作的,參數更新在哪裡,模型訓練在哪裡,模型同步訓練還是異步訓練,分布式訓練架構通信問題等等。
  • 「PySpark/Scala的熟練使用。」 Spark是非常強大的處理大規模資料的工具,為模型準備訓練資料非常友善,與Hive SQL的互動也十分友善。是以熟練使用Pyspark、Scala處理大規模訓練資料非常的重要。
  • 「Hive SQL。」 這是工作中使用頻次很高的語言,推薦算法工程師有時也需要從大規模資料中使用Hive SQL發現問題、分析問題。這也是我們常說的推薦算法工程師要有強烈的資料敏感性。

2.3 一些Tricks

(1)「最近鄰搜尋」:當Embedding映射函數

(user塔或query塔)和

  • 計算query的向量
  • 從事先訓練好的函數

在實際工程中用雙塔模型做大規模物品召回,item塔産出的item Embedding得先灌入faiss中。線上實時得到user Embedding,然後去faiss中計算相似度,實作u2i召回。

(2)「歸一化」:經驗表明,對兩側輸出的Embedding進行

(3)「對于内積計算的結果,除以一個固定的超參

」:

除以超參的效果是把Softmax的結果變得更加明顯(sharpen),通過對超參

的微調可以使召回率或精确率變的更好。這裡溫度

和知識蒸餾中溫度超參的出現位置和作用是一樣的。關于溫度超參

  • 深度學習中的知識蒸餾技術(上),位址:https://mp.weixin.qq.com/s/E7-MF18Y-UeKx694kGFHzA

3. 模型結構與線上部署

實際中的YouTube雙塔到底是怎麼用的?整個召回的模型網絡如下圖所示:

【論文解讀】YouTube采樣修正的雙塔模型論文精讀

将模型分為兩個塔,查詢塔(包含上下文特征和使用者特征)和物料塔,這個模型使用大量的seed video特征和使用者觀看曆史來訓練模型。seed video features 是指使用者正在觀看的視訊所具有的屬性,某種程度上表征了使用者目前的興趣。

3.1 訓練标簽

點選視訊為正樣本。

是一個乘到每個樣本的

上的權重系數,論文中解釋這個系數代表播放進度,如果

秒視訊看了

秒則

,權重的初衷是播放進度越長則表明喜好程度越大,配上點選

「這裡引申出一個問題:在視訊推薦場景中的召回階段,用論文中定義的含權重

這裡我覺得可以換個思路嘗試一下,因為像視訊推薦場景我們可能會用完播/播放百分比/播放時長等目标,完播、播放百分比往往會偏好短視訊,播放時長會偏好長視訊,一般都需要做消偏處理,把點選目标和播放百分比目标結合到一起反倒是不好消偏了。而且這種召回有點不倫不類,線上召回本身就是多路,完全可以将一路召回拆成點選召回和播放召回兩種單獨做優化,更能展現召回的本質——從多個角度初篩可能感興趣的候選。

「更近一步的考慮另外一個問題:像視訊推薦場景我們可能會用完播/播放百分比/播放時長等目标,完播往往會偏好短視訊,播放時長會偏好長視訊,那麼也需要做debias,有沒有什麼好辦法來消偏呢?」

方法就是統計後驗的名額做消偏,即不是對長視訊權重,是對該視訊消費時長減去相同時長視訊大盤消費時長,對diff權重。

3.2 視訊特征

視訊特征有諸如視訊id、頻道id之類的類别特征,也有連續特征。類别特征分為單值類别特征(如 video id)和多值類别特征(如 video topic)。單值類别特征,視訊id、頻道id等特征轉化為embedding,對于多值類别特征,采用對其多值embedding權重求和的方式得到最終的embedding。

這裡的channel id不是指的體育/美食這種頻道,而是類似于作者id的東西,理由是打開每個視訊的作者,其url連結是http://www.youtube.com/channel/***。

【論文解讀】YouTube采樣修正的雙塔模型論文精讀

3.3 使用者特征

使用者特征主要是基于使用者的曆史觀看記錄來捕獲使用者的興趣,比如說,使用者最近看過

對于ID型的類别特征,embedding在模型的兩側是共享的。比如,視訊id,兩個塔進行共享,更好的學習,保證兩個塔在一個空間内。

「這裡再抛出一個問題:video id共享embedding的原因是什麼,共享是最優解嗎?」

模型結構圖中有多處用到了video id,比如使用者觀看曆史/正在看的seed video/候選集合。由于都是一個video id的embedding,很容易想到share embedding。我認為這個insight初衷應該是兩個,其一能夠降低ps存儲壓力,其二是讓embedding學習得更加充分。YouTube實驗發現share與否對結果沒啥影響,那幹脆share還能減資源。

我自己一直都是把能share embedding的ID類特征盡量share embedding,以避免線上服務模型太大,造成線上更新耗時太多的問題。但是,@iwtbs 在文章《借Youtube論文,談談雙塔模型的八大精髓問題》(位址:https://zhuanlan.zhihu.com/p/369152684)中提到自己的經驗是share embedding會讓預估效果變差,因為嚴格意義上來說并不完全是一個空間,是以這個點他持懷疑态度。最終要不要share還是得自己試試才知道,即使效果好也要考慮效果和存儲資源trade-off的問題。

3.4 線上服務

模型基于Tensorflow實作,并且進行了分布式實作。同時,YouTube 每天都會生成新的訓練資料集,模型也會以天為機關進行更新,這樣模型便能适應最新的資料分布變化。

infer階段就跟普通的DNN召回類似,将全量的視訊的embedding計算好,然後線上實時生成查詢塔的embedding,通過faiss等工具進行topK的查詢。

通過雙塔的結構和采樣校正,YouTube實作了又快又準的召回,YouTube雙塔召回同樣也運用在廣大公司的線上業務中,并且效果還不錯。這裡列舉一些工業界的實踐案例:

  • 向量化召回在360資訊流廣告的實踐 - 被包養的程式猿丶的文章 - 知乎 https://zhuanlan.zhihu.com/p/93257390
  • [58同城]深度召回在招聘推薦中的挑戰和實踐,位址:https://mp.weixin.qq.com/s/mcETNOICbabRRq9BBdL4zw

4. 效果如何?

論文的實驗部分向我們展示了item frequency estimation算法和模組化架構的有效性,離線和線上的評估結果都有提升。總的來說,這篇文章便于實作,可以從字裡行間看到很多實踐出真知的影子,也是對經典知識在實踐中改進的例子,是一篇工程性很強的文章。

5. 總結

論文詳細介紹了工業界應用雙塔DNN模型解決大規模視訊召回場景下的問題,詳細介紹了雙塔模型在使用時的一些 Tricks,包括流式資料進行中的采樣機率修正,使用

等技術來提高檢索效率,Embedding歸一化提高準确率,加入超參

最後,借此機會我們來回顧YouTube的三篇重要的實踐論文:

  • (1)首先是YouTube的深度學習開山之作《Deep Neural Networks for YouTube Recommendations》,這是深度學習在推薦領域的首次工業應用,這篇文章野心很大,将召回和排序都囊括進整篇論文。關于這篇論文的解讀,推薦大家讀以下兩篇文章:
  • 重讀Youtube深度學習推薦系統論文,字字珠玑,驚為神文 - 王喆的文章 - 知乎 https://zhuanlan.zhihu.com/p/52169807
  • YouTube深度學習推薦系統的十大工程問題 - 王喆的文章 - 知乎 https://zhuanlan.zhihu.com/p/52504407
  • (2)其次是YouTube的雙塔召回《Sampling-Bias-Corrected Neural Modeling for Large Corpus Item Recommendations》,進一步優化解決召回的冷啟動、長尾等問題。
  • (3)最後是MMoE的應用文章《Recommending What Video to Watch Next: A Multitask Ranking System》,該論文主要聚焦于大規模視訊推薦中的排序階段,介紹一些比較實在的經驗和教訓,涉及到對多個目标進行模組化和解決 Selection Bias這兩個排序系統的關鍵點。關于這篇論文的詳細解讀,推薦大家閱讀這篇文章:
  • 多目标學習在推薦系統中的應用,位址:https://mp.weixin.qq.com/s/c7BdWUM9BFQZfzWP7C_wfQ

可以看到,這三篇論文代表了推薦系統中最重要的兩個子產品——召回和排序的演進,在搭建推薦系統的過程中,也可參照這個流程去搭建适合自己業務的架構。

6. 關于這篇論文的若幹問題的思考

在文章開頭部分,我提出了自己在嘗試采用流式訓練資料做雙塔召回時,思考的三個問題,現在嘗試一下自己給自己答疑。

(1) 流式訓練中,batch内随機負采樣效果不佳,如何能拿到item的出現頻次,做Negative Sampling呢?我們知道流式訓練,訓練資料是以滾動的方式輸入到網絡模型中的,我們無法維護一個動态且占高記憶體的詞表及item頻次資訊。如果無法拿到item出現的頻次,就不能準确的進行負采樣操作。

「引申出問題:要回答這個問題,我們首先需要清楚召回階段為什麼需要采樣?以及現在流行的采樣方法有哪些?batch内随機負采樣到底是如何做的?」

這個問題的答案來源于:SENet雙塔模型:在推薦領域召回粗排的應用及其它 - 張俊林的文章 - 知乎 https://zhuanlan.zhihu.com/p/358779957

我們訓練精排模型的時候(假設是優化點選目标),一般會用“使用者點選”執行個體做為正例,“曝光未點選”執行個體做為負例,來訓練模型,基本大家都是這麼做的。現在,模型召回以及粗排,也需要訓練模型,意思是說,也需要定義正例和負例。一般正例,也都是用“使用者點選”執行個體做為正例,但是怎麼選擇負例,這裡面有不少學問。

【論文解讀】YouTube采樣修正的雙塔模型論文精讀

我們先來看下不同階段模型面對的輸入資料情況,對于召回模型來說,它面臨的輸入資料,是所有物料庫裡的物品;對于粗排模型來說,它面對的輸入資料,是各路召回的結果;對于精排模型來說,它面臨的輸入是粗排模型的輸出結果。如果我們仍然用“曝光未點選”執行個體做為召回和粗排的負例訓練資料,你會發現這個訓練集合,隻是全局物料庫的一小部分,它的分布和全局物料庫以及各路召回結果資料差異較大。即,召回和粗排模型面臨的實際輸入資料與采用“曝光未點選”執行個體做為負例訓練資料,分布差異比較大。是以根據這種負例訓練召回和粗排模型,效果如何就帶有疑問,我們一般把這個現象稱為“Sample Selection Bias”問題。

為了解決“Sample Selection Bias”問題,我們在召回或者粗排模型訓練的時候,應該調整下負例的選擇政策,使得它盡量能夠和模型輸入的資料分布保持一緻。這裡 @張俊林(知乎ID)老師簡單歸納下可能的做法。

「選擇1: 曝光未點選資料」

這就是上面說的導緻Sample Selection Bias問題的原因。我們的經驗是,這個資料還是需要的,隻是要和其它類型的負例選擇方法,按照一定比例進行混合,來緩解Sample Selection Bias問題。當然,有些結論貌似是不用這個資料,是以用還是不用,可能跟應用場景有關。

「選擇2: 全局随機選擇負例」

就是說在原始的全局物料庫裡,随機抽取做為召回或者粗排的負例。這也是一種做法,YouTube DNN雙塔模型就是這麼做的。從道理上講,這個肯定是完全符合輸入資料的分布一緻性的,但是,一般這麼選擇的負例,因為和正例差異太大,導緻模型太好區分正例和負例,是以模型能學到多少知識是成問題的。

「選擇3: Batch内随機選擇負例」

就是說隻包含正例,訓練的時候,在Batch内,選擇除了正例之外的其它Item,做為負例。這個本質上是:給定使用者,在所有其它使用者的正例裡進行随機選擇,構造負例。它在一定程度上,也可以解決Sample Selection Bias問題。比如Google的雙塔召回模型,就是用的這種負例方法。

「選擇4: 曝光資料随機選擇負例」

就是說,在給所有使用者曝光的資料裡,随機選擇做為負例。這個我們測試過,在某些場景下是有效的。

「選擇5: 基于Popularity随機選擇負例」

這種方法的做法是:全局随機選擇,但是越是流行的Item,越大機率會被選擇作為負例。目前不少研究證明了,負例采取Popularity-based方法,對于效果有明顯的正面影響。它隐含的假設是:如果一個例子越流行,那麼它沒有被使用者點過看過,說明更大機率,對目前的使用者來說,它是一個真實的負例。同時,這種方法還會打壓流行Item,增加模型個性化程度。

「選擇6: 基于Hard選擇負例」

它是選擇那些比較難的例子,做為負例。因為難區分的例子,很明顯給模型帶來的

以上是幾種常見的在召回和粗排階段選擇負例的做法。

「正式回答自己提出問題:」 看到這裡這個問題就相對簡單了,論文提出的“Streaming Frequency Estimation”算法,不就是為了解決流式訓練中,沒有固定的詞表,得不到item的頻次資訊,而提出的預估item采樣頻率的算法麼。在流式訓練中可以直接抛棄Negative Sampling算法,采用“Streaming Frequency Estimation”算法。

(2)在batch内如何采樣,才能使用batch softmax 損失函數呢?召回場景下batch softmax與交叉熵相比,優勢在哪裡?

「回答第一小問:」 上面提到的“Batch内随機選擇負例”的辦法,就可以直接使用batch softmax 損失函數。

「回答第二小問,答案來源于」:借Youtube論文,談談雙塔模型的八大精髓問題 - iwtbs的文章 - 知乎 https://zhuanlan.zhihu.com/p/369152684

交叉熵實際上就是模組化為二分類問題,這種興趣絕對值是point-wise。召回本身需要負采樣,在不建構hard-negative情況下流式訓練一般維護一個實時更新的他人正例采樣池,如果負樣本難度不夠大(往往都不夠大)其實最後auc會學得很高,拟合效果未必學的好;而精排由于是準确的正負樣本用二分類剛剛好。

batch softamx則是把batch内的所有樣本作為彼此的負樣本,這種采樣的方式強依賴于batch的分布,會帶來非常大的bias。batch softmax模組化的是相對興趣pair-wise,但是還是同樣的問題,負樣本過于簡單比較相對興趣也沒特别大意義?而且看很多人都提到在推薦領域用pair-wise不如point-wise,搜尋用pair-wise更好,是以之前我也一直沒試,相比較margin hinge loss這種方式多加了一個門檻值更說得通。

(3)當我們進行batch内負采樣的時候,item被采作負樣本的機率約等于其出現在原始樣本中的機率。這樣會導緻一些熱門的受歡迎的item更容易被當成負樣本。而在大多數推薦場景中有很明顯的熱點效應,對于這些熱門item的過度打壓會使得模型傾向于推薦一些冷門的item,進而影響線上表現。是否可以使用這篇論文提出的修正

答:由于大多數推薦場景的物品都服從長尾分布,是以在batch内負采樣的時候,對于熱門物品來說,由于采樣到的機率非常高,當作負樣本的次數也會相應變多,熱門物品會被“過度懲罰”。是以論文對user 和 item的 embedding向量計算得到的内積

進行了logQ修正,可以使用這篇論文提出的修正

7. Reference