消费者行为会变、促销策略会变、甚至竞争对手也会变。你的模型如果还是半年前的版本,预测自然不准。本文介绍如何用在线学习(Online Learning)让模型随着新数据实时更新,无需每月重训,且代码改动极小。
一、概念漂移:为什么你的模型越用越不准?
零售数据中,概念漂移无处不在:
· 突发促销:某天开始买一送一,销量模式永久改变。
· 季节性转换:冰淇淋从春季到夏季,销量均值上升。
· 新品引入:老品被新品替代,历史规律失效。
· 外部事件:疫情、高温、节假日调整。
传统做法:每月手动重新训练一次模型,耗时且滞后。在线学习允许模型每次收到新数据后立即小步更新,持续适应变化。
二、在线学习 vs 批量学习
维度 批量学习(Batch) 在线学习(Online)
数据使用 一次全部训练 逐条或小批量更新
模型更新频率 定期(如月) 实时(每天/每小时)
计算资源 峰值高 平滑、低延迟
适应能力 滞后 快速跟踪变化
适用算法 树模型、深度学习 线性模型、SGD、浅层网络
对于树模型(LightGBM、XGBoost)的增量学习,目前支持有限(XGBoost 有 xgb.train(…, xgb_model=‘previous.model’) 可以继续训练,但效果一般)。更推荐使用 在线版本的线性模型 或 River 库。
但考虑到我们已经有训练好的 LightGBM 模型且效果不错,可以通过模型热更新 + 轻量级在线校准器的方式低成本实现。
三、实用方案:模型热更新 + 残差校准
3.1 整体架构
校准器只需要极少的特征(如时间、最近几天的误差、是否促销等),并可以实时更新。
3.2 实现残差校准器
from sklearn.linear_model import SGDRegressor
import numpy as np
class ResidualCalibrator:
def __init__(self, learning_rate='constant', eta0=0.01):
self.model = SGDRegressor(loss='squared_error', learning_rate=learning_rate, eta0=eta0)
self.features = [] # 用于存储最近的特征
self.targets = [] # 实际残差
self.is_fitted = False
def partial_fit(self, X_residual, residual):
# X_residual: 特征向量,比如 [星期几, 历史平均误差, 促销强度]
if not self.is_fitted:
# 第一次调用需要初始化
self.model.partial_fit(X_residual, [residual])
self.is_fitted = True
else:
self.model.partial_fit(X_residual, [residual])
def predict(self, X_residual):
if not self.is_fitted:
return 0.0
return self.model.predict(X_residual)[0]
# 使用示例
calibrator = ResidualCalibrator()
# 假设每天预测后,第二天拿到真实销量,计算残差
pred_base = 100
true = 115
residual = true – pred_base # +15
# 构造特征,例如:星期=3,过去7天平均绝对误差=5,是否促销=1
feat = np.array([[3, 5, 1]])
calibrator.partial_fit(feat, residual)
# 下次预测时,用 base_model 预测后,再用校准器修正
correction = calibrator.predict(feat_new)
final_pred = base_pred + correction
3.3 特征选择建议
校准器不需要很多特征,这几个很有效:
· day_of_week
· days_since_last_promotion
· recent_bias(过去7天残差的移动平均)
· is_holiday_tomorrow
四、方案二:使用 River 库实现真正的在线学习
如果你希望彻底抛弃重训流程,可以使用 River(专为在线学习设计的 Python 库)。
pip install river
from river import linear_model, metrics, preprocessing
# 定义在线回归模型(带特征缩放)
model = (
preprocessing.StandardScaler() |
linear_model.LinearRegression(optimizer='SGD', l2=0.01)
)
metric = metrics.MAE()
# 模拟数据流
for xi, yi in data_stream:
# xi: 特征字典,yi: 真实销量
y_pred = model.predict_one(xi)
metric.update(yi, y_pred)
model.learn_one(xi, yi) # 更新模型
River 支持特征哈希、缺失值处理、多种优化器,非常适合实时更新。但缺点是不太容易集成已有的 LightGBM 模型,适合新项目。
五、我的 API 中的在线学习策略
考虑到实际用户场景,我的销量预测 API 采用了 混合策略:
· 每日凌晨:自动拉取过去一天的真实销量数据(用户上传或授权拉取)
· 计算残差:对比前一天 base model 的预测
· 更新在线校准器(SGDRegressor,用最近 30 天的残差流)
· 每周一:如果过去一周的校准后误差超过阈值,触发 LightGBM 增量训练(xgb_model 参数,或完全重训但用 warm start)
用户无感知,但模型持续进化。上线后,模型 WMAPE 从 13% 逐步降至 11%,且对促销变化的响应时间从 2 周缩短到 2 天。
六、你也能轻松实现
如果你已经使用了我的 API,在线学习默认开启,无需任何操作。但如果你自己部署模型,可以参考上述残差校准器代码,只需 30 行就能让你的模型“活”起来。
免费试用期间,你可以观察 API 响应头中的 model-version 字段,它记录了基础模型的训练日期和校准器的最后更新时间,透明展示模型的活跃度。
七、总结与预告
在线学习是让预测模型长期保持高精度的关键。本文介绍了两种轻量级方案:残差校准器(兼容现有模型)和 River 库(全新项目推荐)。
互动问题:你的业务中概念漂移最明显的例子是什么?(例如“某个月突然流行的商品”)评论区交流。



