乘用车细分市场销量预测:分层建模与特征工程实战
1. 赛题背景与整体思路拆解1.1 这个赛题到底在预测什么乘用车细分市场销量预测说白了就是给定历史若干个月的车型销量数据去预测未来若干个月、不同车型在不同细分市场下的销量。2019年那场竞赛给出的数据维度相当丰富车型配置、品牌、车身类型、排量、变速箱、上市时间、指导价区间以及按月份排列的销量序列。目标是把未来一段时间内每个车型-细分市场组合的销量预测准。这类问题的难点不在于模型有多深而在于数据本身极其稀疏且波动剧烈。一款车可能上市三个月月销过万然后突然掉到几百台也可能长期稳定在某个区间。再加上细分市场划分比如按车身形式、按价格带、按动力类型每个细分市场里的样本量差异巨大有的细分市场只有几十条记录有的上千条。这种长尾分布直接决定了不能用一个统一模型硬套所有细分市场。适合参考这篇内容的人我大致分三类一是打过结构化数据预测类竞赛、想看看别人怎么处理稀疏时序的二是做汽车行业数据分析、需要落地销量预测的从业者三是刚入门机器学习、想找一个完整项目练手的同学。不管哪一类核心收获应该是一样的——如何把脏、乱、稀疏的业务数据转化成模型能吃的形态并且在验证环节不骗自己。1.2 为什么最终方案是分而治之而不是端到端我们队伍在赛后复盘时最大的共识就是这个赛题如果强行做一个端到端的深度模型大概率会翻车。原因有三个。第一数据量不够。虽然看起来有几万条记录但分摊到每个细分市场、每个车型、每个时间点上可用样本非常有限。深度模型在这种稀疏场景下极易过拟合验证集稍微一变线上成绩就崩。第二业务逻辑强。汽车销量有明显的季节性金九银十、春节前后低谷、政策周期性排放标准切换、购置税优惠、产品生命周期改款、停产。这些因素用树模型加人工特征工程比让神经网络自己学要靠谱得多。第三评估指标敏感。竞赛用的评估指标对高销量车型的绝对误差惩罚很重这意味着大销量车型的预测精度直接决定排名而小销量车型预测得再准也拉不开差距。所以策略上必须对大销量车型单独加码。基于这三点我们最终走的是**分层建模 多模型融合 后处理校准**的路线。分层是指按细分市场或销量量级分组分别训练模型多模型融合是指LightGBM、XGBoost、CatBoost以及一个简单的时序基线做加权后处理校准则是针对预测结果的分布做修正避免出现负销量或异常尖峰。这里给一个实操心得不要一上来就追求模型复杂度。我们前两周试过LSTM和Seq2Seq验证集RMSE比LightGBM高了将近30%而且训练时间翻了好几倍。后来果断放弃深度路线把精力全砸在特征工程和分组策略上成绩才稳步上升。1.3 整体流程的五个阶段把整个项目拆开大概是这么五步数据清洗与对齐把车型配置表、销量表、上市时间表按车型ID和月份对齐处理缺失值和异常值。探索性分析看销量分布、季节性、车型生命周期曲线确定分组依据。特征工程构造滞后特征、滑动窗口统计、同比环比、生命周期阶段标记、细分市场聚合特征等。模型训练与验证按时间切分验证集分组训练多个模型记录每组最优模型。融合与后处理加权融合、截断负值、对高销量车型做残差修正。这五步里第三步和第四步占了我们80%的时间。下面我逐个展开把踩过的坑和最终有效的做法都讲清楚。2. 数据清洗与探索性分析的关键细节2.1 数据对齐时最容易忽略的三个坑第一个坑是车型ID不一致。配置表和销量表里的车型标识可能因为改款、年式变化而出现一对多或多对一的情况。我们的处理方式是以销量表的车型ID为主键配置表通过品牌车系年式做模糊匹配匹配不上的用同车系最近年式的配置填充。这一步听起来简单但实际做的时候会发现大概有5%到8%的记录匹配不上如果直接丢掉会损失不少高销量车型的样本。第二个坑是月份缺失。有些车型在某些月份没有销量记录这到底是销量为零还是数据缺失我们的判断逻辑是如果该车型在缺失月份的前后都有销量且上市时间早于缺失月份、停产时间晚于缺失月份那就填0否则标记为缺失不参与训练。这个逻辑必须写清楚否则模型会把缺失当成零来学导致预测偏低。第三个坑是异常值。汽车销量偶尔会出现极端值比如某个月突然几万台下个月又回到几百台。这可能是批发数据集中录入也可能是特殊促销。我们的做法是对每个车型的销量序列做3倍标准差检测超过阈值的点用前后三个月的移动中位数替换。注意不要直接删除异常点因为删除会破坏时间连续性影响滞后特征的构造。2.2 探索性分析三个必须看的图做时序预测有三张图一定要画。第一张是整体销量按月汇总的折线图。这张图能告诉你季节性有多强。我们当时画出来发现每年2月都是低谷9月到11月是高峰这和行业常识完全吻合。有了这个认知后面构造月份特征时就有了依据而不是盲目让模型去学。第二张是车型生命周期曲线。随机抽20到30个车型把它们的销量按上市后的月份数画出来。你会发现大部分车型符合上市爬坡-稳定-衰退的S型曲线但也有一些车型一上市就是巅峰然后迅速下滑。这个观察直接启发了我们构造上市月数和上市月数的平方两个特征用来捕捉生命周期的非线性。第三张是细分市场销量分布箱线图。这张图决定了你怎么分组。我们当时按车身类型和价格带交叉分了大概12个细分市场发现其中3个细分市场的销量中位数是另外9个的5倍以上。这就意味着如果统一建模大销量细分市场会主导损失函数小销量细分市场被忽略。所以必须分组或者至少给样本加权。2.3 分组策略的确定过程分组不是拍脑袋我们试了三种方案分组方案依据优点缺点最终是否采用按细分市场车身类型价格带业务含义清晰部分组样本过少作为主分组按销量量级历史月均销量分高/中/低样本均衡业务解释弱作为辅助加权按品牌国别自主/合资/进口宏观因素一致组内差异仍大放弃最终采用的是主分组按细分市场同时在每个组内按销量量级给样本加权。具体来说月均销量超过5000台的样本权重设为31000到5000的设为2低于1000的设为1。这样既保留了业务解释性又缓解了样本不均衡。注意分组数量不要太多。我们一开始分了20多个组结果有些组只有几十条训练样本模型根本学不动。后来合并到12个组每组至少300条以上样本效果明显稳定。3. 特征工程从原始字段到模型可用的输入3.1 滞后特征与滑动窗口时序预测的命根子任何时序预测滞后特征都是最重要的。我们构造了以下几类滞后1到12个月的销量直接反映近期趋势。滑动窗口统计过去3个月、6个月、12个月的均值、中位数、标准差、最大值、最小值。同比特征去年同月的销量以及今年累计销量与去年累计销量的比值。环比特征本月销量与上月销量的差值、比值。这里有个细节滞后特征在训练集和测试集上的构造方式必须一致。比如预测未来3个月那么测试集里每个样本的滞后特征只能用预测起点之前的数据。我们当时写了一个滑动窗口生成函数确保不会出现用未来数据预测未来的泄漏。滑动窗口的窗口长度选择也有讲究。窗口太短噪声大窗口太长反应迟钝。我们试了3、6、12三种最终发现6个月窗口在验证集上表现最稳。这可能是因为汽车销量的中期趋势比短期波动更有预测价值。3.2 生命周期特征让模型知道车处于什么阶段前面探索性分析发现生命周期很重要所以专门构造了一组特征上市月数当前月份减去上市月份。上市月数的平方捕捉爬坡和衰退的非线性。是否改款如果配置表里有年式变化标记为1。是否停产如果后续月份没有销量记录标记为1。这组特征在树模型里的重要性排名一直很靠前。特别是上市月数在很多细分市场组里都是前五重要的特征。3.3 细分市场聚合特征引入横向对比除了单车序列特征我们还构造了同细分市场同月的聚合特征该细分市场当月总销量。该车型销量占细分市场总销量的比例。该细分市场当月车型数量。该车型销量在细分市场内的排名。这些特征的作用是给模型提供横向参照。比如一款车自身销量在下降但如果整个细分市场都在下降那它的相对表现其实没变。模型有了这些特征就能区分个体问题和市场问题。3.4 类别特征的处理目标编码 vs 独热编码品牌、车身类型、变速箱这些类别特征我们试了两种处理方式独热编码适合类别数少的特征比如变速箱手动/自动/双离合等不到10类。目标编码适合类别数多的特征比如品牌几十个、车系上百个。目标编码有个经典陷阱必须用交叉验证的方式计算否则会泄漏标签。我们的做法是把训练集分成5折每折用其他4折的销量均值来编码当前折的品牌测试集用全量训练集的均值编码。这样既利用了品牌信息又避免了过拟合。实操心得目标编码后一定要加一个平滑项。比如品牌A只有2条记录均值是10000直接编码会让模型对这个品牌过拟合。我们的平滑公式是编码值 (该品牌销量和 全局均值 × 平滑系数) / (该品牌样本数 平滑系数)平滑系数取10到20之间。实测下来平滑后验证集误差下降了约5%。4. 模型训练、验证与融合的完整实操4.1 时间序列验证集的切分方式这是整个项目里最容易犯错的地方。很多人做时序预测直接用随机切分结果验证集里混入了未来信息线下成绩虚高线上直接崩。正确的做法是按时间切分。比如用前18个月做训练第19到21个月做验证第22到24个月做测试。如果要做多折验证就滚动切分第一折用1到15月训练、16到18月验证第二折用1到18月训练、19到21月验证以此类推。我们当时用了3折滚动验证每折的验证集大小和测试集一致都是3个月。这样得到的验证成绩和线上成绩相关性很高基本能反映真实水平。4.2 三个模型的参数配置与调优过程我们最终融合了三个模型LightGBM、XGBoost、CatBoost。参数不是随便设的而是用贝叶斯优化跑了大概200轮。LightGBM的核心参数lgb_params { objective: regression, metric: rmse, learning_rate: 0.03, num_leaves: 63, max_depth: 8, min_data_in_leaf: 20, feature_fraction: 0.8, bagging_fraction: 0.8, bagging_freq: 5, lambda_l2: 1.0, n_estimators: 2000, early_stopping_rounds: 100 }XGBoost的核心参数xgb_params { objective: reg:squarederror, eta: 0.03, max_depth: 7, min_child_weight: 5, subsample: 0.8, colsample_bytree: 0.8, alpha: 0.1, lambda: 1.0, n_estimators: 2000, early_stopping_rounds: 100 }CatBoost的核心参数cat_params { loss_function: RMSE, learning_rate: 0.05, depth: 7, l2_leaf_reg: 3.0, iterations: 2000, early_stopping_rounds: 100, verbose: False }调参时有个经验学习率不要设太大。0.03到0.05之间比较稳虽然训练慢一点但验证集波动小。另外min_data_in_leaf和min_child_weight这两个参数对稀疏数据特别重要设得太小会过拟合设得太大又欠拟合。我们最终取20和5是在验证集上试了十几组才定下来的。4.3 融合策略加权平均 vs Stacking我们试了两种融合方式加权平均三个模型的预测值按权重相加权重用验证集上的RMSE反比确定。Stacking把三个模型的预测值作为新特征再训练一个线性回归或小树模型。结果发现加权平均在验证集上更稳Stacking容易过拟合尤其是当某个模型在某个细分市场上表现特别差时Stacking会放大这个错误。最终我们用的是加权平均权重大概是LightGBM 0.4、XGBoost 0.35、CatBoost 0.25。注意融合前一定要检查各模型预测值的量纲是否一致。我们有一次发现CatBoost因为用了不同的目标函数预测值整体偏大融合后反而拉低了成绩。后来统一了目标函数才解决。4.4 后处理截断、平滑与高销量修正模型输出后我们做了三步后处理截断负值预测销量不能为负所有负值直接置0。平滑处理对每个车型的预测序列做3个月移动平均避免出现锯齿状波动。高销量修正对历史月均销量超过5000台的车型用验证集上的残差均值做加性修正。第三步是提分的关键。因为评估指标对大销量车型的误差惩罚重我们专门针对这部分车型做了偏差校正。具体做法是在验证集上计算每个高销量车型的预测残差真实值减预测值取均值然后加到测试集预测上。这个操作让我们的线上成绩提升了大概2到3个名次。5. 常见问题与排查技巧实录5.1 验证集成绩很好但线上崩了怎么查这是时序竞赛最经典的问题。排查顺序如下排查项可能原因解决方法特征泄漏用了未来数据构造特征检查所有滞后和滑动窗口的生成逻辑验证集切分随机切分而非时间切分改为滚动时间切分分布偏移训练集和测试集时间跨度大加入时间衰减权重过拟合模型太复杂或特征太多减少特征、增加正则化我们当时遇到过一次线上崩盘最后查出来是目标编码时用了全量数据导致验证集泄漏。改成交叉验证编码后线上线下相关性立刻恢复正常。5.2 小销量车型预测全是零怎么办小销量车型样本少模型容易直接预测零。我们的处理方式是对月均销量低于100台的车型单独训练一个分类模型先判断是否有销量再回归具体数值。在损失函数里给小销量样本更高的权重但不要太高否则会牺牲大销量车型的精度。后处理时如果模型预测为零但历史上有过销量用历史中位数替换。5.3 训练时间太长怎么加速LightGBM和XGBoost在几万条数据上其实很快但如果特征维度上千、树的数量上千训练时间会明显增加。加速手段用feature_fraction和colsample_bytree降低每棵树的特征采样比例。提前停止early stopping一定要开通常500到800棵树就够了。把数据转成LightGBM的Dataset格式能省不少内存和时间。如果机器有多核设置num_threads为物理核心数不要设成逻辑核心数否则会因超线程反而变慢。5.4 独家避坑清单最后整理几条我们踩过的坑都是文档里不会写的不要用未来数据做任何统计包括均值、中位数、编码全部要用滚动窗口或交叉验证。验证集一定要和测试集同分布如果测试集是未来3个月验证集也必须是连续的3个月不能随机抽。融合权重不要用测试集调只能用验证集否则就是变相泄漏。后处理要谨慎平滑和修正都可能引入偏差每次改动都要在验证集上确认。保存每次实验的配置和结果我们最后复盘时发现最好的方案往往是几次小改动的组合如果没有记录根本复现不出来。这个赛题做完我最大的体会是结构化数据预测特征工程和验证策略的重要性远大于模型本身。把数据对齐做干净、把验证集切对、把滞后特征构造好哪怕只用LightGBM单模型也能进前10%。反过来如果这些基础没做好堆再多深度模型也是白搭。后续如果还想继续优化可以考虑引入外部数据比如宏观经济指标、油价或者对每个细分市场单独做超参搜索但边际收益可能就没那么大了。

