当前位置: 首页 > news >正文

LightGBM原理介绍

LightGBM(轻量级梯度提升机)是微软开源的另一个王牌算法。它的底层原理和 XGBoost 完全一样,都是让多棵树接力去学习不正确的部分(残差)。

但微软当年在开发它时,心里憋着一个大招。他们觉得 XGBoost 性能好是好,但在处理海量大数据时,太慢了、太吃内存了。于是,微软对树模型的建树过程进行了大刀阔斧的“偷懒式”改造。

LightGBM 之所以能做到“又快又准”,全靠它的三大核心绝招(而且这三招在后台是同时发力、打组合拳的):

第一招:直方图算法(Histogram)—— 寻找切分点时的高明偷懒

树模型的核心工作是寻找在哪一个数值进行切分最合适(比如在时序特征中:昨天的负荷是否 $> 1500$ 兆瓦?)。

  • XGBoost 的笨办法(预排序):把全城过去几年的所有负荷数据,严格按照从小到大排好序。然后在这个队伍的每一个空隙都切一刀试试,找出最完美的那一刀。数据量只要一上百万,电脑内存直接爆满,跑起来像蜗牛爬。

  • LightGBM 的聪明办法(直方图):它采用了“把数字装进桶里”的思想。比如,把用电量划分成 10 个大桶/垃圾箱(Bins):$0-100$度是 1 号桶,$101-200$度是 2 号桶……

    不管你有几百万条还是几千万条数据,它们都会被归类到这 10 个桶里。

通俗点说:LightGBM 在找切分点时,不再去遍历几百万条数据,而是只遍历这 10 个桶!这一偷懒,让它的运行速度直接飙升了近 10 倍,内存暴省 80%,而且神奇的是,因为数据的大体分布没变,预测精度几乎没有任何下降。

第二招:GOSS 算法 —— 专门淘汰“成绩好的数据”

既然要通过学习残差来纠正错误,那每一棵新树诞生前,都要把所有历史数据算一遍残差。

LightGBM 掐指一算:不对啊,那些残差已经非常小的数据(说明模型已经预测得很准了),为什么每棵树还要重复去算它们?这不是浪费劳动力吗?

于是它发明了GOSS(基于梯度的单边采样)

  • 它把历史数据按照“不正确程度(残差大小)”排个序。

  • 残差大的数据(差生):说明模型还没学好,全量保留,让下一棵树重点照顾。

  • 残差小的数据(优等生):说明模型已经懂了,它就随机抽一小部分留在队伍里充充场面,剩下的直接“放假”。

通过这种方式,LightGBM 大大减少了每一轮训练要算的数据量,速度进一步起飞。

第三招:Leaf-wise 生长策略 —— 精准打击,绝不齐头并进

这是它在结构上和 XGBoost 最明显的区别。

  • XGBoost(按层生长 Level-wise):像教官训练士兵,所有人必须排成一排,整齐划一地向下分裂。不管某些叶子节点有没有潜力,大家都必须一起长一层。

  • LightGBM(按叶子生长 Leaf-wise):它是绝对的实用主义。它每次分裂时,会在当前所有的叶子里面找:“到底谁的残差最大、最不准?”然后只盯着这一个节点疯狂向下切分,其他长得好的节点直接不管。

通俗点说:XGBoost 追求“满堂红”,大家都得整齐;LightGBM 追求“定点清除”,谁错得厉害我连夜加班给它纠正。这种按叶子生长的策略,能用更少的树、更深的结构,更快地把残差降到最低,因此精度极高

⚠️ 注意:盯着一个地方疯狂往下长,容易导致树长得太深,从而“死记硬背”历史(过拟合)。所以实战中我们必须要限高(限制最大深度max_depth)。

💥 LightGBM 的“三连招”组合拳现场:

  • 第一步:数据瘦身(直方图算法 Histogram 启动)模型刚拿到海量的时序特征数据,直接大刀阔斧地把那些连续的负荷数字、温度数字全部塞进指定的“桶”里。这一步,直接把数据量从几百万条的恐怖级别,精简成了区区几百个桶的计算量,完成了内存暴省

  • 第二步:人员精简(GOSS 算法 启动)在每一轮准备建新树纠正残差时,模型看了一眼上一轮的结果。它发现 80% 的历史日子预测得很准(残差接近 0),于是给这 80% 的优等生“放假”,只留下那 20% 预测不准的“差生”重点补课。这一步,完成了训练速度的二次起飞

  • 第三步:精准狙击(Leaf-wise 策略 启动)现在,只剩下一小部分“差生”数据和精简完的“桶”。新树开始生长。它不搞 XGBoost 那种齐头并进的排场,而是盯着最不准的那一个叶子节点,疯狂地、精准地向下连切几刀,用最快的速度把残差清零。这一步,完成了预测精度的高效收敛

