zz京東電商推薦系統實踐

 

挺實在算法

 

 

今天爲你們分享下京東電商推薦系統實踐方面的經驗,主要包括:架構

  • 簡介
  • 排序模塊
  • 實時更新
  • 召回和首輪排序
  • 實驗平臺

簡介

說到推薦系統,最經典的就是協同過濾,上圖是一個協同過濾的例子。協同過濾主要分爲倆種:user-based 基於用戶的協同過濾和 item-based 基於商品的協調過濾。框架

可是,如今絕大多數推薦系統都不會直接使用協同過濾來作推薦。目前主要用的是 learningtorank 框架。分佈式

這裏,是推薦系統的框架,整個推薦系統能夠分爲兩部分,在線部分和離線部分。函數

  • 在線部分主要負責當用戶訪問時,如何把結果拼裝好,而後返回給用戶。主要模塊有召回、排序和對結果的調整。
  • 離線部分主要是對用戶日誌的數據分析,應用於線上。

整個推薦系統大概就是這樣的一個框架。工具

和新聞、視頻這類的內容推薦相比,電商推薦系統又有一些特殊的地方,好比:性能

優化方向(點擊、銷售額、時長、用戶留存等)。另外,電商中推薦的內容也會有不少種,尤爲像是活動類的內容,不少推薦都是算法和人工運營共同完成的。這就是電商推薦和新聞推薦等的區別之處。學習

咱們展開看下在線推薦系統:優化

除了剛纔說的召回和排序以及最終的調整以外,還有實踐過程當中的一些細節。3d

  • 召回:這裏召回會有不少種方法,如協同過濾,熱門商品、實時促銷等和應用場景相關的召回,還有一些基於 KNN 的召回。
  • 過濾:召回以後,會進行過濾,主要是和應用場景相關,如已購商品過濾掉、沒有庫存的過濾掉,或者敏感的商品過濾掉等等這些邏輯。
  • 排序:排序目前主要用到的是 DNN 模型,某些流量比較小的地方會用到 GBDT。
  • 過濾:排序以後還會有些分頁、同商品過濾等邏輯。

調整:最終調整過程當中,主要有兩部分邏輯,多樣性和探索邏輯。

排序模塊

1. 模型結構

深度學習 ranking 模型結構咱們不做爲重點討論,這裏列舉了一種最經典的模型,它們都用到了不少 id 的 Embedding,而後這些 Embedding 規模都很大,這樣訓練和上線都比較耗時。所以,咱們作了一些優化,好比作分佈式的訓練,而且會有一套 Pipeline 來完成模型的上線。另外,雖然模型很複雜,而且能帶來很好的效果,可是特徵工程仍是必不可少的,不少指標的提高仍是依賴於特徵工程,固然也包括一些模型調整的工做。

2. 實踐

那麼如何把這些模型落地呢?咱們看下整個模型的上線過程:

首先最重要的部分是模型訓練平臺和排序服務,由於不少深度模型計算量要求很高,爲了能達到比較快的效果,須要部署單獨的排序服務。目前比較流行的是 TensorFlowserving,能夠很快速的來上線一個深度模型,並充分利用對分片、單機並行,達到很高的計算效率。

模型線上線下一致性問題對於模型效果很是重要,咱們使用特徵日誌來實時記錄特徵,保證特徵的一致性。這樣離線處理的時候會把實時的用戶反饋,和特徵日誌作一個結合生成訓練樣本,而後更新到模型訓練平臺上,平臺更新以後在推送到線上,這樣整個排序造成了一個閉環。

3. 實時更新

咱們的特徵和模型都須要作實時的更新。由於咱們常常須要很快的 catch 一些實時的信號,好比須要實時的用戶畫像來抓住實時的用戶興趣的變化,還好比須要抓住實時的商品畫像,由於常常會有一些活動或者爆品,咱們須要快速的捕捉這些信號,並應用到推薦中。另外還有一些實時的召回和特徵,好比一些交叉的特徵,實時的點擊率,實時訂單等特徵。

除了特徵外,模型也須要實時更新,對於電商場景來講這是有必定困難的,由於訂單是有延時的,延時多是十幾分鍾到十幾小時不等,這樣實時模型更新上就會採起一些保守的策略,好比用點擊率對模型作些微調,而後訂單數據再經過離線來得到,這屬於業務場景的限制。

思考

