文章目录
- 一、算法概念
- 二、算法原理
- (一)Histogram
- (二)GOSS
- 1、信息增益
- 2、近似误差
- (三)EFB
- 三、算法优缺点
- (一)优点
- (二)缺点
- 四、LightGBM分类任务实现对比
- (一)数据加载和样本分区
- 1、Python代码
- 2、Sentosa_DSML社区版
- (二)模型训练
- 1、Python代码
- 2、Sentosa_DSML社区版
- (三)模型评估和模型可视化
- 1、Python代码
- 2、Sentosa_DSML社区版
- 五、LightGBM回归任务实现对比
- (一)数据加载和样本分区
- 1、Python代码
- 2、Sentosa_DSML社区版
- (二)模型训练
- 1、Python代码
- 2、Sentosa_DSML社区版。
- (三)模型评估和模型可视化
- 1、Python代码
- 2、Sentosa_DSML社区版
- 六、总结
一、算法概念
什么是LightGBM?
LightGBM属于Boosting集合模型中的一种,LightGBM和XGBoost一样是对GBDT的高效实现。LightGBM在很多方面会比XGBoost表现更为优秀。LightGBM有以下优势:更快的训练效率、低内存使用、更高的准确率、支持并行化学习、可处理大规模数据。
LightGBM继承了XGBoost的许多优点,包括对稀疏数据的优化、并行训练、支持多种损失函数、正则化、bagging(自助采样)和早停机制。然而,二者之间的主要区别在于树的构建方式。LightGBM并不像大多数其他实现那样逐层生长树,而是采用逐叶生长的方式。它每次选择可以最大化减少损失的叶子节点进行扩展。
此外,LightGBM并不像XGBoost或其他常见的实现那样使用基于排序的决策树学习算法,该算法在排序后的特征值中寻找最佳的分割点。相反,LightGBM实现了一种高度优化的基于直方图的决策树学习算法,在效率和内存使用上具有显著优势。
LightGBM在XGBoost的基础上引入了三项关键技术,使得其在保持较高精度的同时加速了算法运行。这三项技术分别是直方图算法(Histogram)、基于梯度的单侧采样(GOSS)和互斥特征捆绑(EFB)。
Histogram通过将连续特征值离散化为直方图,减少寻找最佳分割点的复杂度,降低计算成本和内存占用;
GOSS通过在训练过程中优先保留梯度较大的样本,减少计算量;
EFB则通过将互斥的特征捆绑在一起,减少特征维度,提升训练速度。
通过这三项算法的引入,LightGBM生成一个叶子节点需要的计算复杂度大幅度降低,从而极大节约了计算时间。
二、算法原理
(一)Histogram
LightGBM 使用的直方图算法的核心思想是将连续的浮点数特征离散化为k个离散值。将原本可能无限取值的特征分割成较少的区间(分桶),直方图中的每一个“桶”(bin)对应一个特征区间,记录该区间内样本的累计统计量,如梯度累加和样本数量。在特征选择时,不需要再逐个遍历所有样本的具体特征值,而是根据直方图的统计结果,直接在离散值的基础上进行遍历。通过比较各个桶中的累计统计量,可以快速找到能够带来最大增益的分割点。
算法流程如下图所示:
首先,外层循环遍历树的深度,从1到最大深度d,对每个当前层的节点,获取对应的数据索引 usedRows;然后,对于每个特征k,构建直方图H,直方图H的作用是将连续的浮点特征值离散化到不同的区间(桶)中,便于后续进行增益计算。;其次,遍历每条数据,更新直方图中的值(针对每个特征)。遍历当前节点的样本,对于每个样本,根据其特征值将其放入对应的直方图桶中,同时更新该桶的统计值,直方图汇总了该节点样本在不同特征值区间的分布情况。;接下来,在直方图H上,遍历所有离散的区间,计算每个区间的分割增益,找出所有叶节点中增益最大的分割点为最优分割点,将该最优分割点对应的叶节点的数据分割成两批。;最后,根据最优分割点,更新rowSet和nodeSet,准备下一层的分裂操作,直到达到最大深度或满足停止条件为止。
(二)GOSS
GOSS算法的核心思想是通过优先选择大梯度的样本进行训练,因为大梯度的数据对模型的改进有更大的贡献,而小梯度的数据通过采样来减少计算量,并调整它们的权重以平衡影响。
GOSS 算法的核心流程如下:首先,根据样本点的梯度绝对值对它们进行降序排序,并选取梯度较大的前a%样本作为大梯度样本集;然后从剩余的梯度较小的样本中随机采样出 b(1−a)% 的小梯度样本。将大梯度样本和小梯度样本合并后,对小梯度样本赋予权重,使用这些样本训练新的弱学习器(如决策树)。重复上述步骤,直到达到指定的迭代次数或模型收敛。
1、信息增益
GOSS 算法中的增益计算公式用于衡量特征的分裂点是否最优。通过GOSS采样后,特征
j
j
j在分裂点
d
d
d的增益计算公式如下所示:
V
~
j
(
d
)
=
1
n
(
(
∑
x
i
∈
A
l
g
i
+
1
−
a
b
∑
x
i
∈
B
i
g
i
)
2
n
l
j
(
d
)
+
(
∑
x
i
∈
A
r
g
i
+
1
−
a
b
∑
x
i
∈
B
r
g
i
)
2
n
r
j
(
d
)
)
\tilde{V}_j(d)=\frac{1}{n}\left(\frac{(\sum_{x_i\in A_l}g_i+\frac{1-a}{b}\sum_{x_i\in B_i}g_i)^2}{n_l^j(d)}+\frac{(\sum_{x_i\in A_r}g_i+\frac{1-a}{b}\sum_{x_i\in B_r}g_i)^2}{n_r^j(d)}\right)
V~j(d)=n1(nlj(d)(∑xi∈Algi+b1−a∑xi∈Bigi)2+nrj(d)(∑xi∈Argi+b1−a∑xi∈Brgi)2)
其中,
∙
\bullet
∙
n
n
n是总样本数。
∙
\bullet
∙
A
l
A_l
Al和
A
r
A_r
Ar分别表示在分裂点
d
d
d左右的样本集合。
∙
\bullet
∙
B
l
B_l
Bl和
B
r
B_r
Br分别表示从梯度较小的样本中随机采样得到的样本,分别为左右的样本集合。
∙
\bullet
∙
g
i
g_i
gi是样本
i
i
i的梯度。
∙
\bullet
∙
n
l
j
(
d
)
n_l^j(d)
nlj(d)和
n
r
j
(
d
)
n_r^j(d)
nrj(d)分别表示在分裂点
d
d
d左右的样本数。
∙
\bullet
∙
a
a
a和
b
b
b是大梯度和小梯度样本的采样比例。
∙
\bullet
∙
1
−
a
b
\frac {1- a}b
b1−a是对小梯度样本权重的调整因子。
这个公式的作用是将大梯度和小梯度样本分别处理后,结合权重调整,确保即使经过采样,增益计算仍然保持精度。
2、近似误差
GOSS 中的近似误差表示为:
E
(
d
)
≤
C
a
,
b
2
ln
1
/
δ
⋅
max
{
1
n
l
j
(
d
)
,
1
n
r
j
(
d
)
}
+
2
D
C
a
,
b
ln
1
/
δ
n
\mathcal{E}(d)\leq C_{a,b}^2\ln1/\delta\cdot\max\left\{\frac{1}{n_l^j(d)},\frac{1}{n_r^j(d)}\right\}+2DC_{a,b}\sqrt{\frac{\ln1/\delta}{n}}
E(d)≤Ca,b2ln1/δ⋅max{nlj(d)1,nrj(d)1}+2DCa,bnln1/δ
该公式用于衡量在给定分裂点
d
d
d时,增益近似误差的上界。
其中
∙
\bullet
∙
n
n
n是样本总数。
∙
\bullet
∙
D
D
D表示树的深度。
∙
\bullet
∙
E
(
d
)
\mathcal{E}(d)
E(d)是在分裂点
d
d
d的增益近似误差。
∙
\bullet
∙
C
a
,
b
C_{a, b}
Ca,b是依赖于采样比例
a
a
a和
b
b
b的常数。
∙
\bullet
∙
δ
\delta
δ是一个置信参数,表示置信水平的倒数。
∙
\bullet
∙
n
l
j
(
d
)
n_l^j( d)
nlj(d)和
n
r
j
(
d
)
n_r^j(d)
nrj(d)分别是分裂点
d
d
d左右的样本数。
这个公式表达了误差上界与分裂点两侧样本数量
n
l
j
(
d
)
n_l^j(d)
nlj(d)和
n
r
j
(
d
)
n_r^j(d)
nrj(d)之间的关系。随着分裂点两侧样本数的增加,误差的上界会变小,确保增益估计的准确性。
(三)EFB
在处理高维特征数据的时候,容易出现数据稀疏问题,存在有些特征之间是互斥的,这样造成了没有必要的计算开销。稀疏性提供了一种能够在不明显降低模型性能的情况下减少特征数量的可能,通过观察这种互斥关系,可以将这些特征捆绑起来,将多个互斥特征合并为一个新的特征,减少特征的数量,从而有效地在不损失信息的前提下显著降低模型的计算复杂度,减少存储开销。
主要解决的两个问题是:
1 如何确定哪些特征应该捆绑在一起;
2 如何把互斥特征对进行捆绑。
对于问题1,特征捆绑算法的流程如下图所示:
特征捆绑算法的核心流程为:首先,构建一个特征冲突图 G,其中每个特征节点的边表示该特征与其他特征在某些数据点上的冲突。其次,按照特征在图中的冲突程度对特征进行排序。最后,将排序后的特征列表进行遍历。如果某个特征可以与当前的捆绑包产生较少的冲突,则将其添加到已有的捆绑包中;否则,创建一个新的捆绑。此外,为了提高效率,提出了一个更简单的排序策略,不需要构建完整的冲突图。改为按特征的非零值数量进行排序,因为更多非零值意味着更高的冲突概率。
对于问题二,需要一种把互斥特征对进行捆绑的方法,算法流程如下所示:
通过合并多个互斥的特征,将它们的分箱索引组合在一起,减少存储和计算的复杂性。这对于互斥特征(如互斥的类别特征)特别有用,因为它们不会在同一条数据中同时非零,因此可以被合并到一个更紧凑的分箱表示中,可以通过向特征的原始值添加偏移量来完成。例如,特征A的取值在[0,10],特征 B 取值 [0, 20],让特征B的每个取值都加一个偏置量10,使得B的值范围变为 [10, 30],这样就把特征1和特征2分开,A 和 B 可以合并为一个新的特征,其值范围为 [0, 30],避免值的冲突,合并后能够有效降低训练复杂度。
三、算法优缺点
(一)优点
1、LightGBM具有高效的训练和预测速度,采用的Histogram算法能够实现并行计算的线性加速。
2、由于使用了Histogram等算法,LightGBM能够减少内存消耗,适用于内存有限的环境。
3、LightGBM通过优化算法和特征选择等方法提高了模型的准确性。
(二)缺点
1、容易过拟合
2、LightGBM 的特征并行算法在数据量很大时,仍然存在计算上的局限。
四、LightGBM分类任务实现对比
(一)数据加载和样本分区
1、Python代码
#导入需要的库
from lightgbm import LGBMClassifier
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
# 导入sklearn的iris数据集,作为模型的训练和验证数据
data = datasets.load_iris()
# 数据划分,按照8:2分切割数据集为训练集和验证集
X_train, X_test, y_train, y_test = train_test_split(data.data, data.target, test_size=0.2, random_state=42)
2、Sentosa_DSML社区版
首先,利用文本读入算子读取数据,对数据进行读入。
其次,连接样本分区算子划分数据的训练集和测试集,选择训练集测试机划分比例为8:2
利用类型算子设置Feature列和Label列。
(二)模型训练
1、Python代码
# 模型定义
model = LGBMClassifier(
boosting_type='dart', # 基学习器 gbdt:传统的梯度提升决策树; dart:Dropouts多重加性回归树
n_estimators=20, # 迭代次数
learning_rate=0.1, # 学习率
max_depth=5, # 树的最大深度
min_child_weight=1, # 决定最小叶子节点样本权重和
min_split_gain=0.1, # 在树的叶节点上进行进一步分区所需的最小损失减少
subsample=0.8, # 每个决策树所用的子样本占总样本的比例(作用于样本)
colsample_bytree=0.8, # 建立树时对特征随机采样的比例(作用于特征)典型值:0.5-1
random_state=27, # 指定随机种子,为了复现结果
importance_type='gain', # 特征重要性的计算方式,split:分隔的总数; gain:总信息增益
)
# 模型训练
model.fit(X_train, y_train)
# 预测
predictions = model.predict(X_test)
2、Sentosa_DSML社区版
连接LightGBM分类算子
参数配置如下图所示:
右击算子,点击运行,得到LightGBM分类模型,如下所示:
(三)模型评估和模型可视化
1、Python代码
# 评估模型
accuracy = accuracy_score(y_test, predictions)
precision = precision_score(y_test, predictions, average='weighted')
recall = recall_score(y_test, predictions, average='weighted')
f1 = f1_score(y_test, predictions, average='weighted')
# 计算混淆矩阵
cm = confusion_matrix(y_test, predictions)
# 计算特征重要性并进行排序
importances = model.feature_importances_
indices = np.argsort(importances)[::-1]
# 绘制特征重要性柱状图
plt.figure(figsize=(10, 6))
plt.title("Feature Importances")
plt.bar(range(X_train.shape[1]), importances[indices], align="center")
plt.xticks(range(X_train.shape[1]), [data.feature_names[i] for i in indices], rotation=45)
plt.tight_layout()
plt.show()
2、Sentosa_DSML社区版
模型后可接评估算子,对模型的分类结果进行评估。模型后也可接任意个数据处理算子,再接图表分析算子或数据写出算子,形成算子流执行。评估算子流如下图所示:
评估算子执行完成后,得到训练集和测试集评估结果如下:
连接混淆矩阵进行模型评估
混淆矩阵算子执行完成后,得到训练集和测试集混淆矩阵结果如下:
右键预览可查看模型的运行结果,如下图所示:
也可以查看模型信息,得到模型特征重要性图等
五、LightGBM回归任务实现对比
(一)数据加载和样本分区
1、Python代码
#导包
import numpy as np
import pandas as pd
from lightgbm import LGBMRegressor
# 读取数据集
df = pd.read_csv("D:/sentosa_ML/Sentosa_DSML/mlServer/TestData/winequality.csv")
df.head()
# 将数据集划分为特征和标签
X = df.drop("quality", axis=1) # 特征
Y = df["quality"] # 标签
# 划分训练集和测试集
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=42)
2、Sentosa_DSML社区版
利用数据读入的算子读取数据
其次,连接样本分区算子对数据集划分训练集和测试集。
连接类型算子设置数据的标签列和特征列
(二)模型训练
1、Python代码
# 使用LightGBM回归器
lgbm_regressor = LGBMRegressor(boosting_type='gbdt',
n_estimators=400,
learning_rate=0.1,
max_depth=10,
num_leaves=31,
min_data_in_leaf=50,
max_bin=255,
min_child_weight=0.001, # 最小叶子节点Hessian和
bagging_fraction=1, # Bagging比例
bagging_freq=0, # Bagging频率
bagging_seed=3, # Bagging种子
lambda_l1=0, # 增加L1正则化
lambda_l2=0 # 增加L2正则化
)
# 训练LightGBM回归模型
lgbm_regressor.fit(X_train, Y_train)
# 预测测试集上的标签
y_pred = lgbm_regressor.predict(X_test)
2、Sentosa_DSML社区版。
连接LightGBM回归算子,设置模型参数,点击应用,并右键执行。
可以训练完成后可以得到LightGBM回归模型,右键即可查看模型信息和预览模型结果。
(三)模型评估和模型可视化
1、Python代码
# 计算评估指标
r2 = r2_score(Y_test, y_pred)
mae = mean_absolute_error(Y_test, y_pred)
mse = mean_squared_error(Y_test, y_pred)
rmse = np.sqrt(mse)
mape = np.mean(np.abs((Y_test - y_pred) / Y_test)) * 100
smape = 100 / len(Y_test) * np.sum(2 * np.abs(Y_test - y_pred) / (np.abs(Y_test) + np.abs(y_pred)))
# 可视化特征重要性
importances = lgbm_regressor.feature_importances_
indices = np.argsort(importances)[::-1]
plt.figure(figsize=(10, 6))
plt.title("Feature Importances")
plt.bar(range(X.shape[1]), importances[indices], align="center")
plt.xticks(range(X.shape[1]), X.columns[indices], rotation=45)
plt.tight_layout()
plt.show()
2、Sentosa_DSML社区版
连接评估算子对模型进行评估
得到训练集和测试集的评估结果,如下所示:
右键点击模型信息,可以看到模型特征重要性图,残差直方图等结果,如下所示:
六、总结
相比传统代码方式,利用Sentosa_DSML社区版完成机器学习算法的流程更加高效和自动化,传统方式需要手动编写大量代码来处理数据清洗、特征工程、模型训练与评估,而在Sentosa_DSML社区版中,这些步骤可以通过可视化界面、预构建模块和自动化流程来简化,有效的降低了技术门槛,非专业开发者也能通过拖拽和配置的方式开发应用,减少了对专业开发人员的依赖。
Sentosa_DSML社区版提供了易于配置的算子流,减少了编写和调试代码的时间,并提升了模型开发和部署的效率,由于应用的结构更清晰,维护和更新变得更加容易,且平台通常会提供版本控制和更新功能,使得应用的持续改进更为便捷。
为了非商业用途的科研学者、研究人员及开发者提供学习、交流及实践机器学习技术,推出了一款轻量化且完全免费的Sentosa_DSML社区版。以轻量化一键安装、平台免费使用、视频教学和社区论坛服务为主要特点,能够与其他数据科学家和机器学习爱好者交流心得,分享经验和解决问题。文章最后附上官网链接,感兴趣工具的可以直接下载使用
https://sentosa.znv.com/