7B大模型做二分类输给了LightGBM:聊聊模型选型、特征穿越和上线前那七项自检

🔑 关键词:机器学习,模型选型,特征穿越,LightGBM调参,离线在线一致性

📖 摘要:用一次真实项目复盘,讲清楚为什么结构化表格任务里GBDT经常赢过深度模型和LLM,特征穿越怎么把AUC 0.94的模型打回0.83,以及LightGBM几个会咬人的参数和上线前必过的七项自检清单。

7B大模型做二分类输给了LightGBM,聊聊那些没人告诉你的模型选型坑

图片

先把我现在的默认姿势摆出来

现在的默认起手式是:LightGBM + 按时间切分 + 至少三个月的回溯验证。只有在文本、图像、序列交互这类任务上才考虑深度模型。LLM 微调?除非任务长成「自由文本进、结构化字段出」的样子,否则我不碰。

这不是保守,是拿钱和时间换来的。2023 年我接手一个设备故障预警项目,前一位同事花了六周微调一个 7B 模型做二分类,A 榜准确率 91.3%,看着挺唬人。我推倒重来,还是 LightGBM,特征是从振动传感器原始信号里手搓的 14 个统计量——均值、方差、峰度、过零率、频带能量比这些。最后准确率 93.7%,推理延迟从 340ms 降到 6ms,机器从一张 A100 换成一台 8 核 16G 的 CPU 服务器。

老板问我,那之前六周算什么。我说算交学费,我第一年也这么干过,把一个 BERT 塞进只有 3 万条样本的工单分类里,过拟合到连我自己都不认识。

图片

真正让我丢脸的不是模型,是特征穿越

模型选型选错了,最多浪费算力。特征穿越选错了,是要出事的。

2021 年做信贷违约预测,第一版模型随机切分,AUC 0.94,KS 0.52。当时组里有人开玩笑说这模型可以直接退休了,不用再调。上线两周,实际 KS 掉到 0.21,坏账率没降反而涨了。

复盘了整整一周。问题出在我用了「近 30 天登录次数」「近 90 天还款笔数」这类特征,而这些字段在数仓里是 T+1 凌晨才更新完的。也就是说,一个 3 月 15 日的样本,我读到的「近 30 天」其实混进了 3 月 16 日之后才落库的信息。随机切分又把这种时间泄漏打散了,验证集里有一半样本和训练集共享同一批未来信息,AUC 当然漂亮。

图片

修法很土,但管用:

  1. 切分一律按时间。train 取 2020-01 到 2020-12,valid 取 2021-01 到 2021-03,test 取 2021-04 到 2021-06。不要随机,永远不要。
  2. 给每个特征标一个「可用时间」。还款笔数是 T+1,那在 T 日样本上要么做 lag,要么整列删掉。我现在的习惯是建一张特征字典表,字段名、口径、更新频率、可用延迟、负责人,五个字段。麻烦,但能救命。
  3. 线上加新鲜度监控。每天统计每个特征的 null 率和分布,PSI 超过 0.25 就告警。

改完以后,那个模型 AUC 掉到 0.83,KS 0.34。数字丑了,但线上跑了半年,KS 在 0.31 到 0.36 之间晃,没崩过。

LightGBM 调参,我只记几个会咬人的参数

在那份 47 万行、213 个特征、正样本占比 3.7% 的信贷数据上,我做过一组对比。num_leaves 从 31 拉到 255,训练集 AUC 从 0.87 涨到 0.96,验证集 AUC 反而从 0.821 掉到 0.807。同一份数据,同样的特征,只改了这一个参数。

图片

所以别一上来就 127、255。我常用的起手参数记在这儿:

  • num_leaves=31
  • learning_rate=0.05,n_estimators=2000,early_stopping_rounds=50
  • min_child_samples=20 起步,样本少的时候调到 50
  • feature_fraction=0.8,bagging_fraction=0.8,bagging_freq=1
  • lambda_l2=1.0
  • is_unbalance 保持 False,自己算 scale_pos_weight

最后这个很多人不注意。is_unbalance 和 scale_pos_weight 同时开,权重会被叠加两次,概率分布直接歪掉,你后面按业务成本算阈值就算不准了。

什么时候我才会真上大模型

图片

不是不用,是得看任务的形状。

判据两条,土办法但好用。输入是自由文本或多模态、输出是结构化字段——微调小模型值得试。我们做过一个客服对话抽工单字段的任务,Qwen2.5-1.5B 加 LoRA,8000 条标注,训了大概 3 小时,F1 从规则版的 0.68 提到 0.89,单次推理成本比调闭源 API 低一个数量级还多。

输入是结构化表格——老老实实 GBDT。我做过三次对比,TabNet 和 FT-Transformer 在样本量小于 50 万时基本没赢过 LightGBM,而且调参耗时是人家的 5 到 10 倍。

还有个坑是概率校准。让 LLM 做二分类,输出是或否,你拿到的那个置信度是 token 概率,不是业务概率。要按阈值做决策,得再套一层 Platt scaling 或者 isotonic 回归,别直接拿 0.5 卡。这个我吃过亏,上线第一天阈值全跑偏,还好当天留了回滚开关。

图片

上线前我会过的七项自检

写得有点长了,最后放个我自己的清单,每次上线前过一遍:

  1. 切分是不是按时间,验证集是不是比训练集晚
  2. 每个特征的可用时间戳,有没有晚于标签观察点
  3. 逐列算训练集和线上的 PSI
  4. 缺失值处理在训练侧和推理侧是否一致
  5. 阈值是按业务成本算的,还是拍的 0.5
  6. 有没有回滚开关
  7. 上线后第一周,每天看一眼 KS 曲线

第 4 条那个坑我踩过。训练里 fillna(-999),推理服务里忘了写,结果线上所有缺失值被当成 0,模型把一大批正常用户判成了高风险,第三天早上才发现。这事儿我现在想起来还有点上火。

🏷️ 标签: