
商品销量预测这件事干过电商和零售数据分析的朋友应该都有同感看着像一个建模问题真正做起来却是数据、业务和系统搅在一起的一场混战。这里说的销量预测不是拍脑袋给一个总数而是要回答“未来一段时间里某个SKU在某个渠道大概能卖掉多少”背后牵动的往往是补货计划、库存水位、促销排期和物流调度。预测准一点库存周转率和缺货率都会有肉眼可见的改善预测偏了轻则积压资金重则大促前断货。这篇文章就聊聊商品销量预测从需求拆解、数据准备、方法选型到特征工程、评估上线的完整思路也会把项目里踩过的坑一并写出来。适合刚接触预测的数据分析师、想落地预测能力的运营或供应链同学也适合已经跑通了几版模型但总感觉“差点意思”的同行。1. 先想清楚商品销量预测到底在预测什么很多预测项目翻车不是算法不够好而是任务没定义清楚。拿到需求先别急着建模至少要把三个问题问明白。1.1 业务目标决定预测粒度第一个问题是预测结果给谁用、拿去做什么决策。是给采购做单SKU补货还是给财务做月度经营计划这两个场景对粒度的要求完全不同。补货场景通常要精细到“SKU × 门店 × 日”因为门店库容小送货周期又固定太粗的预测根本没法用。而财务排资金、排产能往往只要“类目 × 月”甚至“品牌 × 月”就够。粒度越细数据噪声越大预测难度成倍上涨。我见过一个零售项目业务方嘴上说“我要下个月总销售额”模型也确实做到95%精度结果上线后一线仓库根本不看因为他们关心的是每个单品明天送多少箱不是总额。第二个问题是预测周期多长。7天、28天还是90天决定了模型能依赖多少滞后信息。短期预测可以大量使用“昨天销量”“近7天均值”这类强特征长期预测则必须更依赖趋势、季节性和外部事件特征因为近期信息会快速衰减。第三个问题是预测对象怎么定义。同一款商品卖的是“件数”还是“金额”是否包含赠品是否剔除退换货这些口径不锁死后面所有数据都会打架。我的习惯是开工前用半页纸把“预测什么、给谁用、什么粒度、多久滚动一次”写清楚哪怕不完美也要先定个版本。1.2 为什么“看着准”的模型总被业务吐槽一个很容易踩的坑是大盘总量预测得很准但拆到SKU就崩了。总量准是因为不同SKU的预测误差相互抵消了A款多预测了100件B款少预测了100件合计刚好熨平。可业务真正需要的恰恰是A、B各自的值。所以只看整体MAPE是自欺欺人至少要按SKU拆开看误差分布。另一个槽点是“模型在历史数据上很漂亮上线之后立刻衰减”。这在零售预测里太常见了。原因也不难理解模型学的是历史规律但商业环境一直在变。促销力度变了、竞品出了新品、供应链临时断货、平台流量规则调整任何一条都会让历史分布发生偏移。模型没有错错在假设“明天和昨天一样”。真正实用的做法是把预测系统做成每周滚动重训并且把“业务事件”单独记录成特征让模型有机会感知到变化。还有一个经常被忽略的问题业务方要的往往不是“最准的点”而是“敢不敢照着这个数下单”。如果你的模型只输出一个孤零零的数字业务方心里没底最后还是凭经验拍板。后面我会专门讲预测区间那是让模型结果真正被业务接收的关键一步。2. 数据准备预测模型的“地基”长什么样如果说模型是预测项目的门面那数据就是地基。地基没打好后面所有工作都是反复返工。2.1 需要收集的几类数据我列一个比较通用的数据清单做商品预测时优先把这几类凑齐销售流水日期、SKU编码、渠道/门店、销量、销售额、订单量。这是最核心的数据没有它一切免谈。日历特征节假日、大促日、周末、季末、月初月末。尤其要整理一张“业务事件日历”把历年的大促、上新、清仓节点都标出来。价格与促销成交价、原价、折扣率、是否参加满减/秒杀。价格变动对销量的影响非常大。库存状态断货记录、可售天数、到货计划。很多人忽略这一点导致0销量被当成普通低销量来学模型会严重失真。外部变量天气、温度、空气质量、节假日迁徙等。不同品类的敏感度差异很大比如啤酒和雪糕看温度雨具看降水家居服看降温。其他业务动作广告投放、直播带货、渠道主推位、老客复购活动等能收集多少收集多少。这里想强调一点数据不是越多越好而是“和业务决策相关”的才值得进模型。有些团队上来就堆上百个特征结果共线性严重训练慢还不一定涨点。先用手头数据快速建一版基线再决定要不要补外部数据是更务实的路线。2.2 清洗与口径统一销量预测项目里最坑的清洗问题是“0销量到底代表什么”。一种情况是真的没人买另一种情况是断货了根本没法买。如果不区分模型会学到“这个SKU有时候突然卖0件”然后给出一个偏低的预测补货就更保守越补越缺货。正确做法是把断货日期单独打标记要么在训练时剔除要么作为特征喂给模型让模型知道“缺货日不算数”。口径统一也容易埋雷。电商场景里“下单日期”和“支付日期”可能差几个小时甚至几天预售商品差距更大。同一套销量数据前一天用支付口径导出后一天用下单口径导出数字直接对不上。我的习惯是定义清楚“销量支付成功的订单对应的商品件数”并且按天归属到支付时间所在日期所有报表、特征、模型都锁死这个口径才能保证线上和训练数据一致。异常值处理也要小心。大促日销量可能是平日的几十倍如果不做强规则处理模型会被拉到“逢节必爆”的状态但如果直接把大促日删掉模型又学不到节日的增量。比较好的做法是把大促日标记成单独状态并让模型为它学习一个独立的叠加效应。也就是说不删异常值而是教会模型区分“这是特殊事件不是常态”。2.3 别小看节假日对齐这件事很多商品都有明显的节假日效应但节假日有一个麻烦日期每年都在变。春节可能在1月也可能在2月端午节、中秋节更不用说。如果直接拿“1月1日”“5月1日”这样的日历日期当特征跨年训练时模型就会糊涂2023年春节在1月下旬2024年春节在2月中旬同样的日历日对应完全不同的销售节奏。解决思路是把“相对日期”特征做出来。比如“距离春节还有几天”“端午节后第几天”“累计进入大促预热期第几天”。这样模型学的不是某个固定day了一个固定day了而是“节前第7天销量开始爬升”这种稳定规律。这里有个实操细节训练时一定要把节假日的相对位置算准特别是农历节日。我自己习惯用一个统一的“中国节假日表”数据源再人工校正一遍大促日、平台活动日避免节假日表错误污染所有特征。节假日处理是销量预测中最容易被低估的环节。很多模型精度上不去不是算法不行而是一到节前节后就系统性跑偏。把这一步做扎实效果立竿见影。3. 方法选型从简单到复杂分别什么时候用预测方法五花八门但我不建议一上来就上最重的模型。先搞清楚每种方法的适用边界再按业务场景匹配才是正确的顺序。3.1 先用基线方法找手感所谓基线方法就是用最简单的规则做预测比如“未来7天销量等于上周同期”“等于最近28天平均值”“等于去年同周销量”。这些方法没有复杂的参数但它们是整个项目的标尺。如果复杂模型连基线都打不过那不是模型的问题而是数据或任务定义有问题。我在实际项目里发现相当一部分低销量SKU用基线方法已经完全够用。比如那些日均销量稳定在两三件的小文具、配件用移动平均预测误差反而不大。如果强行上复杂模型不仅训练成本高还容易过拟合噪声。我的建议是第一版预测一定要跑三个基线——上周同期、最近4周均值、去年同期然后看每种SKU群组在哪个基线上表现最好。后续复杂模型只要能稳定提升WAPE几个百分点就值得上线如果提升太微弱就要怀疑投入产出比。3.2 统计模型适合什么场景时间序列统计模型比如指数平滑、ARIMA、SARIMA以及带节假日回归项的分解模型是销量预测的经典选择。它们把序列拆成趋势、季节、随机误差三部分结构清晰计算量小而且可解释性强。业务方问“为什么预测值这么高”你可以直接回答“因为去年同期也是这个水平而且近两周趋势在往下走”。这套方法适合什么情况呢历史数据相对稳定、周期规律明显、没有太多突发促销干扰的SKU。比如部分标品、老品、基础款。统计模型的短板也很明显它很难把价格、促销、天气这些外部变量全部吸收进来最多加几个回归项表达不了复杂的非线性关系。另外一旦序列里出现大促这种脉冲式波动统计模型常常反应过度或反应滞后。所以我的定位是统计模型可以作为强基线也可以用于快速验证数据质量还可以在冷启动或小数据场景下兜底。但它不太适合作为整个预测系统的主力模型尤其当你的SKU很多、外部因素很杂的时候。3.3 机器学习与深度学习怎么选机器学习模型尤其是梯度提升树这类模型XGBoost、LightGBM等都是常见的开源实现现在是销量预测落地的主流选择。它们的优势在于特征可以做得非常灵活塞进去促销、天气、节假日、库存状态一堆变量也没问题能自动捕捉非线性关系训练速度快支持成千上万个SKU一起建模。树模型对缺失值也有一定容忍度这在脏乱的业务数据里非常实用。深度学习模型比如LSTM、基于注意力机制的时序模型、Transformer类模型理论上能捕捉更复杂的时序依赖在多序列联合建模和超长周期预测上有潜力。但代价是数据量要求大、训练成本高、调参复杂而且可解释性差。如果业务方是库存管理团队他们往往很难接受一个“黑盒打分”给出来的补货量。我接触过的多数零售项目其实树模型已经能覆盖绝大部分需求深度学习更适合那些数据规模巨大、时序模式复杂、并且有专门数据团队持续迭代的场景。选型时我一般按三条标准取舍数据量够不够、业务是否要求解释、团队有没有持续维护能力。把这三点想清楚就不太会选错。方法数据要求可解释性外部变量支持上线维护成本典型场景基线/移动平均低高弱极低低销量SKU、冷启动兜底统计时序模型中高弱低稳定老品、基线对比梯度提升树中高中强中多SKU、多业务变量、落地主力深度学习很高低强高大规模时序、复杂模式、长期迭代4. 特征工程真正拉开预测效果差距的地方同一个模型算法不同人做特征效果能差出一大截。特征工程不是把能用到的字段全堆上而是要理解每个特征在回答什么问题。4.1 时间特征要“细抠”时间特征至少有四层抠法。第一层是基础日历周几、月几、几月、第几周、是否月初、是否月末、是否季度末。第二层是节假日相对位置距离节前多少天、节后多少天、是否为放假首日。第三层是业务节奏距离上次大促多少天、距离下次大促多少天、当前是否在大促预热期。第四层是周期性编码把星期几拆成day of week的数值或one-hot避免模型把“周六”当成一个比“周五”更大的数。滞后特征是销量预测的重中之重。常见组合是lag1、lag7、lag14、lag28分别对应“昨天”“上周同一天”“两周前同一天”“一个月前同一天”。再进一步还可以做滚动统计量过去7天均值、过去28天均值、过去7天最大值、过去28天标准差。滚动窗口能平滑短期波动给模型一个更稳健的“近期水平”信号。这里必须提醒一个高频坑滞后特征在训练时到底用“真实历史值”还是“上一期的预测值”。如果训练时用真实值上线预测时却拿不到未来几天的真实值就会出现特征分布不一致模型效果断崖式下跌。一般做法是训练和预测都用“截至T日已知的历史值”来构造特征上线时用滚动预测框架把上一轮预测值回填到滞后特征里。这一步非常容易被新手忽略。4.2 内部与外部变量的融合销量预测不能只盯着历史销量曲线。价格弹性是很多品类的核心驱动因素。我一般会构造这些价格特征当天的实际折扣率成交价/原价、折扣率相对于近30天的变化、商品是否参与秒杀或满减、价格同比是否调整过。折扣率这个特征在大促前尤其重要因为模型需要知道“现在的低价是临时的还是长期的”。库存状态特征同样关键。如果某SKU前天断货、昨天补货昨天的销量必然偏低可直接用销量历史去预测今天肯定会低估。把“断货天数”“最近到货后第几天”喂给模型它就能学会在恢复供货后给一个补偿性回升。天气变量则要看品类冷饮对温度敏感雨具对降水量敏感空调对高温天敏感。我的做法是把天气分桶比如“温度高于35℃”“降水量大于20mm”“温差超过10℃”而不是直接丢原始数值这样模型更容易学到业务可解释的阈值规律。4.3 多SKU之间的信息复用单个SKU的历史再长也是有限的尤其新品或低频SKU历史信息稀疏。这种情况可以考虑做层级特征同一类目下所有SKU的平均销量、同品牌下的平均趋势、同价格带的平均折扣敏感度。模型看到这个SKU自身数据少时会自动更依赖类目平均水平。更进一步可以对SKU做聚类分群比如分成稳定型、缓慢增长型、大促爆发型、季节性明显型。每个群组单独训练一个模型或者至少给模型加一个“群体标签”特征。实际操作中群体特征对中长尾SKU的提升往往比增加几十个普通字段更明显。原因很简单那些SKU自己的历史太短、信息量太少能够从“同类朋友”身上借力才是关键。但要注意层级特征里容易混入未来信息。比如用“当周类目总销量”作为特征预测未来某天销量时当周类目总销量还没发生这属于标签泄漏。正确做法是只使用截至预测日为止已知的类目数据比如前7天类目均值而不是预测期内或当天的数据。5. 训练与评估别只盯着一个指标很多团队把模型训练和评估搞得太简化一个随机切分、一个R2、一个MAPE就算交差。这在普通机器学习任务里可以在时序预测里却会埋下大雷。5.1 时序切分与验证策略销量预测是典型的时间序列问题训练和验证集必须按时间先后切分不能随机打乱。如果随机切分模型会偷看“未来”的信息验证集分数虚高上线后立刻现出原形。正确做法是用前70%的时间段训练后30%时间段验证或者用滚动时间窗口多次切分训练/验证比如训练1-12个月、验证13-15个月然后训练1-15个月、验证16-18个月多组对比更稳定。代码示例大致是这样的逻辑# 滚动时序切分的简化示意 train_test_windows [ (2022-01-01, 2023-03-31, 2023-04-01, 2023-06-30), (2022-01-01, 2023-06-30, 2023-07-01, 2023-09-30), ] for train_start, train_end, val_start, val_end in train_test_windows: train sales[(sales.date train_start) (sales.date train_end)] val sales[(sales.date val_start) (sales.date val_end)] # 训练、预测、评估验证时还要注意一个细节预测的是未来28天那么验证期也应该模拟“在第N天做预测然后看未来28天”而不是只预测验证集的第一天。这样才能真实反映线上滚动预测的表现。5.2 业务对齐的评估指标常用指标各有各的毛病。MAE好解释是“平均偏差多少件”但受高销量SKU的量纲影响很大MAPE听起来直观但遇到销量接近0的日子会直接爆炸WAPE按销量总额加权更稳定适合总量场景。多SKU评估我建议拆开看高销量SKU看WAPE中销量看MAE低销量看特殊处理比如对单量归一化或者干脆用分桶后的误差等级。指标公式含义优点注意点MAE平均绝对误差直观、单位一致高销量SKU主导RMSE均方根误差惩罚大偏差对异常值敏感MAPE平均绝对百分比误差无量纲、可对比销量接近0时失真WAPE加权绝对百分比误差总量加权、稳健掩盖SKU结构偏差更重要的一点是指标要和业务损失绑定。如果补货不足导致缺货的损失远大于库存积压那么模型训练时应该更偏向“宁可多预测也不要少预测”这时可以用加权损失或分位数损失而不是一味追求平均精度。如果业务只关心总库存成本WAPE可能就够了。5.3 预测区间往往比点预测更有用点预测给的是一个均值但业务决策需要的往往是“最坏情况下的库存量”或者“保守的补货线”。这时候预测区间比点预测有用得多。比如你预测某SKU未来7天销量500件如果同时给出“80%概率落在430到580件”补货负责人就敢按上限备货如果只给一个500他会很犹豫。实操上有一种简单有效的做法用历史残差估计区间。先算模型在每个SKU上的历史预测误差取残差的25%和75%分位数作为区间宽度然后叠加到点预测上。想要更精细可以直接训练分位数回归模型让模型同时输出多个分位点。库存场景我通常用P80甚至P90作为默认补货参考量因为缺货损失的痛感远大于多囤一点货的库存成本。预测区间还有个额外好处它是和业务方沟通的桥樑。只要告诉对方“模型给的是一个区间而不是一个点”他们就不会再纠结“你怎么可能预测得那么准”沟通成本会明显下降。6. 一次完整的销量预测落地实录理论说再多不如把一条完整链路跑一遍。下面用一个模拟案例来拆解数据完全脱敏但流程、代码思路都是实际项目里能直接套用的。6.1 案例背景与数据形态假设某零售企业要为一个品类做未来28天的SKU级日度销量预测覆盖200个SKU历史数据是最近两年的日粒度销售流水。业务方明确说预测结果每天更新一次用于自动生成门店补货建议。所以我们需要的是“T日晚上预测T1到T28天销量”零售门店按周补货实际系统主要用未来7天的预测。数据样例大概长这样日期SKU编号门店/渠道销量销售额折扣率是否断货温度2023-01-01SKU_A渠道112024000.0032023-01-01SKU_B渠道284000.213这一阶段要做的不复杂把日期、SKU、渠道拼起来作为唯一主键把销量作为目标变量把折扣率、是否断货、温度这些都整理成可用的特征。一个让我印象很深的点是门店和渠道差异太大如果强行把所有渠道放在一起训练模型会把精力花在区分渠道基数差异上。所以这个案例里我们会把渠道作为特征同时对高销量SKU单独建模对中长尾SKU按类目聚合建模。6.2 核心特征与建模代码特征工程的代码我通常按“时间特征 滞后特征 外部变量 层级特征”四个模块来写。下面是简化但可运行结构import pandas as pd import numpy as np df pd.read_csv(sales_data.csv) df[date] pd.to_datetime(df[date]) df df.sort_values([sku_id, date]).reset_index(dropTrue) # 日历特征 df[dayofweek] df[date].dt.dayofweek df[month] df[date].dt.month df[is_month_start] (df[date].dt.is_month_start).astype(int) # 滞后特征与滚动特征 df df.groupby(sku_id).apply( lambda x: x.assign( lag_1x[sales].shift(1), lag_7x[sales].shift(7), lag_14x[sales].shift(14), rolling_mean_7x[sales].shift(1).rolling(7).mean(), rolling_max_28x[sales].shift(1).rolling(28).max(), ) ).reset_index(dropTrue) # 业务事件特征 df[is_promotion] (df[discount_rate] 0).astype(int) df[stockout_days] df.groupby(sku_id)[is_stockout].cumsum() # 剔除缺货目标样本或单独处理 df df[df[is_stockout] 0] # 建模目标与特征列 features [ dayofweek, month, is_month_start, lag_1, lag_7, lag_14, rolling_mean_7, rolling_max_28, is_promotion, discount_rate, stockout_days, ] X df[features] y df[sales]这段代码有几个地方是实际工作中容易漏的滞后特征一定要按SKU分组shift否则会把不同SKU的数据串起来滚动窗口要以shift(1)为起点不能用当天销量算进“当天预测”的特征里断货样本得先剔除否则会把断货导致的0销量当成正常需求。模型训练这一段我直接用LightGBM做回归参数不需要太复杂。子采样、学习率和树深度稍微调一下就能得到一个能用的模型import lightgbm as lgb train_mask df[date] 2023-10-01 valid_mask (df[date] 2023-10-01) (df[date] 2023-11-01) model lgb.LGBMRegressor( n_estimators500, learning_rate0.05, max_depth6, num_leaves31, subsample0.8, colsample_bytree0.8, random_state42, ) model.fit(X[train_mask], y[train_mask]) y_pred model.predict(X[valid_mask])如果你想做分位数预测把目标换成多个quantile模型代码结构几乎不变只是损失函数换成分位数损失。实际操作里我一般用三个模型分别预测P10、P50、P90取P90作为补货参考线。6.3 效果对比与业务落地这个案例里全量SKU的基线上周同期法WAPE大约是38%换成梯度提升树模型后降到26%左右下降了约12个百分点。拆开看提升主要来自两部分大促和节假日前后的预测准确度大幅提升以及中长尾SKU借助类目层级特征后不再“瞎猜”。高销量SKU提升更明显有的从30%降到15%以下。落地时还有一件容易被忽略的事模型输出不是一个数字而是一张表包含SKU、日期、P50预测、P80预测、P90预测、历史同期参考。这张表每天早上由定时任务跑完写进业务数据库再由补货系统读取。上线第一周仓库反馈最大的变化不是“预测多准”而是“终于每天能看到一个统一的、可追溯的数字了”——这其实说明预测项目的第一个价值是“统一口径、替代拍脑袋”。经验总结下来全量SKU一视同仁上复杂模型是浪费。我后来的做法是高销量SKU上完整特征模型中等销量SKU用简版特征模型低销量SKU直接走基线规则。这套分层策略既保证了整体精度又控制了训练和运维成本。7. 上线后的常见问题与排查实录模型上线只是开始真正让人头疼的是后面不断冒出来的各种“怪现象”。下面几个问题几乎每个预测项目都会遇到。7.1 预测结果“自然漂移”怎么办不少团队会遇到这种情况模型刚上线时效果不错跑了三周之后每天的预测值开始整体偏高或偏低而且一天比一天明显。优先排查的方向是特征更新。滞后特征依赖“上一期销量”如果上游数据链路中断昨天销量没进特征模型就会用更旧的数据来预测偏差自然越来越大。我一般会在预测报表里加两列训练数据截止时间、特征数据更新时间一旦出现漂移先看这两列大部分问题都能立刻定位。另一个常见原因是节假日效应随着临近快速增强。比如模型预测距离大促还有10天销量平稳但电商平台提前放出了预售入口实际销量已经爬升。这时候不是模型坏了而是“事件提前发生”。解决办法是把“距离大促天数”类特征做得更细并且定期复盘模型在重大节日前后是否存在系统性偏差有偏差就在重训时调整节日窗口。7.2 新SKU冷启动怎么处理新SKU没有历史销量模型没法算滞后特征最容易出现“预测为0”的尴尬结果。我的处理分几步走。先找到同品类、同价格带、同目标人群的成熟SKU用它们的平均销量曲线作为初始预测然后给一个“上市期成长系数”比如第1周0.3、第2周0.5、第3周0.7逐步放大等新SKU积累到4周真实销量后再切换成正常模型。整个过程的关键是“不要硬套全量模型”否则新品的预测会被方差巨大的少数样本带偏。还有一个冷启动细节新品往往伴随大力度促销上市如果能拿到新品的曝光量、加购量、预售量这些早期信号比历史销量值钱得多。把它们作为额外特征接入冷启动预测的准确度会明显提升。7.3 业务方说“不准”时怎么沟通预测项目里“不准”是常态因为业务方心里往往有一个隐藏的对照上个月实际销量。如果预测值和上月差很多哪怕模型误差其实很小也会被认为不准。遇到这种情况不要急着改模型先一起拆解偏差来源是模型预测错还是业务动作变了导致实际值偏离常态比如突然断货、清仓、改价、换主图、调整投放都会让销量突变这种偏差和模型能力无关。我的沟通习惯是三点第一预测结果尽量带区间用“未来一周大概率在400到500件之间”替代“预测450件”第二每周出一份预测复盘把预测值、实际值、偏差原因列出来让业务方看到偏差不是随机瞎猜而是可以归因的第三明确告诉业务方预测系统给出的是“假设外部条件不变情况下的需求估计”业务需要留意的是超出区间的异常信号而不是纠结每次预测是否精确命中。最后再分享一个我自己的习惯任何预测项目都不要一开始就追求全量上线。先挑一个SKU群组或一个区域打通“数据清洗—特征构建—模型训练—预测输出—业务校验”的完整链路跑通验证有效之后再横向推广。推广时也保留基线模型作为双保险。这个习惯帮我少踩了很多坑尤其是那种“模型在实验室里很高分一接真实业务就崩”的尴尬很大程度上就是靠分层、分群、带区间逐步上线的打法规避掉的。销量预测说到底不是一场算法竞赛而是一套围绕业务决策的数据工程把流程理顺比单纯追求精度更值得花时间。