相关新闻

灰度用户能更新,未覆盖用户却一直提示最新版:HarmonyOS 分阶段发布的检查更新边界

灰度用户能更新,未覆盖用户却一直提示最新版:HarmonyOS 分阶段发布的检查更新边界

灰度用户能更新,未覆盖用户却一直提示最新版:HarmonyOS 分阶段发布的检查更新边界 新版本按 10% 灰度发布后,部分用户收到更新,另一些旧版本用户点“检查更新”却显示已经是最新版;客服又发出详情页链接后&#xff0c…

2026/10/13 15:02:33 阅读更多 →
AI时代小白也能学:FDE前沿部署工程师,帮你企业AI转型不踩坑!

AI时代小白也能学:FDE前沿部署工程师,帮你企业AI转型不踩坑!

AI时代,企业转型焦虑重重,钱花了却没效果。文章介绍了FDE前沿部署工程师,他们懂AI也懂企业运营,能诊断问题、设计流程、落地工具,用AI帮助企业赚钱提效。FDE不需要复杂代码能力,而是“懂生意的AI应用专家”…

2026/10/13 15:01:32 阅读更多 →
Vite对比Webpack:核心优势、真实短板与迁移踩坑实战

Vite对比Webpack:核心优势、真实短板与迁移踩坑实战

