即時競標的機器學習
在過去幾年中,行動廣告和遊戲產業發生了革命性的變化,因為神經網絡被廣泛應用於廣告任務,包括點擊預測。這一轉變發生在大型語言模型(Large Language Models, LLMs)和其他人工智慧創新成功之前,但它正在建立在這波浪潮的動力上。行動遊戲產業每年在用戶獲取上花費數十億美元,像 Applovin 這樣的頂尖公司市值超過 1000 億美元。在這篇文章中,我們將討論一種傳統的機器學習方法來進行點擊預測,提供轉向深度學習的動機,並使用來自 Kaggle 的數據集提供這種方法的實際例子,詳細說明這種方法所帶來的一些增強效果。
在廣告技術領域,大多數大型科技公司可能正在使用深度學習來預測用戶行為。社交媒體平台已經接受了從傳統機器學習(ML)到深度學習的轉變,這在 Reddit 和 LinkedIn 的帖子中都有所提及。在行動遊戲領域,Moloco、Liftoff 和 Applovin 都分享了他們轉向深度學習或硬體加速以改善用戶獲取平台的細節。大多數需求方平台(Demand Side Platforms, DSPs)現在都希望利用神經網絡來提高其平台在行動用戶獲取中的價值。
我們將首先討論邏輯回歸作為預測用戶行為的行業標準,討論這種方法的一些不足之處,然後展示深度學習作為點擊預測的解決方案。我們將深入探討經典機器學習筆記本和深度學習筆記本的實現,預測用戶是否會點擊廣告。我們不會深入到最先進的技術,但會強調深度學習提供的許多優勢。
這篇文章中的所有圖片,除了標題圖片外,都是作者在上述筆記本中創建的。我們在這篇文章中探索的 Kaggle 數據集具有 CC0:公共領域許可。
需求方平台通常提供的用戶獲取目標類型之一是每次點擊成本模型,廣告商在平台在行動設備上展示廣告並且用戶點擊時會被收費。我們將專注於這個目標類型以保持簡單,但大多數廣告商更喜歡專注於推動安裝或獲取會在其應用中花錢的用戶的目標類型。
在程式化競標中,DSP 與一個或多個廣告交易所集成,這些交易所為平台提供競標的庫存。大多數交易所使用 OpenRTB 規範的版本向 DSP 發送競標請求,並以標準化格式返回響應。對於來自供應方平台(Supply Side Platform, SSP)的每個廣告請求,交易所會進行拍賣,響應最高價格的 DSP 獲勝。然後,交易所將中標響應提供給 SSP,這可能會導致在行動設備上展示廣告。
為了讓 DSP 與廣告交易所集成,必須經過一個入門過程,以確保 DSP 能夠滿足交易所的技術要求,這通常要求 DSP 在 120 毫秒內響應競標請求。這是一個巨大的挑戰,因為一些交易所每秒提供超過 100 萬個競標請求,而 DSP 通常與幾個交易所集成。例如,Moloco 在高峰時期每秒響應超過 500 萬個請求(QPS)。由於延遲要求和請求的巨大規模,在 DSP 中使用機器學習進行用戶獲取是具有挑戰性的,但這也是滿足廣告商目標的必要條件。
要作為 DSP 賺錢,您需要能夠提供符合廣告商目標的廣告展示,同時產生淨收入。為了實現這一點,DSP 需要以低於展示所能帶來的預期價值的價格進行競標,同時又要高於請求的競標底線,以便在與其他 DSP 的拍賣中獲勝。需求方平台按展示次數收費,這對應於每千次展示成本(CPM)模型。如果廣告商的目標是每次點擊成本(CPC),那麼 DSP 需要將 CPC 值轉換為 CPM 值進行競標。我們可以使用機器學習來預測用戶點擊展示的可能性,稱為 p_ctr。我們可以這樣計算競標價格:
cpm = target_cpc * p_ctr
bid_price = cpm * bid_shade
我們使用點擊事件的可能性來將每次點擊成本轉換為每千次展示成本,然後應用一個小於 1.0 的競標陰影,以確保我們為廣告商提供的價值超過我們為展示廣告向交易所支付的費用。
為了使點擊預測模型在程式化用戶獲取中表現良好,我們希望模型具有以下特性:
- 大偏差:我們希望點擊模型具有高度的區分能力,能夠區分不太可能導致點擊的展示和非常可能導致點擊的展示。如果模型的偏差不足,它將無法在拍賣中與其他 DSP 競爭。
- 良好校準:我們希望模型的預測轉換率與 DSP 購買的廣告展示的實際轉換率相符。這意味著我們更喜歡模型的輸出可以解釋為轉換發生的概率。校準不良將導致無效的支出。
- 快速評估:我們希望在每秒競標數百萬個請求時降低計算成本,並且希望模型能快速推斷。
- 並行評估:理想情況下,我們希望能夠並行運行模型推斷以提高吞吐量。對於單個競標請求,DSP 可能會考慮數百個競標的活動,每個活動都需要一個 p_ctr 值。
許多廣告技術平台最初使用邏輯回歸進行點擊預測,因為它們在前三個期望特性上表現良好。隨著時間的推移,人們發現深度學習模型在偏差目標上能比邏輯回歸表現得更好,因為神經網絡在區分點擊和不點擊的展示方面更具優勢。此外,神經網絡可以使用批量評估,並且與並行評估的第四個特性相符。
需求方平台能夠將邏輯回歸模型推進到相當遠的地步,這是我們在下一部分中將要討論的,但它們在用戶獲取的應用上確實存在一些界限。深度神經網絡(DNN)可以克服其中一些問題,但也會帶來新的挑戰。
廣告技術公司已經使用邏輯回歸進行點擊預測超過十年。例如,Facebook 在 2014 年的 ADKDD 上展示了使用邏輯回歸結合其他模型的情況。使用邏輯回歸進行點擊預測有許多不同的方法,但我將專注於我過去工作過的一種名為 Big Logistic 的方法。這種方法的基本思想是將所有特徵轉換為標記,創建標記的組合以表示交叉或特徵交互,然後創建一個標記列表,用於將輸入特徵轉換為稀疏向量表示。這是一種將每個特徵進行 1-hot 編碼的方式,所有特徵都是二元的,這有助於簡化點擊模型的超參數調整。這是一種可以支持數值、類別和多熱特徵作為輸入的方法。
為了確定這種方法在實踐中的樣子,我們將提供一個使用 CTR In Advertisement Kaggle 數據集訓練點擊預測模型的實際例子。特徵編碼、模型訓練和評估的完整筆記本可以在這裡找到。我使用 Databricks、PySpark 和 MLlib 進行這個流程。
該數據集提供了一個帶標籤的訓練數據集和一個不帶標籤的測試數據集。為了這個練習,我們將訓練文件拆分為訓練和測試組,以便我們對所有記錄都有標籤。我們創建了一個 90/10% 的拆分,其中訓練集有 414,000 條記錄,測試集有 46,000 條記錄。該數據集有 15 列,包括一個標籤,2 列我們將忽略(session_id 和 user_id),以及 12 個類別值,我們將用作模型中的特徵。上表顯示了一些樣本記錄。
我們將執行的第一步是對數據集進行標記化,這是一種 1-hot 編碼的形式。我們通過將特徵名稱和特徵值連接起來,將每一列轉換為字符串值。例如,我們將為上表中的第一行創建以下標記:
[“product_c”, “campaign_id_359520”, “webpage_id_13787”, ..]
對於空值,我們使用“null”作為值,例如“product_null”。我們還創建所有兩個特徵的組合,這會生成額外的標記:
[“product_c*campaign_id_359520”, “”, “product_c*webpage_id_13787”, “campaign_id_359520*webpage_id_13787”,..]
我們在 PySpark 數據框上使用 UDF 將 12 列轉換為字符串向量。結果數據框包括標記列表和標籤,如下所示。
然後,我們創建一個頂部標記列表,為每個標記分配一個索引,並使用標記名稱到標記索引的映射來編碼數據。我們將標記列表限制為至少有 1000 個示例的值,這樣大約得到了 2500 個標記。
然後,我們將這個標記列表應用到數據集中的每條記錄,將標記列表轉換為稀疏向量表示。如果一條記錄包含某個索引的標記,則該值設置為 1;如果缺少標記,則該值設置為 0。這樣就得到了可以用於 MLlib 訓練邏輯回歸模型的數據集。
我們將數據集拆分為訓練和測試組,擬合模型到訓練數據集,然後轉換測試數據集以獲得預測。
classifier = LogisticRegression(featuresCol = ‘features’,
labelCol = ‘label’, maxIter = 50, regParam = 0.01, elasticNetParam = 0)
lr_model = classifier.fit(train_df)
pred_df = lr_model.transform(test_df).cache()
這個過程產生了以下離線指標,我們將在下一部分中與深度學習模型進行比較。
Actual Conv: 0.06890
Predicted Conv: 0.06770
Log Loss: 0.24795
ROC AUC: 0.58808
PR AUC: 0.09054
AUC 指標看起來不太好,但在我們探索的特徵中,數據集的信號並不多,而其他參與者在 Kaggle 比賽中的 ROC 指標通常更低。數據集的另一個限制是類別值的基數低,只有少量不同的值。這導致參數計數低,只有 2500 個特徵,限制了模型的偏差。
邏輯回歸在點擊預測中表現良好,但當處理高基數特徵時,我們會遇到挑戰。在行動廣告技術中,廣告顯示的出版商應用程序是一個高基數特徵,因為可能有數百萬個潛在的行動應用程序可以顯示廣告。如果我們想將出版商應用程序作為特徵包含在模型中,並使用 1-hot 編碼,我們將最終得到大量的參數計數。尤其是在我們對出版商應用程序和其他高基數特徵(例如設備型號)進行特徵交叉時,情況尤為如此。
我曾經處理過的邏輯回歸點擊模型擁有超過 5000 萬個參數。在這種規模下,MLlib 的邏輯回歸實現會遇到訓練問題,因為它在訓練循環中會使向量變得稠密。為了避免這個瓶頸,我使用了 Fregata 庫,該庫使用稀疏向量直接進行梯度下降,並採用模型平均策略。
大型點擊模型的另一個問題是模型推斷。如果在邏輯模型中包含太多參數,則可能會評估緩慢,顯著增加模型服務成本。
深度學習是一個不錯的點擊模型解決方案,因為它提供了有效處理高基數稀疏特徵的方法。我們在深度學習模型中將使用的一個關鍵層是嵌入層,它將類別特徵作為輸入,並將稠密向量作為輸出。通過嵌入層,我們為類別特徵的詞彙中的每個條目學習一個向量,參數的數量是詞彙大小乘以輸出稠密向量的大小,我們可以控制。神經網絡可以通過在嵌入的稠密層輸出之間創建交互來減少參數計數,而不是在邏輯回歸中使用的稀疏 1-hot 編碼方法之間進行交叉。
嵌入層只是神經網絡能夠提供優於邏輯回歸模型的改進的一種方式,因為深度學習框架提供了多種層類型和架構。我們將專注於嵌入層,為了簡化問題,我們將創建一個管道,將數據集編碼為 TensorFlow 記錄,然後使用嵌入層和交叉層訓練模型以進行點擊預測。數據準備、模型訓練和評估的完整筆記本可以在這裡找到。
我們執行的第一步是為每個要編碼的特徵生成詞彙。對於每個特徵,我們找到所有出現超過 100 次的值,其他所有值都歸類為超出詞彙(OOV)值。然後,我們編碼所有類別特徵並將它們組合成一個名為 int 的單一張量,如下所示。
然後,我們將 Spark 數據框保存為 TensorFlow 記錄到雲存儲中。
output_path = “dbfs:/mnt/ben/kaggle/train/”
train_df.write.format(“tfrecords”).mode(“overwrite”).save(output_path)
然後,我們將文件複製到驅動程序節點,並為訓練和評估模型創建 TensorFlow 數據集。
def getRecords(paths):
features = {‘int’: FixedLenFeature([len(vocab_sizes)], tf.int64),’label’: FixedLenFeature([1], tf.int64)}
@tf.function
def _parse_example(x):
f = tf.io.parse_example(x, features)
return f, f.pop(“label”)
dataset = tf.data.TFRecordDataset(paths)
dataset = dataset.batch(10000)
dataset = dataset.map(_parse_example)
return dataset
training_data = getRecords(train_paths)
test_data = getRecords(test_paths)
然後,我們創建一個 Keras 模型,其中輸入層是每個類別特徵的嵌入層,我們有兩個隱藏的交叉層,最後一層是用於傾向預測的 sigmoid 激活輸出層。
cat_input = tf.keras.Input(shape=(len(vocab_sizes)),
name = “int”, dtype=’int64′)
input_layers = [cat_input]
cross_inputs = []
for attribute in categories_index:
index = categories_index[attribute]
size = vocab_sizes[attribute]
category_input = cat_input[:,(index):(index+1)]
embedding = keras.layers.Flatten()(keras.layers.Embedding(size, 5)(category_input))
cross_inputs.append(embedding)
cross_input = keras.layers.Concatenate()(cross_inputs)
cross_layer = tfrs.layers.dcn.Cross()
crossed_ouput = cross_layer(cross_input, cross_input)
cross_layer = tfrs.layers.dcn.Cross()
crossed_ouput = cross_layer(cross_input, crossed_ouput)
sigmoid_output=tf.keras.layers.Dense(1,activation=”sigmoid”)(crossed_ouput)
model = tf.keras.Model(inputs=input_layers, outputs = [ sigmoid_output ])
model.summary()
生成的模型有 7,951 個參數,這大約是我們邏輯回歸模型的三倍大小。如果類別具有更大的基數,那麼我們預期邏輯模型的參數計數會更高。我們將模型訓練 40 個時期:
metrics=[tf.keras.metrics.AUC(), tf.keras.metrics.AUC(curve=”PR”)]
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-3),
loss=tf.keras.losses.BinaryCrossentropy(), metrics=metrics)
history = model.fit(x = training_data, epochs = 40,
validation_data = test_data, verbose=0)
現在我們可以比較邏輯回歸模型和 DNN 模型之間的離線指標:
Logit DNN
Actual Conv: 0.06890 0.06890
Predicted Conv: 0.06770 0.06574
Log Loss: 0.24795 0.24758
ROC AUC: 0.58808 0.59284
PR AUC: 0.09054 0.09249
我們確實看到在 log loss 指標上有所改善,越低越好,而 AUC 指標上越高越好。主要的改善是精確度-召回(PR)AUC 指標,這可能幫助模型在拍賣中表現更好。DNN 模型的一個問題是模型校準較差,DNN 的平均預測值比邏輯回歸模型更偏離。我們需要進行更多的模型調整以改善模型的校準。
我們現在正處於廣告技術深度學習的時代,公司正在使用各種架構來實現廣告商的用戶獲取目標。在這篇文章中,我們展示了如何從邏輯回歸遷移到具有嵌入層的簡單神經網絡,從而為點擊預測模型提供更好的離線指標。以下是一些我們可以利用深度學習來改善點擊預測的其他方法:
- 使用預訓練模型的嵌入:我們可以使用 BERT 等模型將應用商店描述轉換為向量,以便用作點擊模型的輸入。
- 探索新架構:我們可以探索 DCN 和 TabTransformer 架構。
- 增加非表格數據:我們可以使用 img2vec 從創意資產創建輸入嵌入。
感謝您的閱讀!
本文由 AI 台灣 運用 AI 技術編撰,內容僅供參考,請自行核實相關資訊。
歡迎加入我們的 AI TAIWAN 台灣人工智慧中心 FB 社團,
隨時掌握最新 AI 動態與實用資訊!