news 2026/4/16 12:45:19

【机器学习】案例3.1——GBDT+LR模型融合

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【机器学习】案例3.1——GBDT+LR模型融合

一、项目背景及解决问题的方案

1. 项目背景

在机器学习分类任务中,单一模型难以同时兼顾非线性特征挖掘能力模型可解释性/泛化稳定性

  • 梯度提升决策树(GBDT):擅长挖掘特征间的非线性关系、处理高维/异构特征,对缺失值不敏感,但易过拟合、可解释性差,单独使用时泛化能力受超参数影响大;
  • 逻辑回归(LR):模型简单、可解释性强(能输出概率和特征权重)、训练/预测速度快,是工业界(如CTR预估、风控)的经典基线,但对非线性特征建模能力弱,依赖人工特征工程。

为结合两者优势,工业界提出「GBDT+LR」组合方案:用GBDT做「自动特征工程器」,将原始特征映射为离散的非线性特征,再输入LR分类。本项目以鸢尾花数据集为示例,将多分类任务改造为二分类,实现该组合模型并验证其性能。

2. 解决方案

核心思路:利用GBDT的叶子节点索引做特征编码,将非线性特征转化为LR可处理的离散特征,最终用LR完成分类。具体步骤:

  1. 数据预处理:加载鸢尾花数据集,将「是否为第三类鸢尾花」作为二分类标签,划分训练/测试集(6:4);
  2. GBDT训练:训练GBDT模型,挖掘原始特征的非线性规律;
  3. 特征编码:通过GBDT的apply方法提取样本的叶子节点索引,对索引做One-Hot编码生成新特征;
  4. LR训练:用编码后的新特征训练LR,得到GBDT+LR组合模型;
  5. 性能评估:分别计算单独GBDT和GBDT+LR的AUC,对比两者效果。

二、添加详细注释的完整代码(含中文说明、可视化)