这几年前端社区里关于构建工具的讨论,vite 几乎成了一个绕不开的名字。不管你是刚从 webpack 入门的新人,还是被各种构建配置折磨过的老手,应该都听过“vite 启动快、热更新快”的说法。不少团队在尝试从 webpack 切到 vite,也有不…

2026/10/13 15:01:32 阅读更多 →

最新新闻

选择排序与插入排序:手写背后的底层直觉与工程权衡

选择排序与插入排序:手写背后的底层直觉与工程权衡

1. 为什么今天还要手写选择排序和插入排序?——从“能跑通”到“真理解”的分水岭很多人看到“算法-6-选择排序插入排序”这个标题,第一反应是:这都2024年了,Python里一个sorted()、JavaScript里一个.sort()就搞定的事&#xff0c…

2026/10/13 15:56:01 阅读更多 →
FFmpeg 3.4.2 离线包部署指南:解压、环境配置与常见转码命令详解

FFmpeg 3.4.2 离线包部署指南:解压、环境配置与常见转码命令详解

简介:这是一份FFmpeg 3.4.2稳定版的Windows预编译库资源,面向需要在应用程序中集成音视频处理能力的C/C开发者。包内同时提供32位与64位动态库,涵盖DLL运行库、配套导入库及头文件,开发者可基于这些文件快速完成环境配置&#xff…

