天天看點

統一預估引擎的設計與實作

1. 背景

随着網際網路的快速發展,網際網路上出現了各種海量的資訊。怎麼樣為使用者推薦感興趣的資訊是個很大的挑戰?各種各樣的推薦算法、系統都湧現出來。而預估引擎可以說是推薦系統中比較重要的一環,預估引擎效果的好壞嚴重影響了算法效果。結合oppo的業務場景,我們的預估引擎需要解決幾個問題:

(1)通用性:oppo的推薦業務場景非常多,包括資訊流、商店、短視訊、聯盟、鎖屏雜志、音樂等業務,預估引擎要支援這麼多的場景,架構一定要通用。

(2)多模型預估:在廣告場景中,需要支援ocpx,需要一次請求同時預估ctr和cvr,可能是多個不同的轉化模型(例如下載下傳、付費等)。

(3)模型的動态更新:有些模型是小時更新、有些模型是天級更新,需要做到能夠無感的動态更新。

(4)擴充性:各個業務用到的特征、字典、模型類型都可能不一樣,要做到比較容易擴充。

2. 定位與技術選型

考慮到各個業務的業務特征差異比較大,統一預估引擎如果要支援各個業務的政策實驗和分流實驗,會讓預估引擎子產品非常臃腫,沒法維護。是以最終決定預估引擎隻做預估相關的事情。

從原始資料到得到預估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粗排,綜合名額提升5、6個百分點。

3.8 性能優化

預估引擎子產品對時延要求很高,但是為了達到比較好的算法效果,特征規模又在不斷的增加,是以在設計預估引擎的時候,做了很多性能優化的考量。主要包括以下幾個方面:

(1)通過對象池來減少記憶體配置設定,提高性能。

(2) 特征字段的依賴都事先轉化成下标,在提取特征的時候,就直接使用下标來取對應的字段,減少計算量。

(3)有些特征依賴其他特征結果,會頻繁按照slot去查詢對應結果,考慮到slot資料有限,采用數組來代替。

4. 總結

目前predictor子產品支援了大多數推薦場景,包括資訊流内容、資訊流廣告、應用市場、聯盟、搜尋、短視訊、oppo鎖屏雜志、音樂等場景,部署在近2000台機器上,說明這套設計還比較穩定、擴充性比較好。目前支援業務平滑的切換到dnn模型,各個業務場景都取得一定的收益。

作者簡介

肖超 進階資料挖掘工程師

繼續閱讀