第一届腾讯社交广告高校算法大赛经验分享
第一屆騰訊社交廣告高校算法大賽經驗分享
一、簡介
??去年的5月,我和兩個隊友參加了《第一屆騰訊社交廣告高校算法大賽》,在那之前我們實際上完全沒有相關的競賽經驗,三個毫無經驗的菜鳥暴力提取特征,憑借訓練神經網絡的經驗玄學調參,竟然也獲得了還不錯的成績,最終初賽 10/1000,決賽 39/1000,第一次比賽分工比較混亂,每個人都參與了特征工程和模型調參。初賽和決賽都是線下賽,即用自己的機器跑,提交結果即可。本文是對我的第一次比賽中,獲得的一些經驗和思考的分享,旨在總結自身,尋求進步和創新。
二、賽題背景
2.1 賽題簡介
?? 詳細賽題可以看這里(可能已經找不到了)。本題的業務場景是騰訊的廣告推薦系統,廣告主通過騰訊向用戶發布廣告以推薦自己的產品,騰訊根據廣告主的匯報和反饋搜集用戶的點擊與轉換記錄,賽題給我們提供了這樣的數據,要求我們根據過去兩周內的記錄,預測接下來一天內每一條記錄是否發生轉化,核心問題正是CVR預測。
2.2 賽題數據
2.2.1 提供特征
??賽題提供的原始特征由三部分構成:廣告相關特征(從廣告主、推廣計劃一直到app的各Categorical類字段之間的對應關系)、用戶特征(個人信息)、上下文特征。
廣告特征
| 1 | advertiserID | 廣告主 |
| 2 | campaignID | 推廣計劃ID |
| 3 | adID | 廣告ID |
| 4 | creativeID | 素材ID |
| 5 | appID | AppID |
| 6 | appCategory | App分類,使用3位數字分級編碼 |
| 7 | appPlatform | App平臺(Android,iOS) |
用戶特征
| 1 | userID | 用戶ID,唯一標識一個用戶 |
| 2 | age | 年齡 |
| 3 | gender | 性別 |
| 4 | education | 用戶當前最高學歷 |
| 5 | marriageStatus | 用戶當前感情狀況 |
| 6 | haveBaby | 用戶當前孕育寶寶狀態 |
| 7 | hometown | 出生地,使用二級編碼 |
| 8 | residence | 常住地,使用二級編碼 |
| 9 | appInstallList | App安裝列表,截止到某一時間點用戶全部的App安裝列表(appID) |
| 10 | App安裝流水 | 最近一段時間內用戶安裝App行為流水 |
上下文特征
| 1 | positionID | 廣告曝光的具體位置 |
| 2 | sitesetID | 站點集合ID,多個廣告位的聚合 |
| 3 | positionType | 廣告位類型 |
| 4 | connectionType | 移動設備聯網方式 |
| 5 | telecomsOperator | 移動設備當前使用的運營商 |
2.2.2 評估方式
CVR預測,以交叉熵為評估方式:
2.2.3 理解與思考
這里要明確一下點擊和轉化之間的關系, 樣本中的每一個instance就是一次點擊,但是只有少數的點擊發生了轉化,轉化意味著用戶發生了購買或者從app下載行為。賽題要求預測轉化,因此實際上是一個二分類問題。
轉化具有一定虛假性和延遲性,虛假性產生于廣告主的虛假反饋(例如明明發生了多次轉化,卻反饋說沒有發生,從而少付錢,當然騰訊的計費不是那么簡單的),延遲性產生于廣告主的反饋習慣(隔若干天再向系統反饋的行為是被允許的)以及用戶實際情況(有的用戶點擊了廣告,但過了一段時間才發生購買或下載)。虛假性我們無從處理,但延遲性影響較大,特別是訓練集最后一天的轉化記錄很可能是不準的。
三、數據觀察與預處理
??在進入特征工程之前,首先要粗略地觀察一波數據,這里并不要求觀察 labellabel 的分布,那是在特征選擇的時候需要的,要觀察的實際上是數據的取值,包括而不局限于:連續 or 離散,是否有缺失,是否有異常數據等。
連續與離散
??首先,連續 or 離散。連續特征可以考慮數據的歸一化、量化,以及一些值域變換(包括取log、取指數、Box-Cox等)。離散特征一般是ID類特征(Categorical feature),ID類特征可能是分級的(例如本次比賽中的常住地特征以“大類-小類”的形式存在),因此需要分割。此外,根據要使用的模型,可以考慮對ID類特征進行 One-hot(LR和FFM特別需要,樹模型可以不做,因為樹實際上會把ID當成實數處理,又或者根據梯度學習分裂方向)或者 Label-Encoding 編碼(Label-Encoding編碼得到的輸出可以直接作為樹模型的輸入)。然而,編碼過后常會產生維度爆炸的問題,這時就需要考慮另一個問題,降維。降維分為預降維和后降維,預降維指在One-hot之前,觀察一下特征在不同取值下樣本量的分布,可以將出現次數少的ID歸為同類,再做編碼;后降維指在編碼以后,使用PCA(本質上是特征值分解)或 LDA(實際上是用SVD實現)等降維方法進行降維,或者根據樹模型給出的 feature importance 進行特征選擇。在比賽中,我們并沒有對連續數值做變換,但部分ID類特征做了Onehot,以及在特征選擇階段根據 feature importance 進行了后降維。
缺失值
??其次,觀察是否有缺失值。特征缺失(或稱稀疏)是常見的現象,如果使用提升樹模型,可以選擇不處理,XGBoost和LightGBM在實現上有為缺失特征自動選擇分裂方向的功能。具體地,在分裂結點時,分別假設特征值缺失的樣本被分到左右兩側,根據信息增益的多少決定默認分類方向。如果一定要進行缺失值處理,就要繼續根據連續和離散特征考慮。連續特征 可以填充均值,具體地可以是樣本總體均值,也可以是對應的instance_id的樣本的均值(例如用戶老馬有三次點擊,特征A在第二次處缺失,則用第一次和第三次的均值補充),還可以是當天或者前幾天內的均值。離散特征 可以填充眾數(相當于voting),同樣可以選擇全局眾數或局部眾數。至于統計的范圍如何選擇,就屬于特征工程的范疇了。值得注意的一點是,有時候直接舍棄有缺失特征的樣本是更好的做法。孰好孰壞,應該讓模型性能幫忙做決定。比賽中我們對缺失值的處理是,不處理。
異常數據
??最后,檢查是否存在異常數據。這個是最難的,因為每一個instance_id的每一個統計量都有可能出現異常。例如,某廣告主的日轉化率(日轉化/日點擊)在某天前一直很低,某一天之后激增,且之后一直很高,由于要預測接下來一天,因此必定假設新的一天轉化分布是與歷史分布基本一致的,該廣告主在該天之前的信息顯然不正常,因此應該刪除掉那一天之前的所有記錄。同理,若廣告主在某一天之后日轉化率驟減,且沒有回復的跡象,也應該做相似的處理。為什么說很難呢?因為nstance_id的構成呈組合爆炸,每一個instance_id又可以分別觀察點擊量、轉化率等各種分布,想要人工遍歷是幾乎不可能的。此外,異常數據還可能體現在各方各面,主要還是靠觀察來挖掘。本次比賽中,存在著一種樣本重復異常,即除了label外,其他信息都完全一樣的多個樣本,我們認為它出現的原因在于時間戳的秒位忽略,實際樣本的排序正是按照時間排序的,對此我們做的處理是為這些重復的樣本按先后順序設置一個rank。此外,由于存在上面提到的轉化延遲問題,我們觀察到訓練集最后一天的轉化率遠遠低于前面幾天,對此我們的處理是直接舍棄這一天的樣本。
數據預處理總結
總結一下,我們對于數據的預處理包含下面幾個方面:
四、特征工程
??在本次比賽中,主要包含四部分,單特征、組合特征、泄露特征和基于其他模型構造的特征。
4.1 原始單特征
??每一個原始字段都可以作為instance_id,從而統計相關統計量(例如在過去幾天內的點擊量、轉化次數、轉化率等)。以素材creative_id為例,它是用戶最直接看到的內容,對某個特定的 creative_id,我們統計過去若干天內該 creative_id 的總點擊量、轉化次數和轉化率,作為該 creative_id 取值的三個特征。其物理意義在于,量化地描述了該素材是否更能吸引用戶(點擊量)和發生轉化(轉化率)。
4.2 組合特征
??部分原始字段之間存在著明顯的樹狀層級,詳細可見下圖。例如,每個廣告主下面有若干推廣計劃,每個推廣計劃下面有多個廣告,每個廣告又包含多個素材。他們之中,包含一對一關系(例如一個推廣計劃只能屬于一個廣告主),也存在多對多關系(例如同一個推廣計劃可以為不同的app發出廣告,同一個app也可能收到來自不同推廣計劃的廣告)。對于各種instance_id組合而成的新instance_id,仍可以像原始單特征那樣統計相關統計量。具體地,以 positionID : connectionType 為例,對它的某個取值(指pair取值,比如positionID=0且connectionType=1)統計點擊量和轉化率,其物理意義在于,量化地描述“位置0上的廣告對于連WIFI的用戶所具備的吸引力”。雖然我們不知道位置具體是什么,也不知道1是不是代表WIFI,但是這么統計后,將發現在不同的取值下樣本label的分布變得十分不均勻,也就是說該特征是具有較好的分類效果的。事實也證明,positionID : connectionType 確實是一個強特征。
4.3 leakage特征
??在這類比賽中,我們可以獲取預測當天的所有點擊記錄(正是測試集樣本本身),對于預測當天提取的相關特征,我們稱之為 leakage(泄露),因為在實際的實時系統中,即便可以獲得當前以前的記錄,卻不能獲得當天剩下的記錄,由于泄露了未來的信息,因此稱之為 leakage。具體地,上述的每一個 instance_id(包括單特征和組合特征)的某個取值,都可獲得在當天內距離上一次取該所值經過的時間,以及下一次出現所需要的時間,還有當天內在本次出現之前和之后出現過的總次數。例如,某一個instance user_id=A且creative_id=0 其時間戳是中午12點,經過統計我們發現中午12點之前的它點擊次數為10次,12點之后為1次,如果模型從樣本中學習到的規律是“轉化更偏向于發生在最后幾次點擊”,那么該 instance 發生轉化的概率應該比較大。說到底,這些特征只是對用戶習慣的一種描述,最終決策往往不是取決于單一特征的。
4.4 基于其他模型的特征
4.4.1 tf-idf特征
??tf-idf特征主要針對用戶App安裝列表。將用戶安裝列表看成一個 詞袋模型bag-of-words,每個用戶的安裝列表看作一篇文章,而app就是構成文章的單詞。統計 tf-idf 值,即可得到一個具有一一對應關系的三元組:用戶 : app : tf-idf,以 user_id : app_id 為instance_id,即可直接將 tf-idf 作為特征。實際上,該特征帶來的提升并不算太高,我們認為這是由于安裝列表的稀疏造成的(大多數app在一個列表中只出現過 1 次)。
4.4.2 貝葉斯平滑
??在CTR估計中,一般會統計歷史的展示數NN和點擊數CC,然后用C/NC/N作為廣告CTR的估計。這種估計方法是有問題的,例如投放100次廣告,點擊2次,CTR=2%,于是加大投放廣告到1000次,但點擊只有10次,CTR=1%,同一個廣告CTR相差了一倍,顯然是不合理的。產生該現象的根源來自于樣本量不足,應當默認廣告有一個歷史的展示量和點擊量,在估計CTR時,分別將新的統計量加到分子和分母的常數上,這樣統計出來的CTR誤差才會比較小。貝葉斯平滑的目的,就是根據不同廣告展示和點擊的實際統計值估計出CTR的分布參數,也就是估計分子和分母上的常數。在本題中,我們將CTR的貝葉斯平滑遷移到CVR中。
??具體地,我們假設 “廣告主 : 推廣計劃” pair 的 CVR 服從 Beta 分布,即同一 “廣告主 : 推廣計劃” pair之下,所有 creative_id 服從參數為 CVR 的伯努利分布,也就是說,伯努利中的概率參數 CVR 本身也是一個隨機變量,它服從Beta分布。我們將CTR中的NN和CC遷移為:NN表示點擊量,CC表示轉化量。通過統計每個 “廣告主 : 推廣計劃” pair 取值下,不同 creative_id 的點擊次數 NiNi 和轉化次數 CiCi,代入Beta的極大似然估計,可以求出該 “廣告主 : 推廣計劃” pair 分布的兩個常數,并代入到CVR的估計中,達到平滑的效果。總而言之,認為每一個 “廣告主 : 推廣計劃” pair 各有一個CVR分布,用下面不同素材的統計量估計該分布的值,以更新素材的CVR。
4.5 線下驗證集的構建
??賽題的訓練集為某月的第17天至30天,測試集為第31天。線下驗證集的構造,其原則是確保在模型或特征發生變化時,線下驗證集的準確率與線上的準確率基本符合“同增同減”的規律。如上面所描述,31天存在嚴重的轉化率回溯延遲,帶來了巨大的干擾,因此我們舍去了該天。
- 線下測試:17~22是特征提取區間,23~28作為訓練集,29作為線下驗證
- 線上測試:17~29作為特征提取區間
4.5 特征的選擇
特征選擇上,我們主要采取包裹式和嵌入式相結合的方式。
- 包裹式,指針對不同的特征子集測試模型的性能,選擇性能最佳的模型對應的特征子集。具體地我們實現了方便熱插拔不同特征的代碼,然后暴力遍歷特征子集。
- 嵌入式,指根據提升樹模型輸出的feature importance來決定部分特征的去留。
4.6 特征工程總結
??總結一下,本次比賽中,我們的特征工程主要分為四個部分,單特征、組合特征、泄露特征和基于其他模型構造的特征。構造線下驗證集,根據特征在驗證集上的表現篩選特征,同時參考了模型提供的feature importance。
??特征工程包含了特征的提出、特征生成和特征選擇。其核心在于特征提出,這往往需要基于對數據的觀察和對業務的理解,當然運氣也是很重要的。在有限的比賽時間中遍歷所有的可能性是不現實的,但走投無路之時也只有這種方法而已。
??下面是我參考這里總結的一點關于特征工程的知識圖譜,本次賽題并沒有完全用到上面的所有東西,該圖譜也仍在完善當中,僅供參考。
五、模型
5.1 LR
??LR 適用于特征維度比較高的情況,ID類特征需要先進行Encoding,例如One-hot。LR還可以作為 stacking 的二階段模型,即將一階段訓練的樹模型關于訓練集的輸出作為LR的輸入訓練LR模型。本次比賽中似乎沒有嘗試過。
5.2 樹模型
??本次比賽中主要使用的模型是提升樹GBDT,RF也有試過,但性能上略輸GBDT。
5.2.1 RF 隨機森林
??屬于一種bagging。每次從樣本中有放回地抽取足夠量的樣本,然后訓練樹,樹在結點分裂選擇最佳特征時,首先抽取k個特征(一般選取特征數開平方根),再從中根據信息增益等指標進行選擇,以防止過擬合。當若干樹訓練完成后,使用平均、加權平均或者投票的方式組合成最終模型。
5.2.2 GBDT 梯度提升樹
??GBDT,梯度提升樹。主要使用xgboost和lightgbm,xgboost在傳統的gbdt的基礎上做出了一些改進,包括增益的重新定義、引入L2正則、近似法選取分裂點、預讀取和排序以及并行化加速等。Xgboost的優勢在于能減少過擬合、速度快。Lightgbm則進一步提升了速度并減少內存的開銷。根據比賽中的經驗,二者在準確率上是相近的,但lightgbm要快得多(主要是直方圖算法分裂以及直方圖相減減少了計算量),因此我們后面基本上選擇的是lightgbm。
5.2.3 因子分解機 FM
??一種多項式模型,給我的感覺是很像LR,它也一般被用作stacking的二階段模型。它的輸入一般是Onehot過的非常稀疏的ID類特征。我們主要使用libffm,但不知為何效果總是不佳,所以最終棄用了。
5.2.4 模型融合
??幾乎到了比賽的大后期,我們才發現有模型融合這樣的操作,但那時已經基本上來不及了。在比賽的最后一天,我通宵做了兩個LightGBM的融合,它們分別使用不同的特征子集:目前單模型最好的特征子集,以及篩選中被舍棄的部分特征,提升了1個千分點。因此我們在模型融合方面,其實仍有巨大的提升空間,只不過經驗不足且時間不夠罷了。
六、最重要的部分
我認為在本次比賽中最重要的環節有兩點:特征工程與模型融合。
特征工程中,雖然相當一部分是暴力組合測出來的,但在沒有思路的時候也不失為一種辦法。而一旦增進了對數據和賽題的理解,得到的相關特征就能大幅度提升性能,比如組合特征 positionID : connectionType, 比如貝葉斯平滑 。
模型融合是此類比賽中相當常見的做法,多個“好而不同”的模型通過加權或voting的方式融合在一起,以及模型之間做stacking,都能增加模型的魯棒性和準確性。可惜當時太young太naive,我們在模型融合方面能提升的空間還是存在的。
七、我們和前十名的差距在哪里
比賽結束后,我去聽了前十名的最終答辯,總結了我們和他們的差距如下。
八、面試中被問到過的問題
特征只是反映了用戶行為習慣的某一個方面,只是參與了模型的決策,用戶點擊地越多他越不可能轉化?只能說有這個可能性,而模型正是通過這個特征學習特征與該可能性的關系。
沒有考慮,現在想起來,我認為這可能也是我們成績不夠高的原因之一。應該保留正樣本,對負樣本隨機抽取。
我們并沒有直接把ID類送入樹模型,而是圍繞ID提取了統計特征,來代替特征本身。如果要用到ID本身,可以Onehot后送入FFM或者LR,不適合用樹模型。
附錄:廣告推薦中的貝葉斯平滑
預備小知識
二項分布(nn重伯努利實驗)
P(C|n,μ)=n!C!(n?C)!μC(1?μ)n?CP(C|n,μ)=n!C!(n?C)!μC(1?μ)n?C
Beta分布
p(μ|a,b)=Γ(a+b)Γ(a)Γ(b)μa?1(1?μ)b?1p(μ|a,b)=Γ(a+b)Γ(a)Γ(b)μa?1(1?μ)b?1
估計nn重伯努利實驗的概率μμ
把二項分布的概率密度當做μμ的似然函數,為了估計μμ,需要給μμ設置一個先驗分布。選什么分布呢?選二項分布的共軛分布:Beta分布。
計算后驗概率:
p(μ|C,a,b)=p(μ|a,b)p(C|n,μ)p(C)∝μa+C?1(1?μ)n?C+b?1p(μ|C,a,b)=p(μ|a,b)p(C|n,μ)p(C)∝μa+C?1(1?μ)n?C+b?1
把系數帶上
所以后驗分布也是一個Beta分布:B(a+C,b+n?C)B(a+C,b+n?C)
Beta分布的期望是
a+Ca+b+na+Ca+b+n
一、問題提出
數據的層級結構
??許多場景下,數據呈現層級結構(理解為樹狀)。假設事件(兄弟)之間并不相互獨立,而層級結構中距離近的兩個事件之間的相關性大于距離遠的兩個事件。具體到廣告場景,葉子結點就是不同的廣告,父結點就是廣告主/推廣計劃,從概率的角度講,兄弟廣告之間的CTR應該會相互影響(例如肯德基廣告可能會提升加多寶廣告的點擊率),而同一廣告主的不同廣告應該有相近的CTR分布,或者說廣告風格(肯德基和麥當勞屬于同一集團,它們的CTR分布應該是相似的)。本質上就是說,“不同ID下的廣告的CTR同分布”。
CTR估計不準
??根據歷史點擊統計轉化率CTR存在著歷史CTR與真實CTR相差很大的問題。例如投放100次廣告,發生了兩次點擊,CTR是2%,若增加投放至1000次,點擊只有10次,CTR是1%,兩個CTR相差了一倍。產生這個問題的根源在于投放量不足,而通常的做法是在分子和分母各加一個較大的常數,表示廣告在投放之前就有一個默認的展示次數和點擊次數,從而平滑CTR。
?? 按照層級結構的理論,可以預想一下,為了平滑CTR,應該需要去估計不同ID各自分布(核心是估計分布的參數),由于它是CTR的分布,只要求期望就能得到CTR了(稱為平滑)。
二、理論
現在假設,ID={廣告主=老王,推廣計劃=A計劃} 下有 NN 個不同的廣告。
單個廣告
用μμ表示其中某個廣告的CTR,CC表示廣告被點擊的次數,nn表示廣告被展示的次數,一般來說我們會用 μ??=C/nμ^=C/n 估計該廣告的CTR,這其實是不準的。
首先,廣告的CTR μμ 是一個隨機變量,它服從Beta分布
其次,若已知廣告的CTR μμ,則它的點擊次數 CC 服從伯努利分布 Bin(n,μ)Bin(n,μ)
C~Bin(n,μ)P(C|n,μ)=n!C!(n?C)!μC(1?μ)n?CC~Bin(n,μ)P(C|n,μ)=n!C!(n?C)!μC(1?μ)n?C
伯努利分布是似然函數,而Beta函數則是先驗分布,二者共同決定了后驗分布,即:似然函數 + 先驗分布 = 后驗分布。
N個廣告
父節點 ID={廣告主=老王,推廣計劃=A計劃} 下 NN 個廣告的聯合分布
P(C1,C2,?,CN|n1,n2,?,nN,a,b)=∏i=1NP(Ci|ni,a,b)=∏i=1N∫μiP(Ci,μi|ni,a,b)dμi=∏i=1N∫μiP(Ci|ni,μi)p(μi|a,b)dμi=∏i=1NΓ(a+b)Γ(ni+a+b)Γ(Ci+a)Γ(a)Γ(ni?Ci+b)Γ(b)P(C1,C2,?,CN|n1,n2,?,nN,a,b)=∏i=1NP(Ci|ni,a,b)=∏i=1N∫μiP(Ci,μi|ni,a,b)dμi=∏i=1N∫μiP(Ci|ni,μi)p(μi|a,b)dμi=∏i=1NΓ(a+b)Γ(ni+a+b)Γ(Ci+a)Γ(a)Γ(ni?Ci+b)Γ(b)
極大似然估計 aa 和 bb
取對數似然函數后分別關于aa和bb求偏導數(極大似然估計):
于是迭代更新 aa和bb,直到收斂
a←a∑Ni=1[Ψ(Ci+a)?Ψ(a)]∑Ni=1[Ψ(ni+a+b)?Ψ(a+b)]a←a∑i=1N[Ψ(Ci+a)?Ψ(a)]∑i=1N[Ψ(ni+a+b)?Ψ(a+b)]
b←b∑Ni=1[Ψ(ni?Ci+a)?Ψ(b)]∑Ni=1[Ψ(ni+a+b)?Ψ(a+b)]b←b∑i=1N[Ψ(ni?Ci+a)?Ψ(b)]∑i=1N[Ψ(ni+a+b)?Ψ(a+b)]
最終利用 aa和bb修正CTR:
μ=CN→μ=C+aN+a+bμ=CN→μ=C+aN+a+b
總結
基于CTR在樣本量少時測不準的問題,作出了CTR的相關概率假設,即同廣告主的廣告具有相同的CTR分布(Beta分布),通過極大似然估計獲得超參數aa和bb(實際上它們描述了廣告主的風格),就可以重新估計CTR,從而達到平滑的效果。
參考
總結
以上是生活随笔為你收集整理的第一届腾讯社交广告高校算法大赛经验分享的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学会它,能让你工作学习效率提升10倍!
- 下一篇: import sys