2026/10/13 15:56:01 阅读更多 →
LiteLLM实践:多模型API统一接入与代理网关

LiteLLM实践:多模型API统一接入与代理网关

最近在做大模型应用落地,手里同时握着好几家主流模型的 API Key,结果发现最痛苦的其实不是效果调优,而是工程侧怎么把这么多接口统一管理起来。各家调用的报文格式不一样、鉴权方式不一样、返回结构也不一样,模型一多,…

2026/10/13 15:56:01 阅读更多 →
C#对接ONVIF摄像机:从发现设备到RTSP取流与PTZ云台控制的完整链路

C#对接ONVIF摄像机:从发现设备到RTSP取流与PTZ云台控制的完整链路

简介:面向需要在C#项目中集成Onvif协议的开发者,这份Demo程序提供了一套亲测可用的摄像机对接方案,涵盖RTSP视频流地址获取、PTZ云台控制、预置位设置与调用,并借助VLC 3.0.4.0实现视频流播放,同时附带获取RTSP地址的W…

2026/10/13 15:56:01 阅读更多 →
信贷决策建模:特征工程、评分卡与可解释性实战解析

信贷决策建模:特征工程、评分卡与可解释性实战解析

简介:2020年数学建模C题企业信贷风险预测的完整解答文档,面向备战数模竞赛、希望掌握机器学习风控建模的读者。文档围绕“量化分析—特征工程—模型构建—评估优化”主线展开:先将企业信贷违约风险转化为可量化评分,再从进项与销项…

2026/10/13 15:56:01 阅读更多 →
智能体运营蓝图:从系统打通到互联企业的实践路线

智能体运营蓝图:从系统打通到互联企业的实践路线

我做了不少企业数字化项目的咨询,一个感受特别深:很多公司系统上了不少——CRM、ERP、MES、OA,一个都不少,但业务跑起来还是靠人在几个系统之间来回搬运信息。说要"互联",最后连了个寂寞。这两年智能体&…

2026/10/13 15:55:00 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →