個性化排序算法實踐(四)——GBDT+LR


本質上GBDT+LR是一種具有stacking思想的二分類器模型,所以可以用來解決二分類問題。這個方法出自於Facebook 2014年的論文 Practical Lessons from Predicting Clicks on Ads at Facebook
GBDT+LR 使用最廣泛的場景是CTR點擊率預估,即預測當給用戶推送的廣告會不會被用戶點擊。
點擊率預估模型涉及的訓練樣本一般是上億級別,樣本量大,模型常采用速度較快的LR。但LR是線性模型,學習能力有限,此時特征工程尤其重要。現有的特征工程實驗,主要集中在尋找到有區分度的特征、特征組合,折騰一圈未必會帶來效果提升。GBDT算法的特點正好可以用來發掘有區分度的特征、特征組合,減少特征工程中人力成本。

思想

GBDT+LR 由兩部分組成,其中GBDT用來對訓練集提取特征作為新的訓練輸入數據,LR作為新訓練輸入數據的分類器。

  1. GBDT首先對原始訓練數據做訓練,得到一個二分類器,當然這里也需要利用網格搜索尋找最佳參數組合。
  2. 與通常做法不同的是,當GBDT訓練好做預測的時候,輸出的並不是最終的二分類概率值,而是要把模型中的每棵樹計算得到的預測概率值所屬的葉子結點位置記為1,這樣,就構造出了新的訓練數據。

設GBDT有兩個弱分類器,分別以藍色和紅色部分表示,其中藍色弱分類器葉子結點個數為3,紅色弱分類器葉子結點個數為2,並且藍色弱分類器中對0-1 的預測結果落到了第二個葉子結點上,紅色弱分類器中對0-1 的預測結果也落到了第二個葉子結點上。那么我們就記藍色弱分類器的預測結果為[0 1 0],紅色弱分類器的預測結果為[0 1],綜合起來看,GBDT的輸出為這些弱分類器的組合[0 1 0 0 1] ,或者一個稀疏向量(數組)。在一個具有n個弱分類器、共計m個葉子結點的GBDT中,每一條訓練數據都會被轉換為1*m維稀疏向量,且有n個元素為1,其余m-n 個元素全為0。

GBDT+LR

  1. 新的訓練數據構造完成后,下一步就要與原始的訓練數據中的label(輸出)數據一並輸入到Logistic Regression分類器中進行最終分類器的訓練。思考一下,在對原始數據進行GBDT提取為新的數據這一操作之后,數據不僅變得稀疏,而且由於弱分類器個數,葉子結點個數的影響,可能會導致新的訓練數據特征維度過大的問題,因此,在Logistic Regression這一層中,可使用正則化來減少過擬合的風險,在Facebook的論文中采用的是L1正則化。

實踐

采用,lightgbm+lr訓練的模式進行訓練與測試。具體如下:
1、准備訓練數據,配置lightgbm訓練參數,假設我們設置100棵樹,每棵樹64個葉子結點。
2、lightgbm訓練預測

# train
gbm = lgb.train(params,
                lgb_train,
                num_boost_round=100,
                valid_sets=lgb_train)

print('Save model...')
# save model to file
gbm.save_model('model.txt')

print('Start predicting...')
# predict and get data on leaves, training data
y_pred = gbm.predict(X_train, pred_leaf=True)

這里返回訓練數據在訓練好的模型里預測結果所在的每棵樹中葉子節點的位置(索引),形式為樣本個數*100的二維數組。
3、構造Ont-hot數組作為新的訓練數據
這里並沒有使用sklearn中的OneHotEncoder(),也沒有使用pandas中的get_dummies(),而是手工創建一個One-hot數組。

transformed_training_matrix = np.zeros([len(y_pred), len(y_pred[0]) * num_leaf],
                                       dtype=np.int64)  # N * num_tress * num_leafs
for i in range(0, len(y_pred)):
    temp = np.arange(len(y_pred[0])) * num_leaf + np.array(y_pred[i])
    transformed_training_matrix[i][temp] += 1

先構造一個One-hot數組,通過把每棵樹的起點索引組成一個列表(這代碼里就是 np.arange(len(y_pred[0])) * num_leaf),再加上由落在每棵樹葉子節點的索引組成的列表(np.array(y_pred[i])),就得到了往二維零數組里插入元素的索引信息。
4、lr訓練預測

lm = LogisticRegression(penalty='l2',C=0.05) # logestic model construction
lm.fit(transformed_training_matrix,y_train)  # fitting the data
y_pred_test = lm.predict_proba(transformed_testing_matrix)   # Give the probabilty on each label

使用sklearn接口訓練即可。

Q&A

可以用RF或者XGB嗎?

RF也是多棵樹,但從效果上有實踐證明不如GBDT。且GBDT前面的樹,特征分裂主要體現對多數樣本有區分度的特征;后面的樹,主要體現的是經過前N顆樹,殘差仍然較大的少數樣本。優先選用在整體上有區分度的特征,再選用針對少數樣本有區分度的特征,思路更加合理,這應該也是用GBDT的原因。

可以用FM嗎?

使用FM算法代替LR,可以解決了Logistic Regression的模型表達效果及高維稀疏矩陣的訓練開銷較大的問題。但是因為采用FM對本來已經是高維稀疏矩陣做完特征交叉后,新的特征維度會更加多,並且由於元素非0即1,新的特征數據可能也會更加稀疏。
我們需要再次回到GBDT構造新訓練數據這里。當GBDT構造完新的訓練樣本后,我們要做的是對每一個特征做與輸出之間的特征重要度評估並篩選出重要程度較高的部分特征,這樣,GBDT構造的高維的稀疏矩陣就會減少一部分特征,也就是說得到的稀疏矩陣不再那么高維了。之后,對這些篩選后得到的重要度較高的特征再做FM算法構造交叉項,進而引入非線性特征,繼而完成最終分類器的訓練數據的構造及模型的訓練。

GBDT與LR融合方案
AD ID類特征在CTR預估中是非常重要的特征,直接將AD ID作為feature進行建樹不可行,故考慮為每個AD ID建GBDT樹。但互聯網時代長尾數據現象非常顯著,廣告也存在長尾現象,為了提升廣告整體投放效果,不得不考慮長尾廣告。在GBDT建樹方案中,對於曝光充分訓練樣本充足的廣告,可以單獨建樹,發掘對單個廣告有區分度的特征,但對於曝光不充分樣本不充足的長尾廣告,無法單獨建樹,需要一種方案來解決長尾廣告的問題。
綜合考慮方案如下,使用GBDT建兩類樹,非ID建一類樹,ID建一類樹。
1)非ID類樹:不以細粒度的ID建樹,此類樹作為base,即便曝光少的廣告、廣告主,仍可以通過此類樹得到有區分性的特征、特征組合。
2)ID類樹:以細粒度 的ID建一類樹,用於發現曝光充分的ID對應有區分性的特征、特征組合。如何根據GBDT建的兩類樹,對原始特征進行映射?以如下圖3為例,當一條樣本x進來之后,遍歷兩類樹到葉子節點,得到的特征作為LR的輸入。

參考:
CTR預估(二)--LR與GBDT融合方案
GBDT+LR算法解析及Python實現
Github


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM