LightGBM算法背景、原理、特點+Python實戰案例
大家好,我是Peter~
今天給大家分享一下樹模型的經典算法:LightGBM,介紹算法產生的背景、原理和特點,最后提供一個基于LightGBM和隨機搜索調優的案例。
LightGBM算法
在機器學習領域,梯度提升機(Gradient Boosting Machines, GBMs)是一類強大的集成學習算法,它們通過逐步添加弱學習器(通常是決策樹)來最小化預測誤差,從而構建一個強大的模型。
在大數據時代,數據集的規模急劇增長,傳統的GBMs由于其計算和存儲成本高昂,難以有效地擴展。
- 例如,對于水平分割的決策樹生長策略,雖然可以生成平衡的樹,但往往會導致模型的區分能力下降;而對于基于葉子的生長策略,雖能提高精度卻容易過擬合。
- 此外,大多數GBM實現在每次迭代中都需要遍歷整個數據集來計算梯度,這在數據量巨大時效率低下。因此,需要一個既能高效處理大規模數據又能保持模型準確度的算法。
為了解決這些問題,Microsoft在2017年推出了LightGBM(Light Gradient Boosting Machine),一個更快速、更低內存消耗、更高性能的梯度提升框架。
官方學習地址:https://lightgbm.readthedocs.io/en/stable/
LightGBM的原理
1、基于直方圖的決策樹算法:
- 原理:LightGBM使用直方圖優化技術,將連續的特征值離散化成特定的bin(即直方圖的桶),減少了在節點分裂時需要計算的數據量。
- 優點:這種方法可以在減少內存使用的同時,提高計算速度。
- 實現細節:對于每個特征,算法都維護一個直方圖,記錄該特征在不同分桶中的統計信息。在進行節點分裂時,可以直接利用這些直方圖的信息,而不需要遍歷所有數據。
2、帶深度限制的leaf-wise樹生長策略:
- 原理:與傳統的水平分割不同,leaf-wise的生長策略是每次從當前所有葉子節點中選擇分裂收益最大的節點進行分裂。
- 優點:這種策略可以使得決策樹更加側重于數據中的異常部分,通常可以得到更好的精度。
- 缺點:容易導致過擬合,特別是當數據中有噪聲時。
- 改進措施:LightGBM通過設置最大深度限制來防止過擬合。
3、單邊梯度采樣(GOSS):
- 原理:對于數據集中的大梯度樣本,GOSS算法只保留數據的一部分(通常是大梯度的樣本),減少計算量同時保證不會損失太多的信息。
- 優點:這種方法可以在不顯著損失精度的情況下加快訓練速度。
- 應用場景:特別適用于數據傾斜嚴重的情況。
4、互斥特征捆綁(EFB):
- 原理:EFB是一種減少特征數量,提高計算效率的技術。它將互斥的特征(即從不同時為非零的特征)進行合并,以減少特征維度。
- 優點:提高了內存的使用效率和訓練速度。
- 實現細節:通過特征的互斥性,算法可以在同一時間處理更多的特征,從而減少了實際處理的特征數。
5、支持并行和分布式學習:
- 原理:LightGBM支持多線程學習,能夠利用多個CPU進行并行訓練。
- 優點:顯著提高了在多核處理器上的訓練速度。
- 擴展性:還支持分布式學習,可以利用多臺機器共同訓練模型。
6、緩存優化:
- 原理:優化了對數據的讀取方式,可以使用更多的緩存來加快數據交換的速度。
- 優點:特別是在大數據集上,緩存優化可以顯著提升性能。
7、支持多種損失函數:
- 特點:除了常用的回歸和分類的損失函數外,LightGBM還支持自定義損失函數,滿足不同的業務需求。
8、正則化和剪枝:
- 原理:提供了L1和L2正則化項來控制模型復雜度,避免過擬合。
- 實現:實現了后向剪枝的策略來進一步防止過擬合。
9、模型解釋性:
- 特點:由于是基于決策樹的模型,LightGBM具有良好的模型解釋性,可以通過特征重要性等方式理解模型的決策邏輯。
LightGBM的特點
高效性
- 速度優勢:通過直方圖優化和 leaf-wise 生長策略,LightGBM 在保證精度的同時大幅提升了訓練速度。
- 內存使用:相比于其他GBM實現,LightGBM 需要的內存更少,這使得它能夠處理更大的數據集。
準確性
- 最佳優先的生長策略:LightGBM 采用的 leaf-wise 生長策略可以更緊密地擬合數據,通常可以得到比水平分割更好的精度。
- 避免過擬合的方法:通過設置最大深度限制和后向剪枝,LightGBM 能夠在提升模型精度的同時避免過擬合。
可擴展性
- 并行和分布式學習:LightGBM 的設計支持多線程和分布式計算,這使得它能夠充分利用現代硬件的計算能力。
- 多平臺支持:LightGBM 可以在 Windows、macOS 和 Linux 等多種操作系統上運行,支持 Python、R、Java 等多種編程語言。
易用性
- 參數調優:LightGBM 提供了豐富的參數選項,方便用戶根據具體問題進行調整。
- 預訓練模型:用戶可以從預訓練的模型開始,加速自己的建模過程。
- 模型解釋工具:LightGBM 提供了特征重要性評估工具,幫助用戶理解模型的決策過程。
導入庫
In [1]:
import numpy as np
import lightgbm as lgb
from sklearn.model_selection import train_test_split, RandomizedSearchCV
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score
import warnings
warnings.filterwarnings("ignore")
加載數據
加載公開的iris數據集:
In [2]:
# 加載數據集
data = load_iris()
X, y = data.data, data.target
y = [int(i) for i in y] # 將標簽轉換為整數
In [3]:
X[:3]
Out[3]:
array([[5.1, 3.5, 1.4, 0.2],
[4.9, 3. , 1.4, 0.2],
[4.7, 3.2, 1.3, 0.2]])
In [4]:
y[:10]
Out[4]:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
劃分數據
In [5]:
# 劃分訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
同時創建LightGBM數據集:
In [6]:
lgb_train = lgb.Dataset(X_train, label=y_train)
參數設置
In [7]:
# 設置參數范圍
param_dist = {
'boosting_type': ['gbdt', 'dart'], # 提升類型 梯度提升決策樹(gbdt)和Dropouts meet Multiple Additive Regression Trees(dart)
'objective': ['binary', 'multiclass'], # 目標;二分類和多分類
'num_leaves': range(20, 150), # 葉子節點數量
'learning_rate': [0.01, 0.05, 0.1], # 學習率
'feature_fraction': [0.6, 0.8, 1.0], # 特征采樣比例
'bagging_fraction': [0.6, 0.8, 1.0], # 數據采樣比例
'bagging_freq': range(0, 80), # 數據采樣頻率
'verbose': [-1] # 是否顯示訓練過程中的詳細信息,-1表示不顯示
}
隨機搜索調參
In [8]:
# 初始化模型
model = lgb.LGBMClassifier()
# 使用隨機搜索進行參數調優
random_search = RandomizedSearchCV(estimator=model,
param_distributinotallow=param_dist, # 參數組合
n_iter=100,
cv=5, # 5折交叉驗證
verbose=2,
random_state=42,
n_jobs=-1)
# 模型訓練
random_search.fit(X_train, y_train)
Fitting 5 folds for each of 100 candidates, totalling 500 fits
輸出最佳的參數組合:
In [9]:
# 輸出最佳參數
print("Best parameters found: ", random_search.best_params_)
Best parameters found: {'verbose': -1, 'objective': 'multiclass', 'num_leaves': 87, 'learning_rate': 0.05, 'feature_fraction': 0.6, 'boosting_type': 'gbdt', 'bagging_freq': 22, 'bagging_fraction': 0.6}
使用最佳參數建模
In [10]:
# 使用最佳參數訓練模型
best_model = random_search.best_estimator_
best_model.fit(X_train, y_train)
# 預測
y_pred = best_model.predict(X_test)
y_pred = [round(i) for i in y_pred] # 將概率轉換為類別
# 評估模型
print('Accuracy: %.4f' % accuracy_score(y_test, y_pred))
Accuracy: 0.9667