1. 背景算法
隨着互聯網的快速發展,互聯網上出現了各類海量的信息。怎麼樣爲用戶推薦感興趣的信息是個很大的挑戰?各類各樣的推薦算法、系統都涌現出來。而預估引擎能夠說是推薦系統中比較重要的一環,預估引擎效果的好壞嚴重影響了算法效果。結合oppo的業務場景,咱們的預估引擎須要解決幾個問題:數組
(1)通用性:oppo的推薦業務場景很是多,包括信息流、商店、短視頻、聯盟、鎖屏雜誌、音樂等業務,預估引擎要支持這麼多的場景,框架必定要通用。性能優化
(2)多模型預估:在廣告場景中,須要支持ocpx,須要一次請求同時預估ctr和cvr,多是多個不一樣的轉化模型(例以下載、付費等)。網絡
(3)模型的動態更新:有些模型是小時更新、有些模型是天級更新,須要作到可以無感的動態更新。框架
(4)擴展性:各個業務用到的特徵、字典、模型類型均可能不同,要作到比較容易擴展。異步
2. 定位與技術選型ide
考慮到各個業務的業務特徵差別比較大,統一預估引擎若是要支持各個業務的策略實驗和分流實驗,會讓預估引擎模塊很是臃腫,無法維護。因此最終決定預估引擎只作預估相關的事情。 從原始數據到獲得預估ctr結果,須要通過特徵提取,提取特徵以後的結果再進行模型預估。考慮到特徵提取結果比較大,一次預估須要用的特徵結果大約有2M,這麼大的數據若是經過網絡來傳輸,耗時太長。因此預估引擎整體的流程包括了兩部分:特徵提取和模型預估。性能
3. Predictor的設計與實現優化
3.1 Predictor模塊在整個推薦系統中的位置線程
以oppo手機應用市場爲類來講明predictor模塊在整個系統中的位置, ranker模塊負責排序,包括各類分流實驗和各類運營策略等。它經過grpc框架與predictor模塊進行通訊。
3.2 Predictor模塊的主體流程
圖中示意了兩個請求的處理流程,圖中提特徵包括多個特徵conf,每一個樣本、每一個特徵配置提取一次。預估也會是多個模型,每一個樣本、每一個conf、每一個模型會預估屢次。特徵提取依賴外部字典,預估依賴外部的模型文件,外部字典的更新、雙buf切換都是經過字典管理模塊來完成的。下面分別就字典管理模塊、分task, 提特徵,預估,merge進行詳細說明。
3.3 字典管理模塊
以下圖所示:conf1, conf2, lr_model_x0等表示磁盤上的文件,每一個文件名都是經過不一樣的字典解析類來解析,這個字典解析類負責管理這個文件的加載,雙buf切換。例如:FeatureConfDict負責解析conf1,它內部保存兩個FeatureConfList類型的buf,當conf1文件發生更新時,就用備的FeatureConfList* 進行加載,加載完成後,在加載過程當中,服務使用主的FeatureConfList*指針。加載完成後,進行主從切換,待沒有請求使用老的buf,就釋放到老的buf內存。
3.4 分task邏輯
接收到一個請求,這個請求指定了多conf多模型來預估。以下圖所示:
上圖表示一共有8條樣本,分別用兩個conf:conf0, conf1來提取特徵,其中conf0的結果由model0,model1來預估,conf1由model2,model3來預估。按照2個樣本一個task,拆分完task以後會獲得4個task,以下圖所示:
按照樣本維度進行拆分紅4個task,丟到線程池去執行。
3.5 Merge流程
在預估完成以後,須要按照conf/model這個維度進行組織預估結果給ranker, 最終的response以下圖右子圖所示。
3.6 特徵提取框架的設計
特徵提取框架線上、線下都會用到,這樣比較好保證線上線下的一致性。因此設計的時候要同時考慮到線上線下的業務場景。
線上是將請求帶來的數據與字典數據拼成一條條樣本,進行特徵提取的。而線下是編譯so,經過mapreduce來調用,樣本是經過反序列化hdfs的一條條文本獲得的。
3.6.1 特徵配置文件格式
特徵配置文件包括兩部分: schema部分,特徵算子部分。
3.6.2 schema部分
上圖中有5個 schema配置
user_schema:表示當前的用戶相關信息,只在在線方式使用,由上游請求帶過來。
item_schema:表示推薦的item相關信息,只在在線方式使用,一部分由請求帶過來,一部分由字典文件中獲取。
context_schema:表示推薦的上下文相關信息,只在在線方式使用,由上游戲請求帶過來。例如:當前網絡狀態是wifi仍是4G。
all_schema: 表示最終的樣本的schema信息。在線模式是將user_schema, item_schema,context_schema的各個字段放在all_schema的對應位置,離線模塊是將hdfs的一行行文本,按照all_schema_type指定的類型進行反序列化生成的。不論是在線仍是離線,特徵框架的樣本最終的字段順序都是按照all_schema順序存放的
all_schema_type: 離線模式纔會用到,指定了各個schema的類型,這些類型名都是事先定義好的,在離線模式下,根據schema類型來反序列化各個字段。
3.6.3 特徵算子配置部分
每一個特徵包括下面這些字段:
Name: 特徵名字
Class:表示這個特徵用的哪一個特徵算子類,對應代碼裏類名
Slot: 惟一標識一個特徵
Depend: 表示該特徵依賴哪些字段, 這個字段在上述all_schema中必須存在
Args: 表示傳給特徵算子的參數, 框架會轉成float傳給算子
Str_args: 傳給特徵算子的參數,以字符串的形式傳遞。
3.6.4 特徵分group(common和uncommon)
一次預估請求裏面,全部樣本的用戶和context信息是同樣的, 考慮到有些特徵只依賴用戶和context信息,這部分特徵只須要提取一次,全部樣本共用。
特徵配置裏面一部分特徵會依賴其餘的特徵(例如組合特徵、 cvm特徵),因此須要對特徵的依賴進行分析,用來判斷一個特徵最終依賴的字段信息。
i_id特徵依賴item字段的item_id,因此它是uncommon特徵
u_a/net特徵只依賴user_schema或者context字段, 不依賴item字段,因此它是common特徵 u_a-i_id組合特徵依賴i_id特徵,間隔依賴item_id,因此它是uncommon特徵,
u_a-net組合特徵只依賴u_a和network字段,因此它是common特徵,在特徵提取的時候,一次請求只算一次。
注意:這裏特徵分group是異步字典更新線程來負責計算好的,不是請求來了現算的。
3.7 預估部分
前面提到了,一個請求裏面指定了用哪一個特徵配置文件來提取特徵,用哪一個模型來預估。全部的模型都是有異步字典更新線程來負責更新。目前支持了LR, FM, DSSM, Deep&Wide等模型的預估,而且比較容易擴展。下面大概介紹下兩個根據業務場景作了深度優化的模型:
3.7.1 FM模型預估(LR相似)
其中
考慮到業務場景,多個樣本的user/context信息是同樣的,那麼線上FM的 預估能夠寫成這個形式:
標紅部分全部樣本都是同樣的,一個請求只用計算一次。
3.7.2 DSSM(雙塔)模型
雙塔模型的網絡結構以下圖所示:
實際上一共有三個塔,C(context信息),U(user信息), I(item信息), user與item子塔獲得的向量通過點積,再與C進行求和。
3.7.3 在線serving部分
考慮一些場景的item的信息變化比較慢,通常離線將item的子塔先計算好,獲得向量,經過字典的方式動態加載。
在線的時候只用計算c塔,u塔, 一個請求只有一條樣本須要計算;I塔部分由查字典獲得向量。計算量相比全鏈接,大幅度減小。性能有大幅度的提高,可是因爲user信息與item只有一層點積相乘,相比全鏈接,離線auc會降低1%,因此比較適合召回或者粗排等對準確度要求不高的場景。在信息流廣告、聯盟廣告業務替換原來的統計 ctr粗排,綜合指標提高五、6個百分點。
3.8 性能優化
預估引擎模塊對時延要求很高,可是爲了達到比較好的算法效果,特徵規模又在不斷的增長,因此在設計預估引擎的時候,作了不少性能優化的考量。主要包括如下幾個方面:
(1)經過對象池來減小內存分配,提升性能。
(2) 特徵字段的依賴都事先轉化成下標,在提取特徵的時候,就直接使用下標來取對應的字段,減小計算量。
(3)有些特徵依賴其餘特徵結果,會頻繁按照slot去查詢對應結果,考慮到slot數據有限,採用數組來代替。
4. 總結
目前predictor模塊支持了大多數推薦場景,包括信息流內容、信息流廣告、應用市場、聯盟、搜索、短視頻、oppo鎖屏雜誌、音樂等場景,部署在近2000臺機器上,說明這套設計還比較穩定、擴展性比較好。目前支持業務平滑的切換到dnn模型,各個業務場景都取得必定的收益。
做者簡介
肖超 高級數據挖掘工程師
10+年的廣告系統工程落地經驗,在oppo主要負責模型的特徵提取、推理的工程落地工做。
更多精彩內容,請掃碼關注【OPPO互聯網技術】公衆號