排序能夠算是推薦系統中比較重要的一個環節,可是隻有排序確定是不夠的,事實上,有一些問題是目前的排序框架沒法解決的:

  • 排序獲得的結果很是類似,影響體驗。
  • 有多個優化目標,須要一個平衡(點擊率、訂單金額、用戶交互時長等)。
  • 計算能力有限,若是有無限的計算力,能夠直接對所有候選集進行排序。

1. 多樣性

使用模型輸出的結果通常都會很是類似,若是直接給用戶看體驗會不好,所以在模型以後咱們須要加入多樣性的邏輯。

比較通用的解決辦法是多樣性的 ranking,這是一個貪心算法,從第一個商品開始選,當選第二個商品的時候,會從新計算下候選集中每一個商品的 score,而後選擇一個 score 最高的。咱們的方法是看 noveltyscore 候選商品的產品詞分佈和以前 N 個商品的產品詞分佈的 KL 距離。這樣作的思路,就是選一個和已有商品最不像的商品,來更好的保證商品推薦結果的多樣性。

因爲純基於算法的多樣性可能會出現 badcase,所以還須要一個規則來進行兜底,確保在極端狀況下結果也能接受。

最後,咱們思考一個問題,有沒有更好的方法實現多樣性的邏輯呢?固然有,好比是否能夠考慮使用 listwiseranking。這裏只是爲你們分享一個比較容易的,而且效果比較好的方法。

2. 多目標

咱們的優化目標有不少,好比點擊、轉化、時長等,問題會變得比較複雜,單一的模型訓練很難覆蓋到全部指標。另外,常常咱們須要在各個指標之間進行權衡,所以可調試性也很是重要。

一種頗有用的方式是多模型 ranking,而後用某種方式把全部模型的結果 combine。

這也體現了一個思想,在算法的實際應用中,其實須要在算法的先進性和系統可維護性、可調試性之間作一個平衡。每每 paper 裏頗有創意的算法落地的時候是有些困難的。

3. 多輪排序

下面咱們討論一下多輪排序的問題。多輪排序是 learningtorank 實踐中很重要的一個思想。使用多輪排序主要是由於計算資源的限制,沒法使用複雜的模型進行大規模的候選集排序。右圖描述了一個多輪排序的框架。這像是一個漏斗模型,從上往下模型的複雜度是遞增的,同時候選集是逐漸減小的,就是越到後面用越複雜的模型來保證效果更好,越到前面可能只須要簡單的模型來保證能拿到一些商品就能夠了。

這樣會存在一個問題,因爲訓練樣本可能有偏,致使只有被用戶看到的樣本纔有 label,可是通常不會有太大的影響。

基於索引的首輪排序

1. 索引召回

下面咱們重點介紹一下第一輪排序。倒排索引很常見,是信息檢索裏經常使用的工具。它經過把 doc 的內容索引到 docid 的方式,快速經過內容來查找 doc。咱們不少召回都是經過索引實現的。這裏我列舉了一些基於索引的召回方式,如 itemcf 的 key、產品詞、熱門類目、促銷產品詞等。

雖然索引可以很大程度上的縮小候選集的範圍,可是常常狀況下,第一輪排序的 doc 數量仍然可能會很大。爲了保證性能,截斷邏輯是必不可少的。經過狀況下能夠經過 qualityscore 截斷,保留質量好的 doc。通過線性的 LR 或者 GBDT 模型就能夠有結果了。另外截斷以後須要有些多樣性的邏輯,由於只有在召回的時候保持多樣性,最終結果纔會有多樣性。

基於 qualityscore 截斷是一種 naive 的算法,這裏咱們討論另外一種業界也較經常使用的算法,wand。wand 實際上是 weakand,它的重點是 wand 操做符。wand 操做符是一個布爾操做符,當 Xiwi比θ大時,它的值是 1,不然是 0。之因此叫作 weak-and,是由於當 w 都取 1,θ取 K 時,wand 操做符就變成了 and,當 w 取 1,θ取 1 時,wand 操做符就變成了 or。能夠看出 wand 是介於 and 和 or 之間的操做。對 Xiwi 求和的操做其實和咱們線性模型很類似。經過 wand 操做符,咱們能夠定義一些上界,由於是倒排索引,能夠給每一個索引鏈賦予一個估計值,這樣就能夠拿到權重上界 UBt,這樣經過和 wand 操做符對比,就能夠快速的判斷 UBt 是否知足條件,若是知足條件就能夠快速的把一些 doc 扔掉,這樣就能夠快速的使用線性模型對全戶作 ranking。能夠看到,基於線性模型的分數作截斷,比徹底基於 qualityscore 截斷的策略要稍微好一點。

這裏我列了 paper 中 wand 算法的僞代碼。出於時間關係,咱們不會過算法邏輯的細節。我認爲它的主要的思路是經過快速使用 upperbound 作截斷和跳轉,能夠略過不少明顯不符合的候選 doc,從而減小計算 score 的次數。固然這種方法對於線性模型來講,有一個缺點,當咱們須要多樣性的時候,沒辦法很好的實如今模型中增長多樣性的。

wand 算法目前已經應用很是普遍了,在不少開源的索引如 lucene 中,也會用到這種方法快速計算文本相關分。

剛剛咱們介紹了使用倒排索引作第一輪排序,以及一個常見的排序加速算法,回過來咱們思考一下倒排索引自己,它適用於什麼場景,不適用於什麼場景。

首先它適用於 kv 查找這種場景,而且 kv 查找也屬於實際應用不少的狀況。可是對於更復雜的方式,相似 graph 的召回方式不友好,好比找用戶看過的商品中類似商品的相關商品,這時實現起來會比較麻煩,這是它的一些限制。再一個,咱們須要有較好的截斷策略,例如底層使用 relevencescore 截斷,排序使用 GBDT。

固然,索引還會受到機器自己的內存限制,限於機器的大小,不少時候咱們須要多機分片部署索引,這樣會帶來必定的複雜性。雖然有些限制,可是索引是目前應用很普遍、有效的方式,包括在推薦、搜索等領域都會使用到。

2.KNN 召回

除了索引召回,KNN 也是如今較經常使用的一種召回方式。首先,咱們把全部的候選集轉換成 embedding,咱們把用戶興趣也能夠轉換成 embedding,經過定義 embedding 之間距離計算公式,咱們能夠定義 KNN 召回問題,也就是在所有候選池中,找到與用戶最接近的 k 個結果。

定義好 KNN 召回的問題,下一步就是如何找到最近的 K 個候選集。因爲整個候選集很是大,每次都使用用戶的 embedding 去全量計算距離是不現實的,只能使用一種近似算法。咱們今天分享其中的一種近似算法。是 facebook 開源的 KNN 計算庫 faiss 使用的。其原理:

首先須要對所有候選集進行分塊,每一塊都會有本身的質心。paper 中使用 Lloyd 算法,將整個空間劃分開。分塊後,就須要對每一塊構建索引,進而經過索引實現快速檢索的功能。

右圖是索引構建和檢索的方法。

上半部分是如何構建索引(這裏的優化點是使用了二級索引):首先拿到 y 候選集以後,作一個 quantizer 分類獲得一個一級索引,把它放到索引表中,另外還獲得殘差 computeresidual,能夠對殘差再進行一次 quantizer,獲得一個二級索引,經過兩級索引來加快檢索的速度,同理,在真正的 quary 的時候,拿到的是用戶的向量 x,先作一個 quantizer,獲得 k 近鄰的一級索引,而後查找 k 個一級索引,同時拿到 k 個二級索引,而後在二級索引中查找,而後這裏還有不少加速的算法(這裏就不展開了),經過這樣一種多層的查詢方式來作到加速 K 近鄰的算法。

PS:關於 KNN 的一些思考,KNN 是一種有效的方式,可是不是惟一有效的方式。好比以後分享的 TDM,可以比 KNN 更加靈活。

實驗平臺

最後簡單介紹下分層實驗平臺,由於你們想快速迭代特徵和模型,離不開實驗,常常會遇到的狀況是實驗流量不夠用了,這時就須要對實驗作分層。分層的邏輯見右圖,經過在不一樣的 Layer 使用不一樣的哈希函數,保證每一個 Layer 之間流量是正交的,這樣就能夠在不一樣的 Layer 上作不一樣的實驗。

分層實驗的具體作法:召回 -> 排序 -> 後處理 -> 業務,另外還有一部分對齊流量,用來作全量的驗證。

分層的優勢,能夠用於作實驗的流量多,適合快速迭代;缺點,須要嚴格控制層與層之間的關係,防止相互干擾。本次分享就到這裏,謝謝你們。

做者介紹:

孟崇,京東推薦架構負責人。負責京東推薦系統的 ranking 算法架構和模型訓練。碩士畢業於中科院自動化所,前後在 yahoo、獵豹移動和京東從事推薦的工做,有豐富的推薦算法經驗。

本文來自 DataFun 社區

原文連接:

https://mp.weixin.qq.com/s/vpANPrl86Ou2fBVHgLXtBQ

相關文章
相關標籤/搜索