代码示例

import warnings import lightgbm as lgb import matplotlib.pyplot as plt import numpy as np import pandas as pd # 忽略不必要的警告信息,让控制台输出更干净 warnings.filterwarnings("ignore") # ========================================== # 1. 模拟生成一份真实的电力负荷数据 (以小时为单位) # ========================================== np.random.seed(42) # 生成 300 个小时的时间序列(大约12.5天的数据量) time_index = pd.date_range(start="2026-05-01", periods=300, freq="H") # 模拟基础负荷,并叠加每天的周期性用电规律(中午高峰,凌晨低谷) base_load = 200 simulated_load = [] for i, t in enumerate(time_index): # 用正弦函数模拟每日用电规律 daily_pattern = 50 * np.sin(2 * np.pi * t.hour / 24) # 加上随机噪声 noise = np.random.normal(0, 8) simulated_load.append(base_load + daily_pattern + noise) # 组装成 Pandas DataFrame,时间作为索引 df = pd.DataFrame(data={"load": simulated_load}, index=time_index) # ========================================== # 2. 特征工程:重塑数据,准备好“答卷特征” # ========================================== def create_lightgbm_features(data): """构建 LightGBM 所需的时间、滞后和滚动统计特征""" df_feat = data.copy() # --- 提取时间戳特征 --- df_feat["hour"] = df_feat.index.hour # 提取小时 (0-23),用于捕捉日周期 df_feat["dayofweek"] = df_feat.index.dayofweek # 提取星期几 (0-6),用于捕捉周工作日规律 # --- 构建滞后特征 (Lag Features) --- # 假设我们只提前 1 小时预测下一小时,所以最小可以用 lag_1 df_feat["lag_1"] = df_feat["load"].shift(1) # 1小时前的负荷(代表眼前的惯性) df_feat["lag_2"] = df_feat["load"].shift(2) # 2小时前的负荷 df_feat["lag_24"] = df_feat["load"].shift(24) # 昨天同一时刻的负荷(强力捕捉日周期规律) # --- 构建滚动统计特征 (Rolling Features) --- # 基于过去已经发生的数据(lag_1),滚动计算过去 12 小时的平均用电量 df_feat["rolling_mean_12h"] = df_feat["lag_1"].rolling(12).mean() return df_feat # 执行特征工程,生成表格特征 df_with_features = create_lightgbm_features(df) # 因为 shift(24) 会导致前 24 行没有历史数据而产生空值 (NaN),必须无情删掉 df_with_features = df_with_features.dropna() # ========================================== # 3. 严格按时间先后划分训练集和测试集 # ========================================== # 定义丢给树模型去走迷宫的特征列 FEATURES = ["hour", "dayofweek", "lag_1", "lag_2", "lag_24", "rolling_mean_12h"] # 定义模型要预测的未来标准答案 TARGET = "load" # 划分数据集:前 250 个小时用于训练,最后 26 个小时用于测试 train_df = df_with_features.iloc[:250] test_df = df_with_features.iloc[250:] X_train, y_train = train_df[FEATURES], train_df[TARGET] X_test, y_test = test_df[FEATURES], test_df[TARGET] # ========================================== # 4. 配置 LightGBM 的三大绝招参数 # ========================================== # 将数据打包成 LightGBM 专用的 Dataset 格式,提升底层运行效率 lgb_train = lgb.Dataset(X_train, y_train) params = { "objective": "regression", # 告诉模型这是一个回归任务(预测连续的用电量) "metric": "rmse", # 使用均方根误差来评估模型纠正残差的效果 "learning_rate": 0.05, # 学习率,控制每棵新树修正残差的步伐大小 # --- 绝招一:GOSS 算法 --- "boosting_type": "goss", # 开启 GOSS,让模型给优等生放假,重点扣住残差大的“差生”数据 # --- 绝招二:直方图算法 --- "max_bin": 255, # 把连续数字切分成最多 255 个桶,极大节省内存和寻找切分点的时间 # --- 绝招三:Leaf-wise 生长策略 --- "num_leaves": 31, # 限制一棵树最多拥有 31 个叶子节点,精准切分残差最大的分支 "max_depth": 5, # 配合 Leaf-wise 进行“限高”,防止树长得太深导致死记硬背历史(过拟合) "verbose": -1, # 减少不必要的日志打印,保持控制台清爽 } # ========================================== # 5. 串行训练:让多棵树接力学习残差 # ========================================== # num_boost_round=150: 代表一共有 150 棵树排队串行接力,后一棵树永远在纠正前一棵树的残差 model = lgb.train(params, lgb_train, num_boost_round=150) # ========================================== # 6. 预测未来并可视化比对 # ========================================== # 带着未知的测试集特征(X_test)去走训练好的树群迷宫,每棵树吐出的数字相加得到最终预测值 predictions = model.predict(X_test) # 转换成带时间索引的 Series,方便画图对齐 predictions_series = pd.Series(predictions, index=test_df.index) # 绘图比对结果 plt.figure(figsize=(12, 5)) plt.plot(train_df.index[-48:], train_df["load"][-48:], label="History (Last 48h)", color="blue") plt.plot(test_df.index, y_test, label="Actual Future (Truth)", color="green", linewidth=2) plt.plot( test_df.index, predictions_series, label="LightGBM Forecast", color="red", linestyle="--", linewidth=2, ) plt.title("Electricity Load Forecasting using LightGBM (GOSS & Leaf-Wise)") plt.xlabel("Time") plt.ylabel("Load (MW)") plt.legend() plt.grid(True) plt.show()
http://www.jsqmd.com/news/937692/

