1. Linear Regression
以一元線性回歸為例,該算法的中心思想是:找一條直線,並且讓這條直線盡可能地擬合圖中的數據點:
該模型可簡寫為:y = ax + b,我們需要根據已有的數據對(x, y),找到最佳的參數a, b 。同理,在高維空間中,我們尋找的就是線性分割空間的高維超平面。在優化模型的過程中,我們需要用損失函數 \(L(\hat y, y)\) 來衡量模型參數的好壞,線性回歸常用的損失函數為均方誤差(MSELoss):
\(L(\hat y, y)=\frac{1}{m} \sum_{i=1}^{m} (\hat y^{(i)} - y^{(i)})^2\)
模型訓練(尋找最佳參數)的過程就是求解以下函數的過程:
\(a^*, b^* = \textstyle\arg\min_{a,b}L(\hat y, y)\)
該函數可以通過微積分和線代計算求解(最小二乘法),也可以通過最優化方法求解。在實踐中,由於模型涉及的訓練數據往往規模較大,如果用最小二乘法來解矩陣方程將會消耗過多的計算資源,因此我們常用最優化方法中的梯度下降法來求解該函數
梯度下降法的原理並不復雜,我們只需要從參數的初始值開始,根據訓練數據的計算結果不斷更新參數即可:
\(w_j := w_j - \alpha \frac{\partial }{\partial w_j}L(\omega )\)
批梯度下降和隨機梯度下降都是在上述公式的基礎上做的簡單改進,其目在於提升算法的優化效率,這里就暫時先不展開了
2. Factorization Machines
相關Paper:
- Rendle S . Factorization Machines[C] ICDM 2010
- Rendle S , et al. Fast context-aware recommendations with factorization machines[C]
算法介紹:
- FMs的優點:
- FMs考慮了特征的二階交叉,彌補了邏輯回歸表達能力差的缺陷
- FMs模型復雜度保持為線性,並且改進為高階特征組合時,仍為線性復雜度
- FMs引入隱向量,緩解了數據稀疏帶來的參數難訓練問題
- 在推薦算法的應用場景中,用戶和物品特征中有很多項是categorical類型的,需要經過One-Hot編碼轉化成數值型特征,這將導致樣本數據變得非常稀疏:
- 在推薦算法的應用場景中,用戶和物品特征中有很多項是categorical類型的,需要經過One-Hot編碼轉化成數值型特征,這將導致樣本數據變得非常稀疏:
- FMs的缺點:
- 雖然考慮了特征的交叉,但是表達能力仍然有限,不及深度模型
- 同一特征 x_i 與不同特征組合使用的都是同一隱向量 v_i ,違反了特征與不同特征組合可發揮不同重要性的事實
- 模型原理:
- FM在線性模型的基礎上添加了一個多項式,用於描述特征之間的二階交叉:
\(y = \omega _0 + \sum _{i=1}^{n} \omega _i x_i + \sum _{i=1}^{n-1} \sum _{j=i+1}^{n} \omega _{ij} x_i x_j\)- 上式中:n表示特征維數,不同特征兩兩組合可以得到n(n-1)/2個交叉
- 舉個例子描述特征交叉:假如我們知道“小明既喜歡看戰爭電影,又曾購買過坦克模型”,那么我們就能比僅知道“小明喜歡看戰爭電影”或“小明購買過坦克模型”更能推斷出小明對某軍事類廣告的點擊傾向。從數學角度看,就是我們原本只建模f(x) = z 和 f(y) = z,現在我們能建模f(x, y) = z,這其實就是模型復雜度提升所帶來的擬合能力的提升
- FM在線性模型的基礎上添加了一個多項式,用於描述特征之間的二階交叉:
- 引入交叉特征后帶來的問題:
- 上式中參數w_ij的優化其實是比較困難的,因為在計算梯度時,只有x_i和x_j都不為0時,我們才能得到有效的結果,但由於特征矩陣的稀疏性,使得大部分參數w都難以得到充分的訓練
- 解決方案:
-
FM對於每個特征x_i,學習一個長度為k(k << n)的一維向量v,進而得到一個n×k的矩陣V,於是,兩個特征 x_i 和 x_j 的特征組合的權重值,通過特征對應的向量 v_i 和 v_j 的內積 <v_i, v_j> 來表示,等同於對特征做了一個embedding:
-
這個embedding並不依賴某個特定的特征組合是否出現過,所以只要特征 x_i 和其它任意特征組合出現過,那么就可以學習自己對應的embedding向量
-
- 復雜度分析:算法的計算復雜度為O(kn),推導和化簡過程可見Rendle S . Factorization Machines中的 Lemma 3.1
- 在優化方面,隨機梯度下降(SGD)和交替最小二乘(ALS)的單輪迭代復雜度都是O(kN_z(X)),ALS的優勢在於它不需要指定額外的超參(學習率),因此在效果上更加穩定
3. XGBoost
GBDT是以決策樹(CART)為基學習器的GB算法,XGBoost擴展和改進了GDBT,XGBoost算法更快,准確率也相對較高。我們接下來按順序依次對其進行介紹。
先看決策樹:
-
決策樹模型的構造過程可概括為:循環執行“特征選擇+分裂子樹”,最后觸達閾值停止分裂。在預測階段,我們把樣本特征按樹的分裂過程依次展開,最后樣本的標簽就是葉子節點中占大多數的樣本所對應的標簽:
-
決策樹如何做特征選擇?—— 三種算法(ID3, C4.5, CART)
- ID3以信息熵減幅度作為特征選擇依據,缺點是該算法偏好細粒度高的特征(如uuid),容易過擬合;C4.5在熵減式子中增加了一個分母(分枝數目)作為懲罰項,規避了ID3特征分裂時細粒度過高的問題;CART采用Gini系數作為特征選擇依據,在保持其他算法優點的同時(Gini系數可理解為熵模型的一階泰勒展開),減少了大量的對數運算
-
剪枝策略:
- 預剪枝:在分裂子樹前判斷是否繼續。常用的停止標准包括:“計算分裂前后准確率是否提升”,“檢查分裂后節點內樣本容量是否低於閾值”等。預剪枝策略可以降低過擬合風險,減少模型訓練時間,但同時也會帶來欠擬合風險
- 后剪枝:在決策樹構建完成后刪去不必要的子樹。典型的后剪枝策略如C4.5的“悲觀剪枝法”:自底向上依次判斷各節點分裂前后模型准確率是否提升,刪去對結果無增益的子樹。后剪枝策略的泛化性能常優於預剪枝策略,但其需要更多的訓練時間
-
連續值處理(以CART為例):
- 在解決回歸問題時,CART采用和方差作為特征分割點的選擇方式:對任意有序數值特征a,窮舉分割界限s,計算分割后的兩團簇數據的和方差,最后取分割后和方差最小的界限作為切割閾值:
\(min_{a,s}\left [ min_{c_1} \sum_{x_i \in D_1} (y_i - c_1)^2 + min_{c_2} \sum_{x_i \in D_2} (y_i - c_2)^2\right ]\)
上式中D1,D2代表分割后的兩團數據簇,c1, c2代表兩團數據簇中的數據均值
- 在解決回歸問題時,CART采用和方差作為特征分割點的選擇方式:對任意有序數值特征a,窮舉分割界限s,計算分割后的兩團簇數據的和方差,最后取分割后和方差最小的界限作為切割閾值:
-
接下來我們看GB與GBDT:
- GB(Gradient boosting)是一種集成學習方法,通過聚合多個弱模型,來獲得一個強模型。其核心思路是各模型通過“串聯”的方式,依次擬合其前置模型的殘差,進而實現對模型總體偏差(bias)的糾正。假設我們有M個弱模型,那么上述思想可用公式表述為:
\(\begin{matrix} F_{m+1}(x) = F_m(x) + h(x) , & 1 \le m \le M \end{matrix}\) - 注意上式中后置學習器擬合的h(x)是通過訓練數據計算出來的,其不同於真實數據分布中的殘差,為了對二者作區分,h(x)又被稱作“偽殘差”
- GB(Gradient boosting)是一種集成學習方法,通過聚合多個弱模型,來獲得一個強模型。其核心思路是各模型通過“串聯”的方式,依次擬合其前置模型的殘差,進而實現對模型總體偏差(bias)的糾正。假設我們有M個弱模型,那么上述思想可用公式表述為:
-
GBDT就是用決策樹(CART)充當GB方法中的弱模型(基學習器),進而實現的集成學習算法,其中基學習器的迭代步驟為:
我們注意到:在第一步計算偽殘差時,我們對損失函數求了一個偏導,以此作為目標殘差的近似。為什么這里能用負梯度來估算殘差呢?其實這里蘊含了一個隱藏條件,就是基學習器(CART)的損失函數必須為平方誤差(Square Error Loss),只有這個條件滿足時,我們才能用負梯度近似殘差,相關數學證明可參考:GBDT理解難點 - 擬合負梯度
最后我們看XGBoost:
- XGBoost在總體思路上與GBDT是相同的,它們都是通過串聯決策樹來擬合殘差,二者的不同之處在於目標函數的定義以及實現細節上的差異。從另一個角度看,我們也可以把XGBoost理解為工程視角下,加入了各種tricks以進行強化的GBDT
- XGBoost的目標函數推導:
- XGBoost通過疊加t個基學習器來擬合目標數據分布,從整體來看,其目標函數可分為兩部分——預測誤差懲罰項和模型復雜度懲罰項:
\[\begin{matrix} Obj = \sum_{i=1}^n l(\hat y_i,y_i) + \sum_{t=1}^k \Omega(f_t) & , & \Omega(f_t) = \gamma T_t + \frac{1}{2}\lambda \sum_{j=1}^T \omega _j^2 \end{matrix} \]- 上式中n代表訓練樣本樹,函數l代表預測誤差懲罰項,函數Omega代表模型復雜度懲罰項,T_t代表基學習器t下的葉子節點數目,omega代表基學習器中的權重參數(即L2正則項),gamma和lambda是平衡兩個復雜度懲罰項的權重超參
- 由於Boosting需要依次對各基學習器的結果求和,所以在訓練第t個模型時,算法給出的預測值為:
\[\hat y_i^t = \hat y_i^{t-1} + f_t(x_i) \]- 上式中y hat代表已構建好的基學習器的預測結果,函數f代表正在訓練的基學習器,將其帶入前面給出的目標函數,得到:
\[Obj^{(t)} = \sum_{i=1}^n l(\hat y_i^{t-1} + f_t(x_i),y_i) + \sum_{i=1}^t \Omega(f_i) \]- 已知泰勒二階展開式:
\[f(x+\bigtriangleup x) \approx f(x) + f'(x) \bigtriangleup x + \frac{1}{2}f''(x)\bigtriangleup x^2 \]- 將 \(\hat y_i^t = \hat y_i^{t-1} + f_t(x_i)\) 中的第一個加項視為x,第二個加項視為delta x,對目標函數中的預測誤差懲罰項做二階泰勒展開,得到:
\[Obj^{(t)} \approx \sum_{i=1}^n \left [ l(\hat y_i^{t-1},y_i) + g_i f_t(x_i) + \frac{1}{2}h_if_t^2(x_i) \right ] + \sum_{i=1}^t \Omega(f_i) \]- 上式中g_i是損失函數loss()的一階導數,h_i是損失函數的二階導數
- 由於前置基學習器的預測結果已知,因此 \(l(\hat y_i^{t-1},y_i)\) 在式中是一個常數,其值不影響優化結果,固可從目標式中移除:
\[Obj^{(t)} \approx \sum_{i=1}^n \left [ g_i f_t(x_i) + \frac{1}{2}h_if_t^2(x_i) \right ] + \sum_{i=1}^t \Omega(f_i) \]- 同樣,由於前置學習器的y hat已知,因此在損失函數確定后(比如指定SELoss),g_i和h_i的值也可以通過計算得出,在式中為常數。至此,目標函數中的未知量就只剩當前學習器的輸出值f了。考慮到XGBoost使用的基學習器是決策樹,因此遍歷所有樣本后對各樣本的損失求和,就等同於決策樹接收所有訓練樣本后,對各葉子節點給出的預測值計算損失並求和,即:
\[\sum_{i=1}^n \left [ g_i f_t(x_i) + \frac{1}{2}h_if_t^2(x_i) \right ] = \sum_{j=1}^T \left [ \left ( \sum_{i \in I_j} g_i \right ) \omega_j + \frac{1}{2}\left ( \sum_{i \in I_j} h_i \right ) \omega_j^2 \right ] \]這里T代表葉子節點總數,j代表葉子節點序號,I_j代表該葉子節點中的訓練樣本集,omega_j 代表該葉子節點給出的預測值- 將上式代入目標函數式中,並將復雜度懲罰項Omega()展開,得到:
\[\begin{aligned} Obj^{(t)} &\approx \sum_{j=1}^T \left [ \left ( \sum_{i \in I_j} g_i \right ) \omega_j + \frac{1}{2}\left ( \sum_{i \in I_j} h_i \right ) \omega_j^2 \right ] + \gamma T + \frac{1}{2}\lambda \sum_{j=1}^T \omega _j^2 \\ &= \sum_{j=1}^T \left [ \left ( \sum_{i \in I_j} g_i \right ) \omega_j + \frac{1}{2}\left ( \sum_{i \in I_j} h_i + \lambda \right ) \omega_j^2 \right ] + \gamma T\\ \end{aligned} \]- 進一步,記\(\begin{matrix} G_j = \sum_{i \in I_j} g_i & , & H_j = \sum_{i \in I_j} h_i \end{matrix}\),則上述目標函數可表示為:
\[Obj^{(t)} = \sum_{j=1}^T \left [ G_j \omega_j + \frac{1}{2}\left ( H_j + \lambda \right ) \omega_j^2 \right ] + \gamma T \]- 我們可以在上式中對omega_j求一階導,並令其等於0:
\[\frac{\partial Obj^{(t)}}{\partial\omega_j} = G_j + (H_j + \lambda)\omega_j = 0 \]- 進而將omega_j用其他已知項表達出來:
\[\omega_j^* = -\frac{G_j}{H_J + \lambda} \]- 將上式代入目標函數式,進一步化簡得到:
\[obj = -\frac{1}{2}\sum^T_{j=1}\frac{G_j^2}{H_j+\lambda} + \gamma T \]該式就是我們最終使用的目標函數的形式了,上式中的G和H需要我們指定損失函數,然后分別求一階和二階導得到。通過該目標函數,我們即可在決策樹中對特征進行選擇分裂(窮舉得到使目標函數下降最多的分割方案,當然,其中依然有工程上的優化tricks)。由於XGBoost的目標函數中本身有對模型復雜度的懲罰項,因此我們不需要再做額外的剪枝工作。同時,由於G和H對各訓練樣本間相互沒有依賴,因此各樣本的損失可以並行計算,從而加快了模型的訓練速度。
【參考】