# 导入必要的库importnumpyasnpimportmatplotlib.pyplotasplt# 补充可视化库# 导入GBDT分类器fromsklearn.ensembleimportGradientBoostingClassifier# 导入逻辑回归分类器fromsklearn.linear_modelimportLogisticRegression# 导入AUC评估指标fromsklearn.metricsimportroc_auc_score# 导入One-Hot编码器fromsklearn.preprocessingimportOneHotEncoder# 导入鸢尾花数据集fromsklearn.datasetsimportload_iris# 导入数据集划分工具fromsklearn.model_selectionimporttrain_test_split# 设置中文显示(解决plt中文乱码问题)plt.rcParams['font.sans-serif']=['SimHei']# 黑体plt.rcParams['axes.unicode_minus']=False# 解决负号显示问题classGradientBoostingWithLR(object):"""GBDT+LR组合模型类:实现GBDT特征编码 + LR分类的端到端流程"""def__init__(self):"""初始化模型相关变量"""self.gbdt_model=None# 存储训练好的GBDT模型self.lr_model=None# 存储训练好的LR模型self.gbdt_encoder=None# 存储One-Hot编码器self.X_train_leafs=None# 训练集样本的GBDT叶子节点索引self.X_test_leafs=None# 测试集样本的GBDT叶子节点索引self.X_trans=None# 训练集叶子节点索引的One-Hot编码结果defgbdt_train(self,X_train,y_train):""" 训练GBDT模型 参数: X_train: 训练集特征矩阵(np.array) y_train: 训练集标签(np.array) 返回: 训练好的GBDT模型 """# 初始化GBDT模型gbdt_model=GradientBoostingClassifier(n_estimators=10,# 决策树数量:10棵max_depth=6,# 单棵树最大深度:6verbose=0,# 训练过程不打印日志max_features=0.5# 每棵树使用50%的特征)# 用训练集训练GBDT模型gbdt_model.fit(X_train,y_train)returngbdt_modeldeflr_train(self,X_train,y_train):""" 训练逻辑回归模型 参数: X_train: 训练集特征矩阵(One-Hot编码后的) y_train: 训练集标签(np.array) 返回: 训练好的LR模型 """# 初始化LR模型(使用默认参数)lr_model=LogisticRegression()# 用编码后的特征训练LR模型lr_model.fit(X_train,y_train)returnlr_modeldefgbdt_lr_train(self,X_train,y_train):""" 端到端训练GBDT+LR组合模型 参数: X_train: 原始训练集特征矩阵 y_train: 训练集标签 返回: 训练好的LR模型(组合模型核心) """# 第一步:训练GBDT模型self.gbdt_model=self.gbdt_train(X_train,y_train)# 第二步:用GBDT提取训练集样本的叶子节点索引# apply方法返回形状为[样本数, 树数量, 1]的数组,[:, :, 0]降维为[样本数, 树数量]self.X_train_leafs=self.gbdt_model.apply(X_train)[:,:,0]# 第三步:初始化One-Hot编码器,对叶子节点索引做编码self.gbdt_encoder=OneHotEncoder(sparse=False)# 拟合编码器并转换训练集叶子节点索引self.X_trans=self.gbdt_encoder.fit_transform(self.X_train_leafs)# 第四步:用编码后的特征训练LR模型self.lr_model=self.lr_train(self.X_trans,y_train)returnself.lr_modeldefgbdt_lr_pred(self,model,X_test,y_test):""" 用GBDT+LR组合模型预测并评估AUC 参数: model: 训练好的LR模型 X_test: 原始测试集特征矩阵 y_test: 测试集标签 返回: 组合模型的AUC分数 """# 第一步:提取测试集样本的GBDT叶子节点索引self.X_test_leafs=self.gbdt_model.apply(X_test)[:,:,0]# 第二步:合并训练集和测试集的叶子节点索引(保证One-Hot编码维度一致)(train_rows,cols)=self.X_train_leafs.shape# 获取训练集样本数和特征数X_all_leafs=np.concatenate((self.X_train_leafs,self.X_test_leafs),axis=0)# 对合并后的索引做One-Hot编码X_trans_all=self.gbdt_encoder.fit_transform(X_all_leafs)# 第三步:提取测试集的编码特征,预测正类概率y_pred=model.predict_proba(X_trans_all[train_rows:])[:,1]# 计算AUC分数auc_score=roc_auc_score(y_test,y_pred)# 打印中文说明的AUC结果print(f'GBDT+LR组合模型 AUC分数:{auc_score:.5f}')returnauc_scoredefmodel_assessment(self,model,X_test,y_test,model_name="GBDT"):""" 通用模型评估函数(计算AUC) 参数: model: 待评估的模型(GBDT/LR等) X_test: 测试集特征矩阵 y_test: 测试集标签 model_name: 模型名称(用于打印日志) 返回: 模型的AUC分数 """# 预测测试集正类概率y_pred=model.predict_proba(X_test)[:,1]# 计算AUC分数auc_score=roc_auc_score(y_test,y_pred)# 打印中文说明的AUC结果print(f'{model_name}模型 AUC分数:{auc_score:.5f}')returnauc_scoredefload_data():""" 数据加载与预处理函数: 1. 加载鸢尾花数据集 2. 将多分类任务转为二分类(是否为第三类鸢尾花Virginica) 3. 划分训练集(60%)和测试集(40%) 返回: X_train: 训练集特征 X_test: 测试集特征 y_train: 训练集标签 y_test: 测试集标签 """# 加载鸢尾花数据集iris_data=load_iris()# 提取特征矩阵X=iris_data['data']# 构造二分类标签:y=1表示是第三类鸢尾花,y=0表示不是y=iris_data['target']==2# 划分训练集和测试集,测试集占40%,随机种子固定为0(保证结果可复现)X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.4,random_state=0)returnX_train,X_test,y_train,y_testif__name__=='__main__':# 1. 加载并预处理数据X_train,X_test,y_train,y_test=load_data()# 2. 初始化GBDT+LR组合模型实例gblr=GradientBoostingWithLR()# 3. 训练组合模型gbdt_lr_model=gblr.gbdt_lr_train(X_train,y_train)# 4. 评估单独GBDT模型的性能gbdt_auc=gblr.model_assessment(gblr.gbdt_model,X_test,y_test,model_name="单独GBDT")# 5. 评估GBDT+LR组合模型的性能gbdt_lr_auc=gblr.gbdt_lr_pred(gbdt_lr_model,X_test,y_test)# 6. 补充可视化:绘制AUC对比柱状图models=['单独GBDT','GBDT+LR组合模型']auc_scores=[gbdt_auc,gbdt_lr_auc]plt.bar(models,auc_scores,color=['#1f77b4','#ff7f0e'])plt.title('模型AUC性能对比')plt.ylabel('AUC分数')plt.ylim(0.9,1.0)# 限定y轴范围,突出差异# 在柱状图上标注具体数值fori,scoreinenumerate(auc_scores):plt.text(i,score+0.005,f'{score:.5f}',ha='center')plt.show()

三、去除所有注释的简洁版代码

以下是完全去除所有注释、仅保留核心代码的简洁版,适配新版sklearn且可直接运行:

