在廣告/搜索/推薦系統中 對展示結果打散的通用魯棒算法

摘要:之所以同時提到廣告/搜索/推薦三個系統,是因爲這三者有一定的相似性,即通過一次請求(基於上下文、用戶場景、關鍵詞等)給用戶呈現一籃子元素,這些元素包括如文章、商品、活動、專輯、音樂、視頻等等。這一籃子需要展示的元素儘管是根據權重進行過排序,但一個很常見的問題就是基於視覺效果的考慮需對這個列表進行類別打散,最常見的一個例子是在電商領域,對推薦的商品進行類目/品牌等屬性打散開,從而增加閱讀舒適性。

一、引言

  根據摘要的描述,廣告/搜索/推薦系統中經常可能需要對結果進行按類別重排序,以便得到更好的視覺體驗,這類需求場景,很多時候是出現在綜合性展示區域,如考拉的首頁,新聞的首頁、音樂的每日推薦等等,如果是專用欄位,比如電商中同品牌推薦、相似推薦等並不需要這種考慮的,但是可能仍然可能需要根據顏色、包裝樣式打散等等。

圖1展示了4個商品結果,如果是在搜索結果中,這樣的排列可能並不會覺得有任何問題,如果呈現在根據興趣的推薦中,這一連串特別是相似的藥瓶可能會讓用戶覺得系統出了bug,更常見的一個場景是某搜索的廣告中,經常給你展示一堆某系醫院的廣告,一個挨着一個。

圖1在推薦中一次效果不太好的呈現示例

圖2給出了一種基於內容推薦APP中的一例子,出現這樣的情況有種讓用戶覺得進入了娛樂頻道的感覺。

圖2某內容推薦中經常連續推薦兩篇娛樂新聞

所以我們需要對輸出結果按特定的類別進行打散,這裏統稱用“類別”,具體可以指分類、種羣、一二級三級類目、物理屬性、來源、產地、品牌、廣告主、色系、款式等等。如果涉及到多種類別同時考慮,則情況比較複雜,暫時此討論範圍內。本文基於自己的經驗以及幾個版本的迭代成果,結合在考拉推薦中的實踐經驗,提出一種可以實現比較通用魯棒的排序方法,並給出實際一步一步解讀,分享對這個細節的一些思考,有錯誤和改進之處多多指教:)

實際上,這一方面公開的資料不太豐富,但只要做過類似的數據後期處理的,一定有自己的經驗或者實現方式,先看看最通常能想到的基於窗口滑動的,圖3的第一行數據是原始數據,窗口尺寸爲2(定義考慮的窗口中最大位置減去最小位置的差值)其中文字顏色代表某種類別(紅黃白三類),數值代表元素id(可以認爲是商品id等等)。原理是通過一個窗口區域內逐步排查,發現有衝突的類別,就和後面最近一位類別不衝突的id做交換,如第二行中2和3同時存在窗口中,那麼3和後面的4交換能保證第一窗口中沒有類別衝突的元素,依次類推,直到第四窗口的時候發現,沒有任何其他元素可以填充進窗口4中能滿足要求。那麼最終的結果中同類別的7和8就會連續出現。基於窗口滑動的這種算法直接簡易常見,時間複雜度是O(n*k),通常需要排序的元素(n值)不會上三位數,所以實際應用中可以忽略時間的損耗影響。窗口滑動方法容易實現和理解但主要的問題是不太魯棒,如果不加以控制容易出現連續(未分散)的情況(當然實際中可以有其它更復雜手段加以控制)。

圖3窗口滑動法打散類別


二、方法

(1) 說明

定義:窗口尺寸爲winlen爲考慮的窗口中最大位置減去最小位置的差值,比如可以將同類別的放置到0(程序員數數從0開始)號位和2號位,那麼winlen=2,故而如果winlen<2,實際無意義;實際使用中,用得多的值是2/3/4(很特別)。此外,下文中會經常進行“輪詢”和“摘取”兩個過程,輪詢表示依次對類別進行遍歷,目的是查看該類別排序中的第一個元素是否滿足要求,如滿足要求,就摘取(類似彈出、pop)到候選隊列,並在該類別的原存儲出中刪除這個元素。

假定:原始數據一般是有序的,通常根據用戶喜好的預測程度排序,重排序必然會打亂其預測,也就是違背初衷,本文提出的方法儘量保證原有順序,爲了部分環節的快速處理,會有地方忽略本身的順序權重,所以我們假定了給出的原始數據,均是滿足要求,其順序在一些地方同等對待。

效果:本方法通用魯棒,所謂通用,一方面是場景通用,一方面是指剛纔提到的可以對各種類別進行打散,還有一方面是只可以對各種類型的數據(Long和String居多)進行處理;所謂魯棒,是指同樣的輸入數據列表,不管其結構是怎樣的排列方式,都能同樣程度的得到分散效果。

條件:不難證明,如果最多類別元素是k,列表大小是n,窗口尺寸是winlen,如果符合:

則無論如何也不能滿足打散的需求,只能以最大可能對列表前部分的類別打散,後尾部數據採用貪心算法降級處理(比如採取winlen-1、winlen-2的尺寸等),上述公式中中括號是取整。


(2) 實現思路和框架

  本文提出的算法思路主要是通過做數據預處理,將元素和類別按原有順序填充到動態數據類別矩陣,行座標是元素,列座標是類別,在同一類別中,元素按輸入順序排列。在選取過程中,優先輪詢元素多的類別,再進行日常輪詢,輪詢的結果和參數(返回個數limit、打散窗口尺寸winlen等)進行對比,如果滿足條件,則摘取相應的元素到輸出隊列,再進行下一輪的摘取。

圖4

   首先將數據和參數進行變換(主要是輸出個數limit,通常和輸入一致,以及窗口尺寸winlen),依次得到基礎數據含:類別最新位置記錄器L(用於記錄每個類別最新的一個位置)、類別元素字典D(記錄映射關係)、動態數據類別矩陣M(,若一個元素被摘取,則同類別的其它元素自動向上補,同類別的順序和輸入時候的順序保持一致),富元素類別指針P(每次元素摘取後,更新該指針指向新的最多元素的類別,可能多個);

其次將輸入數據放進候選器進行篩選,對動態數據類別矩陣M在每一輪按類別對元素挨個日常輪詢,且在每次輪詢前優先詢問一次富元素類別指針P指向的類別(若是同一個,則忽略),無論是優先詢問的還是日常輪詢,其判斷依據是對被詢問的元素根據最新位置記錄器L的數據和設定的窗口winlen的關係來判定,若成功得到候選集,根據當前環境的使用參數和類別元素字典D對應關係更新相應數據;

經過一輪的輪詢問下來,摘取的元素依次更新到輸出數據,並響應的對摘取過後的基數數據進行排序,如果有類別的元素被摘空,則更新空類別的集合,如果滿足特定條件,則退出循環,否則進行下一輪的日常輪詢。剛纔所述特定條件包括:空類別集合是所有類別、輸出的元素數量達到傳入的limit個、再也沒有新的候選集生成等;

若流程已經退出輪詢的步驟,且輸出列表的元素個數未達到設定的個數,說明要麼設定值過大要麼動態數據類別矩陣M裏面還有元素無論如何也無法按設定條件進行足夠的打散後放到輸入列表,這時候只能通過填充策略今天填充,填充策略採用貪心法,依次對存在元素的類別進行輪詢,哪個類別和當前最新位置記錄器L的值差異最大則選哪個元素,直到滿足條件。

以上就是架構的整體思路,用一句話來總結核心思想就是通過將原始輸入數據存放到動態數據類別矩陣M對類別進行多輪的輪詢同時優先考慮當前擁有最多數據的類別,進行類別的打散排序輸出,若實在無法打散,則儘可能採取貪心算法進行填充。

(3) 算法流程示例

以上框架中核心算法流程總體如下:

圖5總體算法流程

下面以一個示例簡短的對以上算法做說明,假定一列原始數據如下,顏色表示類別,數字表示商品id:

該示例數據大致和上文中基於窗口滑動了的類似,但爲了增加說明幾個算法細節,做了適當修改,整個算法流程示意圖如下。

 

 

 通過圖6-圖8之後,剩下兩個元素不能按規則分配,於是按貪心法遍歷類別(貪心是指計算此時能進行最大窗口處理的情況就選擇該元素),很容易理解的得到將12和10一次填入到輸出列表中,如下:

(3) 再進一步優化

對比原始數據,經過本文提出的算法已經儘量做到按窗口尺寸爲3的打散,留下最後兩個元素不滿足需求,觀察過程發現,在某一步優先輪詢的時候,去掉了類別A之後,A和B的元素數量一致且爲最大,這個時候應增加循環差集算法作優先輪詢(可以有最大優先輪詢次數限制),這樣可以在6之後優先排3而非11.

 

圖9:某兩步中可以優化的地方

通過以上優化思想,可以最終得到更好的結果,如下對比所示,第一行是原始數據,第二行是優化後的算法,此時只有最後一個元素(元素id=10)未做到按窗口尺寸3進行排列,觀察該數據發現,這已經在理論上已經無法實現,故而目前的狀況爲最優解(嚴謹的說是並列之一)。

 

三、結尾

   本文提出了一種類別分散算法,從結構和實例詳細做了闡述,通過本文的方法,在廣告/搜索/推薦系統中,可以按特定的類別和特定的數據類型對最終結果進行規則分散,以提高用戶體驗。實際應用中,還可能結合這種思想按當前場景的特性進一步優化;另外,工程部署中還應該注重上游算法本身對類別數目的控制,要是出來的所有元素都是同一個類別,直觀來看就不可能;再有,第一個元素的排列可能需要考慮之前的展示結果,比如每次刷新10個元素的應用場景,從第一個元素開始,就應該考慮和上一次請求的最後幾個元素的窗口問題;最後如果是多種類別,比如類目+品牌,可以將類目和品牌作爲一個聯合類別輸入進行打散。

    理論上講,本文提出的時間損耗均爲O(nlogn),經測試對1000的商品排序時間損耗不超過1ms,而實際應用場景多爲幾到幾十個商品,所以時間不成問題。通過提出的動態數據類別矩陣的摘取方式,可以做到比較魯棒的得到全局最優之一的解,實際上全局最優解在對算法細節做微調後會以不同的結果呈現,還可以通過AB測試進行微小的細調(如果場景需要)。本文示例的k=5,n=12,winlen=3,通過條件公式很顯然不能滿足所有條件,故而只能犧牲最後一個元素的達到標準(10和9只間隔了2)來近似滿足需求要求。

參考:https://sq.163yun.com/blog/article/186211645454565376

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