推荐系统避坑指南
寫在前面的話
大家好鴨,我是時晴,跟著師傅學習推薦算法煉丹有一段時間了,過程中遇到了很多奇奇怪怪的問題。我想很多和我一樣初入推薦領域的同學,都多多少少有跟我同樣的經歷和體會。不管項目大小,也不論推薦什么東西,只要你做過和推薦系統相關的項目,你就會多多少少的遇見過坑兒,所以,作為自己煉丹道路上的一份筆記,本文幫大家歸納整理了一下推薦系統里的那些坑兒,都是知乎大佬們曾經的真實經歷(當時自己記筆記的同時做了一些調整和修改,嘻嘻),整理分享給大家,希望對煉丹路上遇到困惑的你能有所幫助。
壹號坑:線上線下不一致問題
1. 特征不一致
這種在離線拼接樣本和特征的Pipeline中比較常見。一般離線特征都是按照天處理的,考慮各種數據pipeline的流程,處理時間一般都會有延遲,離線特征處理完之后導到線上之后,用于線上模型預估時請求使用。那這種情況產生的原因是什么呢?在離線,我們使用T-n到T-1的數據訓練模型,用T天的數據進行測評,拿到了很好的離線指標,比如AUC為0.82。但是在線服務的模型,并不是這樣的理想情況,一個模型每天重新迭代訓練,需要新一天(T-1天)的日志,日志從數據隊列傳輸到大數據平臺,進行日志的處理,新一天各種特征的計算,組織訓練樣本,進行模型訓練,之后還要把模型從大數據平臺更新到在線服務器,整個流程走下來幾個小時過去了。那么在新模型上線前,在線服務的是T-2的模型,相當于在離線用T-2的模型去測評T天的樣本,效果會大打折扣。因而線上一整天的平均測評指標,是低于離線測評指標的。
舉個例子,例如12月15日這天,線上預估請求用的特征是12月14號的特征數據。到了12月16日,特征Pipeline開始處理數據,到了凌晨5點(有時候ETL作業集群有問題可能會到中午12點),離線特征處理完了導到線上。那么在12月16日0點-2月16日5點,這段時間線上請求的特征使用的是老的特征數據,也就是12月14日的特征數據。12月16日5點-12月16日24點,線上特征使用的是12月15日的數據。而在離線樣本生成過程中,到了12月17日0點,如果是按天拼接的,那么12月16號這天的所有樣本,都會使用12月15日的特征。
這樣,12月16日0點--2月16日5點的樣本,在離線樣本拼接的階段,使用的是12月15日的特征數據,而在線上請求特征的時候使用的還是12月14日的特征。特征Pipeline流程處理越長,這種不一致會越大。
那么問題來了,如果換成實時數據進行實時特征加工是不是就解決這個問題了?
實時特征在線使用的時候,經過客戶端埋點的上報(這些先不考慮埋點系統的各種坑),流式計算處理日志數據進入在線數據源或特征庫,需要經過一段時間。也就是說,如果你剛剛點擊了某個“豪車、豪宅”視頻,緊接著下滑翻頁,系統是拿不到“豪車、豪宅”這個行為的。如果離線模型訓練中有用到了帶有“豪車、豪宅”的特征,由于近期行為的影響非常大,那么離在線的不一致會非常嚴重。
2. 數據分布不一致
如果仔細排查,既不存在數據泄漏,也沒有出現不一致的問題,離線auc明明就是漲了很多,線上就是下降,而且是離線漲的越多,線上下降越多,還有一種可能就是數據的不一致,也就是數據的“冰山效應”——離線訓練用的是有偏的冰山上的數據,而在線上預估的時候,需要預測的是整個冰山的數據,包括大量冰面以下的數據!
這種情況其實在推薦系統里非常常見,但是往往非常的隱蔽,一時半會很難發現。我們看下面這張圖。左邊是我們的Baseline,綠色的表示正樣本,紅色表示負樣本,灰色部分表示線上由于推薦系統的“偏見”(預估分數較低),導致根本沒有展現過的數據。
關于推進系統的偏差問題,之前的《推薦系統Bias大全》一文已經總結了推薦系統中所有Bias情況,有興趣的可以跳轉看一下。
離線階段,我們通過各種優化,新模型的離線評估表現更好了,例如圖中第二列,可以發現第4個綠色的正樣本和第7個綠色的正樣本排到了第3和第6的位置,離線的auc指標漲了。
到了真正線上的預估也就是第三列,發現對于這部分離線見過的樣本,模型的預估序并未改變。但是新模型給了灰色沒有見過的數據更高的預估分數,這部分數據一旦表現不好,很可能造成我們前面說的情況,離線(第二列)評估指標明明漲了不少,在線(第三列)評估指標CTR卻下降。
這種情況也不是必現的,在LR以特征工程為主要迭代的時代很少見。主要的原因是模型的前后迭代差異并不大。新模型對比老模型最主要的特點是新加入了一部分特征,往往模型的打分差異并不大,從圖中第二列到第三列,原來那些冰山下的數據也就是舊模型預估分數偏低的部分,在新模型中能夠脫穎而出拿到很高的預估分數的概率并不高。
而在模型有較大變化的時候,例如lr->樹模型,lr->深度模型,不同網絡結構的深度模型變化,這種情況容易出現,原因就是新舊模型的變化較大,預估分數變化也較大。
舉一個簡單的例子,假設我們的baseline是熱門模型,樣本都是老的熱門模型生產出的熱門樣本,這個時候我們用簡單的lr模型去擬合,到了真正的線上預估的時候,對于大量之前沒見過的非熱門的數據,模型自然很難預估好。沒有足夠好的樣本,模型也很難學到足夠有用的信息。
說另一個很有意思的現象,之前在某個組的時候,兩個team優化同一個場景,大家用的回流樣本都是一樣的,但是特征和模型都是自己獨立優化和迭代。有意思的是,如果一個team的優化取得了比較明顯的提升之后,另一個team哪怕什么都不做,過一段時間效果也會慢慢漲上來。
對于這種情況,最根本的手段就是解決數據的有偏問題。尤其是新模型,一開始相當于都是在擬合老模型產生的樣本,剛上線效果如果比較差,經過一段時間迭代,影響的樣本分布慢慢趨近于新模型,也能收斂,但效率較低。這里給下兩個在我們這還比較有效的經驗:
這里的無偏是相對的,可以是隨機/探索流量產生的樣本,也可以是新模型產生的樣本。大概意思,就是盡可能利用這些對新模型有利的樣本。
比較trick的方法,沒有太多方法論,但是確實能work。
新模型預估分數PCTRnew 和老模型預估分數PCTRold 直接在線上做線性融合,剛上線的時候a選取比較小,隨著慢慢迭代,a慢慢放大。
貳號坑:評估指標里問題
在《推薦系統采樣評估指標及線上線下一致性問題》一文中,主要闡述了該部分的觀點:
- 在評估推薦算法的效果時,能不采樣就不采樣!
- 除了AUC, Precision@K, Recall@K, Average Precision, NDCG都是不一致的,采樣計算得到的結果和真實結果可能差很大!
- 現在隨機采樣計算得到的評估指標的分數具有高偏差,低方差的問題,很多情況和真實情況不符合,結論可能也都錯了!
- 如果一定要進行采樣計算評估指標的值, 建議采用文中提出的糾正的方案,雖然可能會有較大的方差,但是偏差大大降低,更加接近真實情況;
舉個例子,比如在信息流推薦中,低俗內容和標題黨往往會在短期內對CTR指標有較好的提升,但是這些內容對整個生態在長期來看是有害的,如何處理這部分內容是值得思考的問題。又比如在電商推薦中,如何處理重復推薦也是一直都存在的問題。
推薦系統太難了。難到工程師和產品都還沒清楚自己要的是什么。“推薦”這個問題本身都不是well-defined的。按照道理來講,推薦系統要做的事情其實是“推薦用戶希望看到的東西”,但是“用戶希望看到的東西”落實到指標上,可就讓人頭大了。
以內容推薦為例。你說究竟要得到什么呢?
- 高CTR?那么擦邊球的軟色情以及熱門文章就會被選出來
- 高Staytime?那么視頻+文章feed流就成為為視頻feed流和超長文章feed流
- 高read/U?那么短文章就會被選出來
這些指標相互依賴,此消彼長,目前主流是沿用計算廣告的老路,按照CTR作為最廣泛使用的評價指標來優化,這個指標的劣根性是顯而易見的,然而至今并沒有很好地指標來指導系統。
今日頭條的做法是,優化CTR同時關注其他指標的變動;也有的從CTR開始,優化到瓶頸后進行Staytime的優化等等...
Medium的做法是,優化一個f(CTR, staytime,...)的多指標加權的綜合指標,但是據我所知,這個加權的系數,還是一個magic number,是人拍腦門定的。
大家都在探索, 也并沒有一個定論,究竟推薦系統該優化一些什么。
相信很多人剛入行的時候對單純優化CTR都是有疑惑的,日子久了,也就都麻木了。
叁號坑:推薦系統健康度問題
推薦系統應該是一個良性循環的系統。這也就導致了E&E, exploration & exploitation問題的出現,簡單說,就是保證精準推薦的同時,進行興趣探索。
一說大家都明白了,這不就是所有推薦系統做的最差的地方嗎?我看了一個東西,就使勁出一個東西,App明明很多東西,我卻越用越窄。
這個問題更加玄學,更加讓人無奈。
EE要不要做?肯定要做,你不能讓用戶只能看到一類新聞,這樣久了他的feed 流只會越來越小,自己也覺得沒勁,所以一定要做興趣探索。
但是做,就勢必犧牲指標,探索的過程是艱難的,大部分時間用戶體驗上也是負向的。那么,
- 犧牲多少CTR來保EE才算是合適的?
- EE的ROI什么時候算是>1的?
- 怎么樣確定EE的效果?
- EE要E到什么程度?
其實大家也都沒有想清楚,多避而不談。
肆號坑:工程里的一些坑
模型工程
系統工程
群坑亂舞:踩坑合集
看過了推薦系統在各種情況下的那些坑兒,最后,放一下 吳海波@知乎 的總結。
- i2i/simirank等相似計算算法中的哈利波特問題,相似性計算在推薦系統的召回起到非常重要的作用,而熱門物品和用戶天然有優勢。因此,處理方法基本上都是憑經驗,會出現各種magic number的參數。
- svd/svd++等算法,在各種比賽中大放異彩,但是據我所知,各大互聯網公司中基本沒有用它的。
- i2i及它的各種變種真是太好用了,大部分公司的業務量,從ROI來看,其實沒有必要再做什么優化了。
- 推薦的召回策略多優于少,但系統的計算rt是個問題,沒有好的系統架構,也沒有什么優化空間。
- i2i等類似計算算法,實際業務中容易跑掛,比如用spark就容易oom,很容易發生傾斜,處理起來又有很多trick和dirty job。
- 推薦系統不只有召回,召回后的ranking起到非常大的作用,這個和廣告的點擊率預估有點像。
- 非常多的業務沒有辦法向頭條/facebook之類的有穩定的用戶留存指標,而留存是推薦系統非常重要目標,因此需要找各種折中的指標去知道abtest。
- 訓練樣本穿越/泄露問題,即在訓練的特征中包含了測試集的樣本的信息,這個是初期非常容易犯的錯誤,在后期有時也會隱秘的發生。
- 大部分推薦系統的訓練數據需要在離線條件下去拼接,其中用戶的行為狀態和時間有關,拼接非常容易出問題,因為系統當時的狀態會有各種狀況(延時、數據不一致)等,導致訓練和實際在線的數據不一致,建議把訓練需要的日志在實際請求中直接拼接好打印落盤。
- 最后,算法的作用有點像前輩們講的:短期被人高估,長期被人低估。按目前國內業務方對算法有了解的特別少,算法對生態的長短期影響,只能靠算法負責人去判斷,因此,就算你只是個打工的,請有一顆做老板的心。
參考資料
總結
- 上一篇: 2020年搜索推荐系统论文干货集锦
- 下一篇: java信息管理系统总结_java实现科