importnumpyasnpimportmatplotlib.pyplotaspltfromsklearn.ensembleimportGradientBoostingClassifierfromsklearn.linear_modelimportLogisticRegressionfromsklearn.metricsimportroc_auc_scorefromsklearn.preprocessingimportOneHotEncoderfromsklearn.datasetsimportload_irisfromsklearn.model_selectionimporttrain_test_split plt.rcParams['font.sans-serif']=['SimHei']plt.rcParams['axes.unicode_minus']=FalseclassGradientBoostingWithLR(object):def__init__(self):self.gbdt_model=Noneself.lr_model=Noneself.gbdt_encoder=Noneself.X_train_leafs=Noneself.X_test_leafs=Noneself.X_trans=Nonedefgbdt_train(self,X_train,y_train):gbdt_model=GradientBoostingClassifier(n_estimators=10,max_depth=6,verbose=0,max_features=0.5)gbdt_model.fit(X_train,y_train)returngbdt_modeldeflr_train(self,X_train,y_train):lr_model=LogisticRegression()lr_model.fit(X_train,y_train)returnlr_modeldefgbdt_lr_train(self,X_train,y_train):self.gbdt_model=self.gbdt_train(X_train,y_train)self.X_train_leafs=self.gbdt_model.apply(X_train)[:,:,0]self.gbdt_encoder=OneHotEncoder(sparse=False)self.X_trans=self.gbdt_encoder.fit_transform(self.X_train_leafs)self.lr_model=self.lr_train(self.X_trans,y_train)returnself.lr_modeldefgbdt_lr_pred(self,model,X_test,y_test):self.X_test_leafs=self.gbdt_model.apply(X_test)[:,:,0](train_rows,cols)=self.X_train_leafs.shape X_all_leafs=np.concatenate((self.X_train_leafs,self.X_test_leafs),axis=0)X_trans_all=self.gbdt_encoder.fit_transform(X_all_leafs)y_pred=model.predict_proba(X_trans_all[train_rows:])[:,1]auc_score=roc_auc_score(y_test,y_pred)print(f'GBDT+LR组合模型 AUC分数:{auc_score:.5f}')returnauc_scoredefmodel_assessment(self,model,X_test,y_test,model_name="GBDT"):y_pred=model.predict_proba(X_test)[:,1]auc_score=roc_auc_score(y_test,y_pred)print(f'{model_name}模型 AUC分数:{auc_score:.5f}')returnauc_scoredefload_data():iris_data=load_iris()X=iris_data['data']y=iris_data['target']==2X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.4,random_state=0)returnX_train,X_test,y_train,y_testif__name__=='__main__':X_train,X_test,y_train,y_test=load_data()gblr=GradientBoostingWithLR()gbdt_lr_model=gblr.gbdt_lr_train(X_train,y_train)gbdt_auc=gblr.model_assessment(gblr.gbdt_model,X_test,y_test,model_name="单独GBDT")gbdt_lr_auc=gblr.gbdt_lr_pred(gbdt_lr_model,X_test,y_test)models=['单独GBDT','GBDT+LR组合模型']auc_scores=[gbdt_auc,gbdt_lr_auc]plt.bar(models,auc_scores,color=['#1f77b4','#ff7f0e'])plt.title('模型AUC性能对比')plt.ylabel('AUC分数')plt.ylim(0.9,1.0)fori,scoreinenumerate(auc_scores):plt.text(i,score+0.005,f'{score:.5f}',ha='center')plt.show()

运行结果

''' 单独GBDT模型 AUC分数:0.97192 GBDT+LR组合模型 AUC分数:0.98962 进程已结束,退出代码为 0 '''
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 2:57:12

OpenCore Legacy Patcher专业指南:为老旧Mac设备制作启动安装盘

OpenCore Legacy Patcher专业指南:为老旧Mac设备制作启动安装盘 【免费下载链接】OpenCore-Legacy-Patcher 体验与之前一样的macOS 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 项目概述与核心价值 OpenCore Legacy Patcher…

作者头像 李华
网站建设 2026/4/16 10:39:55

音视频学习(七十三):视频压缩:帧间与时间冗余消除

视频压缩是数字视频技术的核心组成部分,其主要目标是在保持可接受的视觉质量的前提下,大幅减少视频数据量。未压缩的视频数据量巨大,难以存储和传输。视频压缩算法通过识别并消除视频数据中的冗余信息来实现这一目标。这些冗余主要分为三类&a…

作者头像 李华
网站建设 2026/4/15 19:56:10

音视频学习(七十四):视频压缩:变换编码

变换编码(Transform Coding)是现代视频压缩技术中消除空间冗余(帧内冗余)和残差冗余的核心环节。无论是在独立编码的I帧中,还是在帧间预测后产生的残差块中,变换编码都是将空间域(像素值&#x…

作者头像 李华
网站建设 2026/4/16 10:46:10

把timerfd + epoll讲透,最硬核的Linux系统编程实战

传统的定时器实现方案各有优劣:基于最小堆的定时器能够快速找到最早到期任务(O(1)),但插入和删除操作需要 O(logN) 的堆调整;红黑树的插入、查找、删除都是 O(logN),对于大量同时到期的任务处理更加自然;而时间轮(Hashed Wheel Timer)虽然能做到接近 O(1) 的插入和取消…

作者头像 李华
网站建设 2026/4/16 10:45:03

智能预警系统如何让风险在发生前被化解

想象一下:在地铁隧道的墙壁开始渗水前三小时,系统已经预判到排水泵的异常工作模式并向维修团队发出工单;在变电站的断路器跳闸导致全城大停电前十五分钟,值班人员已收到设备过热预警并启动负荷转移预案;在边坡滑坡掩埋…

作者头像 李华
网站建设 2026/4/16 10:38:55

AKA协议认证与密钥协商的核心原理

认证的密钥协商协议(Authenticated Key Agreement,AKA)是现代网络安全通信的基石。它将身份认证(证明“你是谁”)与密钥分发(安全协商“我们用什么密钥通信”)融为一体,为建立安全信…

作者头像 李华