相关文章:

  • 一图理清对称加密 AEAD 为什么最怕 nonce 用错
  • PingFangSC字体包:跨平台字体一致性解决方案技术指南
  • 基于Arduino与光敏电阻的智能窗帘自动控制系统设计与实现
  • 3.3 Linux权限操作
  • 从“拼图式采购“到“全域闭环“:2026年GEO监测工具终极选型指南
  • 揭秘消息防撤回:如何永久保存微信QQ的消失对话
  • 2026年济南钻戒回收实用科普:素军奢品汇钻石回收闲置处置参考文稿 - GrowthUME
  • Sobel算子实战:用OpenCV 4.x给老旧照片‘描边’,实现一键卡通化/素描风效果
  • 去欧洲机票别再自己刷OTA了!武汉圣擎航空——您身边最靠谱的法国及全欧航线特价公务舱/头等舱专家(附全航线解析+售后保障) - 土星买买买
  • 告别阈值烦恼:用Halcon的MLP分类器搞定复杂场景下的颜色识别(附完整代码)
  • 用Python+灰色关联度分析,手把手教你量化低碳建筑全生命周期的碳排放(附代码)
  • Flutter跨小程序开发:如何用一套Dart代码征服微信小程序生态
  • 手把手教你学Simulink——双向 DC‑DC 变换器在恒压(CV)与恒流(CC)模式下的切换仿真
  • 肺部靶向 AAV 怎么选?如何解决靶向不精准、转导效率低的递送难题?
  • 类型体操实战:Promise.all 类型实现
  • 2026年赤峰劳动工伤律师推荐:5位实战经验丰富值得信赖的维权专家 - 本地品牌推荐
  • 2026年济南黄金回收实用科普:素军奢品汇贵金属回收闲置处置参考文稿 - GrowthUME
  • 【AI笔记】环境配置
  • 如何通过OmenSuperHub优化惠普OMEN游戏本的性能和散热
  • 2026 HENGSHI BOX 全域智控舱技术白皮书:衡石科技软硬一体的私有化 Agentic BI 架构
  • 7次碰壁、4个版本:我在一个浏览器插件里看到Agent该有的样子
  • 铜箔胶带电路制作:LED发光蝙蝠的串联电路实践
  • 告别零碎作业:留学生如何把大学四年代码重构为可交付全栈「蒸汽求职分享」
  • 【Agent 学习日记】我们来说说 Agent 记忆压缩通常有哪些方法?
  • 2026 短视频去水印软件推荐,抖音快手视频号通用 - 时时资讯
  • 10.使用requests库爬取网易云音乐
  • 国内飞往澳大利亚全航线汇总|特价经济 / 特惠公务 / 折扣商务头等舱申请|靠谱国际机票代理人优选:武汉圣擎航空(15120088536 微信同号) - 土星买买买
  • 从零打造2000W正弦波逆变器:PIC单片机控制与全桥功率设计实战
  • Buck 滑模变结构控制(SMC)仿真
  • 3.4 Linux目录操作