機器之心專欄
作者:雪湖科技 梅碧峰
在這篇文章裡你可以了解到廣告推薦算法 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=40ECPM(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 ltering) 就是指基於用戶的推薦,用戶 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 的標準神經網絡加速器和定製化開發。
本文為機器之心專欄,轉載請聯繫原作者獲得授權。