在這篇文章裡你可以瞭解到廣告推薦演算法 Wide and deep 模型的相關知識和搭建方法,還能瞭解到模型最佳化和評估的方式。我還為你準備了將模型部署到 FPGA 上做硬體加速的方法,希望對你有幫助。閱讀這篇文章你可能需要 20 分鐘的時間。
早上起床開啟音樂 APP,會有今日歌單為你推薦一些歌曲。地鐵上閒來無事,刷一刷抖音等短影片,讓枯燥的時光變得有趣。睡前開啟購物 APP,看一看今天是不是有新品上架。不知不覺大家已經習慣了這些 APP,不知道大家有沒有留意到為什麼這些 APP 這麼懂你,知道你喜歡聽什麼音樂,喜歡看什麼型別的短影片,喜歡什麼樣的商品?
圖 1:某美食 APP 的推薦頁面
這些 APP 都會有類似「猜你喜歡」這類欄目。在使用時會驚歎「它怎麼直到我喜歡這個」,當然,也會有「我怎麼可能喜歡這個」的吐槽。其實這些推送都是由機器學習搭建的推薦系統預測的結果。今天就介紹一下推薦系統中的重要成員 CTR 預估模型,下面先讓大家對 CTR 預估模型有一個初步認識。
先了解兩個名詞
CTR(Click-Through-Rate)點選率,它是在一定時間內點選量/曝光量*100%,意味著投放了 A 條廣告有 A*CTR 條被點選了。
ECPM(earning cost per mille)每 1000 次曝光帶來收入。ECPM=1000*CTR*單條廣告點選價格。
看個例子:
廣告 A:點選率 4%,每個曝光 1 元錢,廣告 B:點選率 1%,每個曝光 5 元錢。假如你要投放 1000 條廣告,你會選擇廣告 A,還是廣告 B?直觀上來看,廣告 A 的點選率高,當然選擇投放廣告 A。
那麼:ECPM=1000*CTR*點選出價:
ECPM(A)=1000*4%*1=40
ECPM(B)=1000*1%*5=50
但是從 ECPM 指標來看的話廣告 B 帶來的收益會更高,這就是廣告競拍的關鍵計算規則。
我們可以看到 CTR 是為廣告排序用的,對於計算 ECPM 來說,只有 CTR 是未知的,只要準確得出 CTR 值就可以了。因此 CTR 預估也是廣告競拍系統的關鍵指標。廣告系統的 CTR 預估在具體的數值上比推薦系統要求更高,比如推薦系統可能只需要知道 A 的 CTR 比 B 大就可以排序了。
而廣告由於不是直接用 CTR 進行排序,還加上了出價,因此廣告系統不僅要知道 A 的 CTR 比 B 大,而且還需要知道 A 的 CTR 比 B 的 CTR 大多少。
那麼再看一個例子:
如果廣告 A:點選率是 5%,廣告 B:點選率也是 5%,點選價格也相同,該選擇廣告 A 還是廣告 B?點選率相同,點選價格也相同,得出 ECPM 也相同,該怎麼選擇投放廣告 A 還是 B 呢?
此時就可以根據廣告屬性做針對性推薦,針對不同的人群,做合適的推薦。例如:廣告 A 是包,廣告 B 是遊戲,可做針對性推薦。即:針對女人這一群體投放廣告 A、針對男人這一群體投放方告 B,這樣則會提高總廣告收益率。
CTR 模型是怎麼得出結果的呢?
我們可以根據經驗判斷決定廣告點選率的屬性:廣告行業、使用者年齡、使用者性別等。由此可分為三類屬性:
user:年齡、性別、收入、興趣、工作等。
ad items:類別、價格、創意、實用等。
others:時間、投放位置、投放頻率、當前熱點等。
這些決定屬性在 CTR 預估模型中都叫做特徵,而 CTR 預估模型中有一重要過程「特徵工程」,將能影響點選率的特徵找到並進行處理,比如把特徵變成 0 和 1 的二值化、把連續的特徵離散化、把特徵平滑化、向量化。
這樣 CTR 模型相當於是無數特徵(x)的一個函式,CTR=f(x1,x2,x3,x4,x5...),輸入歷史資料訓練,不斷調整引數(超引數),模型根據輸入的資料不斷更新引數(權重),最終到迭代很多次,引數(權重)幾乎不變化。當輸入新的資料,就會預測該資料的結果,也就是點選率了。
那麼有沒有很好奇如何搭建並訓練出一個好的 CTR 預估模型呢?
一、模型迭代過程
推薦系統這一場景常用的兩大分類:CF-Based(協同過濾)、Content-Based(基於內容的推薦)。
協同過濾 (collaborative filtering) 就是指基於使用者的推薦,使用者 A 和 B 比較相似,那麼 A 喜歡的 B 也可能喜歡。基於內容推薦是指物品 item1 和 item2 比較相似,那麼喜歡 item1 的使用者多半也喜歡 item2。
對於接下來的模型無論是傳統的機器學習還是結合現今火熱的深度學習模型都會針對場景需求構建特徵建模。
LR(Logistics Regression)==>
MLR(Mixed Logistic Regression)==>
LR+GBDT(Gradient Boost Decision Tree)==>
LR+DNN(Deep Neural Networks)即 Wide&Deep==>
1.1、LR
所謂推薦也就離不開 Rank 這一問題,如何講不同的特徵組透過一個表示式計算出分數的高低並排序是推薦的核心問題。透過線性迴歸的方式找到一組滿足這一規律的引數,公式如下:
再透過 sigmoid 函式將輸出對映到(0,1)之間,得出二分類機率值。
LR 模型一直是 CTR 預估的 benchmark 模型,原理通俗易懂、可解釋性強。但是當特徵與特徵之間、特徵與目標之間存在非線性關係時,模型效果就會大打折扣。因此模型十分依賴人們根據經驗提取、構建特徵。
另外,LR 模型不能處理組合特徵,例如:年齡和性別的組合,不同年齡段不同性別對目標的偏愛程度會不相同,但是模型無法自動挖掘這一隱含資訊,依賴人工根據經驗組合特徵。這也直接使得它表達能力受限,基本上只能處理線性可分或近似線性可分的問題。
為了讓線性模型能夠學習到原始特徵與擬合目標之間的非線性關係,通常需要對原始特徵做一些非線性轉換。常用的轉換方法包括:連續特徵離散化、向量化、特徵之間的交叉等。稍後會介紹為什麼這樣處理。
1.2、MLR
它相當於聚類+LR 的形式。將 X 聚成 m 類,之後把每個類單獨訓練一個 LR。MLR 相較於 LR 有更好的非線性表達能力,是 LR 的一種擴充。
我們知道 softmax 的公式如下:
將 x 進行聚類,即得擴充之後的模型公式:
當聚類數目 m=1 時,退化為 LR。m 越大,模型的擬合能力越強,m 根據具體訓練資料分佈來設定。
圖 2 MLR 模型結構
但是 MLR 與 LR 一樣,同樣需要人工特徵工程處理,由於目標函式是非凸函式(易陷入區域性最優解),需要預訓練,不然可能會不收斂,得不到好的模型。
1.3、LR+GBDT
顧名思義 LR 模型和 GBDT 模型組合。GBDT 可做迴歸與分類,這個看自己的需求。在 CTR 預估這一任務中要使用的是迴歸樹而非決策樹。梯度提升也就是朝著梯度下降的方向上建樹,透過不斷更新弱分類器,得到強分類器的過程。
每一子樹都是學習之前樹的結論和的殘差,透過最小化 log 損失函式找到最準確的分支,直到所有葉子節點的值唯一,或者達到樹的深度達到預設值。如果某葉子節點上的值不唯一,計算平均值作為預測值輸出。
LR+GBDT:
Facebook 率先提出用 GBDT 模型解決 LR 模型的組合特徵問題。特徵工程分為兩部分,一部分特徵透過 GBDT 模型訓練,把每顆樹的葉子節點作為新特徵,加入原始特徵中,再用 LR 得到最終的模型。
GBDT 模型能夠學習高階非線性特徵組合,對應樹的一條路徑(用葉子節點來表示)。通常用 GBDT 模型訓練連續值特徵、值空間不大(value 種類較少)的特徵,空間很大的特徵在 LR 模型中訓練。這樣就能把高階特徵進行組合,同時又能利用線性模型處理大規模稀疏特徵。
圖 3 LR+GBDT 模型結構圖
1.4、LR+DNN(Wide&Deep)
先回想一下我們學習的過程。從出生時代,不斷學習歷史知識,透過記憶達到見多識廣的效果。然後透過歷史知識泛化 (generalize) 到之前沒見過的。但是泛化的結果不一定都準確。記憶 (memorization) 又可以修正泛化的規則 (generalized rules),作為特殊去處理。這就是透過 Memorization 和 Generalization 的學習方式。
推薦系統需要解決兩個問題:
記憶能力: 比如透過歷史資料知道「喜歡吃水煮魚」的也人「喜歡吃回鍋肉」,當輸入為「喜歡吃水煮魚」,推出「喜歡吃回鍋肉」
泛化能力: 推斷在歷史資料中從未見過的情形,「喜歡吃水煮魚」,「喜歡吃回鍋肉」,推出喜歡吃川菜,進而推薦出其他川菜
但是,模型普遍都存在兩個問題:
偏向於提取低階或者高階的組合特徵,不能同時提取這兩種型別的特徵。
需要專業的領域知識來做特徵工程。
線性模型結合深度神經網路為什麼叫做 wide and deep 呢?
無論是線性模型、梯度下降樹、因子分解機模型,都是透過不斷學習歷史資料特徵,來適應新的資料,預測出新資料的表現。這說明模型要具備一個基本特徵記憶能力,也就是 wide 部分。
但是當輸入一些之前沒有學習過的資料,此時模型表現卻不優秀,不能根據歷史資料,有機組合,推出新的正確結論。此時單單依賴記憶能力是不夠的。深度學習卻可以構建多層隱層透過 FC(全連線)的方式挖掘到特徵與特徵之間的深度隱藏的資訊,來提高模型的泛化能力,也就是 deep 部分。將這兩部分的輸出透過邏輯迴歸,得出預測類別。
圖 4 Wide & Deep 模型結構圖
它混合了一個線性模型(Wide part)和 Deep 模型 (Deep part)。這兩部分模型需要不同的輸入,而 Wide part 部分的輸入,依舊依賴人工特徵工程。本質上是線性模型 (左邊部分, Wide model) 和 DNN 的融合 (右邊部分,Deep Model)。
對於歷史資料特徵保證一定的記憶能力,對於新的資料特徵擁有推理泛化能力。較大地提高了預測的準確率,這也是一次大膽的嘗試,在推薦系統中引入深度學習,在之後的 CTR 模型發展中大多也都是按照此設計思路進行的。
1.5、資料處理
CTR 預估資料特點:
輸入中包含類別型和連續型資料。類別型資料需要 one-hot(獨熱編碼), 連續型資料可以先離散化再 one-hot,也可以直接保留原值。
維度非常高,特徵值特別多。
資料非常稀疏。如:city 包含各種不同的地方。
特徵按照 Field 分組。如:city、brand、category 等都屬於一個 Field,或者將這些 Field 拆分為多個 Fidld。
正負樣本不均衡。點選率一般都比較小,大量負樣本存在。
如何高效的提取這些組合特徵?CTR 預估重點在於學習組合特徵。注意,組合特徵包括二階、三階甚至更高階的,複雜的特徵,網路不太容易學習、表達。一般做法是人工設定相關知識,進行特徵工程。但是這樣做會非常耗費人力,另外人工引入知識也不能做到全面。
1.6、模型搭建
以 Wide and Deep 為例,介紹網路的搭建。在 tensorflow.estimator 下有構建好的 API,下面將簡要介紹如何使用它。
Wide 中不斷提到這樣一種變換用來生成組合特徵:
tf.feature_column.categorical_column_with_vocabulary_list(file)()。知道所有的不同取值,而且取值不多。可以透過 list 或者 file 的形式,列出需要訓練的 value。
tf.feature_column.categorical_column_with_hash_bucket(),不知道所有不同取值,或者取值多。透過 hash 的方式,生成對應的 hash_size 個值,但是可能會出現雜湊衝突的問題,一般不會產生什麼影響。
tf.feature_column.numeric_column(),對 number 型別的資料進行直接對映。一般會對 number 型別 feature 做歸一化,標準化。
tf.feature_column.bucketized_column(),分桶離散化構造為 sparse 特徵。這種做法的優點是模型可解釋高,實現快速高效,特徵重要度易於分析。特徵分割槽間之後,每個區間上目標(y)的分佈可能是不同的,從而每個區間對應的新特徵在模型訓練結束後都能擁有獨立的權重係數。
特徵離散化相當於把線性函式變成了分段線性函式,從而引入了非線性結構。比如不同年齡段的使用者的行為模式可能是不同的,但是並不意味著年齡越大就對擬合目標(比如,點選率)的貢獻越大,因此直接把年齡作為特徵值訓練就不合適。而把年齡分段(分桶處理)後,模型就能夠學習到不同年齡段的使用者的不同偏好模式。
tf.feature_column.indicator_column(),離散型別資料轉換查詢,將類別型資料進行 one-hot,稀疏變數轉換為稠密變數。
tf.feature_column.embedding_column(),(加深 feature 維度,將特徵向量化,可使模型學到深層次資訊),對於 RNN 中有 tf.nn.embedding_lookup(), 將文字資訊轉為向量,具體演算法可以自行查一下。
離散化的其他好處還包括對資料中的噪音有更好的魯棒性(異常值也落在一個劃分割槽間,異常值本身的大小不會過度影響模型預測結果);離散化還使得模型更加穩定,特徵值本身的微小變化(只有還落在原來的劃分割槽間)不會引起模型預測值的變化。
tf.feature_column.crossed_column(),構建交叉類別,將兩個或者兩個以上的 features 根據 hash 值拼接,對 hash_key(交叉類別數)取餘。特徵交叉是另一種常用的引入非線性性的特徵工程方法。
通常 CTR 預估涉及到使用者、物品、上下文等幾方面的特徵,有時某個單個 feature 對目標判定的影響會較小,而多種型別的 features 組合在一起就能夠對目標的判定產生較大的影響。比如 user 的性別和 item 的類別交叉就能夠刻畫例如「女性偏愛女裝」,「男性喜歡男裝」的知識。交叉類別可以把領域知識(先驗知識)融入模型。
Deep 部分,透過 build_columns(), 得到可分別得到 wide 和 deep 部分,透過 tf.estimator.DNNLinearCombinedClassifier(),可設定隱藏層層數,節點數,最佳化方法(dnn 中 Adagrad,linear 中 Ftrl),dropout,BN,啟用函式等。將 linear 和 dnn 連線起來。將點選率設定為 lebel1,從經驗實測效果上說,理論原因這裡就不贅述了。
將訓練資料序列化為 protobuf 格式,加快 io 時間,設定 batch_size、epoch 等引數就可以訓練模型了。
二、模型最佳化
對於不同資料,選用不同的 features,不同的資料清理方式,模型效果也會有不同,透過測試集驗證模型評價指標,對於 CTR 預估模型來說,AUC 是關鍵指標(稍後介紹)。同時監測查準(precision),查全率(recall),確定模型需要最佳化的方向,對於正負不均衡情況還可以加大小樣本的權重係數。
一般來說,AUC 指標可以達到 0.7-0.8。當 AUC 在這個範圍時,如果準確率較低,說明模型效果還有待提高,可以調整隱藏層數目(3-5)層和節點數(2**n,具體看自己的 features 輸出維度),構建組合特徵,構建交叉特徵。學習率可設定一個稍微大點的初始值,然後設定逐漸衰減的學習率,加快收斂。最佳化手段千變萬化,掌握其本質,在儘可能學習到更多的特徵性避免過擬合。具體最佳化最佳化方法由模型的表現來決定。
三、模型評估
AUC(Area under Curve):Roc 曲線下的面積,介於 0.5 和 1 之間。AUC 作為數值可以直觀的評價分類器的好壞,值越大越好。
直觀理解就是:AUC 是一個機率值,當你隨機挑選一個正樣本以及負樣本,當前的分類演算法根據計算得到的 Score 值將這個正樣本排在負樣本前面的機率就是 AUC 值,AUC 值越大,當前分類演算法越有可能將正樣本排在負樣本前面,從而能夠更好地分類。
下表是經過調整後,不同演算法實現的模型效果對比表:
圖 5 模型效果對比表
不斷最佳化後得出幾個模型的不同效果,將每一次廣告曝光按照預測的 CTR 從小到大排序,可以根據預測的 CTR 值根據 ECPM 公式,按照單位曝光量統計出預估的 ECPM 和真實的 ECMP 進行比較,就可以知道預估的 CTR 值是否可靠了。
正確預估 CTR 是為了把真正高 CTR 的廣告挑出並展示出來麼,錯誤地預估——把高的 CTR 低估或把低的 CTR 高估都會讓高的 ECPM 不會排在最前面。在實際的實踐過程中,CTR 預測正確通常 ECPM、CTR、收入這些指標通常都會漲。
四、模型部署
通常對於 AI 演算法模型都是透過 GPU 伺服器部署模型,但是對於推薦系統類演算法邏輯計算較多,在速度上反而沒有優勢,部署成本也比較高,經濟性很差。所以大都透過 CPU 雲伺服器部署,但是速度又不夠理想。那麼有沒有另外一種可能?
答案是肯定的,可以透過 FPGA+CPU 的方式,大型推薦系統的上線都是透過雲端部署,同時用線上和離線方式更新模型。雪湖科技 FPGA 開發團隊把以 Wide and Deep 為基礎網路的模型移植到阿里雲 FPGA 伺服器 F3(FPGA:VU9P)上,使用者可以透過映象檔案部署。模型精度損失可控制在千分之一。
相較於 CPU 伺服器,FPGA 伺服器的吞吐量提高了 3~5 倍。當模型更新時,透過雪湖科技提供的工具可直接載入模型引數,可做到一鍵式更新模型引數。
五、CTR 模型發展
Wide&Deep 雖然效果很好,但是隨著演算法的不斷迭代基於 Wide&Deep 模型思想,有很多新的模型被開發出來,基本思想是用 FM、FFM 代替 LR 部分,透過串聯或者並聯的方式與 DNN 部分組合成新的模型,例如 FNN,PNN,DeepFM,DeepFFM,AFM,DeepCross 等等,雪湖科技公司也致力於將所有 CTR 預估模型都完美相容,在保證精度的前提下,增大吞吐量。後面的文章中會針對這些模型做詳細介紹,敬請關注。
作者介紹:本文作者為雪湖科技演算法工程師梅碧峰,現負責人工智慧演算法開發。在 AI 演算法領域工作超過 5 年,喜歡戴著 Sony 降噪耳機埋頭研究各類演算法模型。理想主義的現實工作者,致力於用演算法解放人工,實現 1+1>2 的問題。
雪湖科技是一家專注於人工智慧和 FPGA 應用開發的企業,特別擅長於在利用 FPGA 對各類 AI 演算法做硬體加速,可以提供各類基於 FPGA 的標準神經網路加速器和定製化開發。