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

从Kaggle经典赛题到实战:Rossmann销售额预测的数据探索与特征工程全解析

1. 初识Rossmann销售额预测赛题

第一次接触Kaggle的Rossmann销售额预测比赛时,我被这个真实业务场景的问题吸引了。想象一下,你是一家连锁药店的区域经理,需要提前六周预测每家门店未来48天的销售额——这直接关系到库存管理、人员排班和促销策略。比赛提供的2013-2015年德国1115家Rossmann门店数据,包含了日期、促销、节假日等丰富信息,简直就是时间序列预测的完美练兵场。

原始数据分为两个核心文件:train.csv记录每日销售情况,store.csv存储门店静态属性。我习惯先用pandas快速浏览数据结构:

import pandas as pd train = pd.read_csv('train.csv', parse_dates=['Date']) stores = pd.read_csv('store.csv') print(train.head()) print(stores.describe())

关键字段包括:

  • 日期特征:Date, DayOfWeek, Month
  • 运营状态:Open(是否营业), Promo(是否促销)
  • 节假日:StateHoliday(国家假日), SchoolHoliday(学校假期)
  • 门店属性:StoreType(4种类型), Assortment(商品等级)
  • 竞争信息:CompetitionDistance(最近竞对距离)

2. 数据清洗与异常处理实战

拿到原始数据后,我花了整整两天时间做数据清洗。首先是处理缺失值——CompetitionDistance有3%的缺失,我的处理策略是用同类型门店的中位数填充:

stores['CompetitionDistance'] = stores.groupby('StoreType')['CompetitionDistance']\ .transform(lambda x: x.fillna(x.median()))

最棘手的是销售数据中的零值问题。原始数据中有0.3%的销售记录为0,分析发现它们分两种情况:

  1. 门店当天歇业(Open=0)
  2. 门店营业但销售额异常(Open=1)

对于第一种情况,我直接排除(测试集也只预测营业日的销售)。第二种情况采用Prophet模型进行插值:

from prophet import Prophet def fill_zero_sales(store_df): model = Prophet(yearly_seasonality=True) model.fit(store_df[store_df['Sales'] > 0]) future = model.make_future_dataframe(periods=365) forecast = model.predict(future) return forecast[['ds', 'yhat']]

3. 时间序列特征深度挖掘

3.1 基础时间特征构造

日期本身没有预测价值,需要分解出有业务意义的特征。我创建了这些特征:

  • 周循环特征:用sin/cos编码DayOfWeek(周一=sin(0), 周日=sin(2π))
  • 月份效应:德国12月圣诞季销售激增
  • 促销周期:Promo2是连续促销,需要计算当前处于促销周期的第几周
# 周循环编码示例 train['DayOfWeek_sin'] = np.sin(2 * np.pi * train['DayOfWeek'] / 7) train['DayOfWeek_cos'] = np.cos(2 * np.pi * train['DayOfWeek'] / 7)

3.2 业务事件特征

通过分析节假日前后销售曲线,我发现:

  • 圣诞节前两周销售额增长35%
  • 复活节前一周增长22%
  • 学校假期期间日均销售额比平时高18%

于是构造了"距离下次节假日天数"特征:

holiday_dates = train[train['StateHoliday'] != '0']['Date'].unique() train['DaysToNextHoliday'] = train['Date'].apply( lambda x: min([(d - x).days for d in holiday_dates if d > x], default=30))

4. 门店画像与竞争分析

4.1 门店分层特征

StoreType和Assortment的交叉分析揭示出关键洞见:

  • B类门店+扩展商品组合的门店,平均销售额比其他组合高62%
  • 周日营业的门店(仅占15%)贡献了28%的总销售额

我为此创建了门店分层标签:

stores['PremiumStore'] = ((stores['StoreType'] == 'b') & (stores['Assortment'] == 'c')).astype(int)

4.2 竞争特征工程

处理竞争对手数据时踩过一个坑:CompetitionOpenSince字段是竞对开业时间,需要计算"竞对已开业时长":

stores['CompetitionDuration'] = (pd.to_datetime('2015-08-01') - pd.to_datetime(stores['CompetitionOpenSinceYear'].astype(str) + '-' + stores['CompetitionOpenSinceMonth'].astype(str) + '-01')) stores['CompetitionDuration'] = stores['CompetitionDuration'].dt.days.clip(lower=0)

热力图分析显示:竞对距离<500米的门店,促销效果会降低约15%。因此我创建了竞争强度指标:

stores['CompetitionIntensity'] = 1 / (1 + stores['CompetitionDistance']/1000)

5. 高级特征工程技巧

5.1 动态时间窗口统计

借鉴比赛冠军方案,我实现了滚动统计特征:

  • 过去30天同门店的销售均值/标准差
  • 去年同期销售额变化率
  • 最近一次促销的销售提升比例
def rolling_features(df, window=30): return df.groupby('Store')['Sales']\ .rolling(window, min_periods=1)\ .agg(['mean', 'std'])\ .add_prefix(f'rolling_{window}_')

5.2 prophet时间序列分解

使用Facebook的Prophet模型分解每家店的销售趋势:

  • Trend:长期趋势项
  • Weekly:周周期项
  • Yearly:年周期项
from prophet import Prophet def decompose_store(store_data): m = Prophet(weekly_seasonality=True, yearly_seasonality=True) m.fit(store_data.rename(columns={'Date':'ds', 'Sales':'y'})) components = m.predict(store_data) return components[['trend', 'weekly', 'yearly']]

6. 特征筛选与模型优化

6.1 Null Importance特征筛选

面对300+特征,我采用Null Importance方法筛选:

  1. 用全部特征训练LightGBM模型记录特征重要性
  2. 随机打乱标签y,重复训练100次
  3. 保留真实重要性 > 打乱后重要性75分位数的特征
from lightgbm import LGBMRegressor def null_importance(X, y, n_runs=100): model = LGBMRegressor() model.fit(X, y) real_imp = pd.DataFrame(model.feature_importances_, index=X.columns) null_imp = pd.DataFrame() for _ in range(n_runs): y_shuffled = y.sample(frac=1) model.fit(X, y_shuffled) imp = pd.DataFrame(model.feature_importances_, index=X.columns) null_imp = pd.concat([null_imp, imp], axis=1) return real_imp, null_imp

6.2 模型融合策略

最终方案融合了三个模型:

  1. XGBoost:处理数值型特征
  2. LightGBM:高效处理类别特征
  3. CatBoost:自动处理缺失值

融合时采用加权平均,权重通过交叉验证确定:

weights = { 'xgb': 0.4, 'lgb': 0.35, 'cat': 0.25 } final_pred = (weights['xgb'] * xgb_pred + weights['lgb'] * lgb_pred + weights['cat'] * cat_pred)

7. 比赛经验与实用建议

通过这次比赛,我总结了几个关键经验:

  1. 业务理解优先:花时间研究德国零售业特点,比调参更重要
  2. 可视化驱动分析:每个特征生成时都绘制其与Sales的关系图
  3. 稳健的验证策略:采用时间序列交叉验证(TimeSeriesSplit)
  4. 避免过度工程:最终只用到了70个核心特征

对于想尝试该赛题的朋友,建议从简化版开始:

  1. 先只用10家门店数据
  2. 实现基础时间特征+门店属性
  3. 逐步添加促销/节假日特征
  4. 最后扩展至全量数据

零售预测的魅力在于,每个业务决策都能反映在数据中。这次实战让我深刻体会到:好的特征工程,就是把业务语言翻译成模型能理解的数据语言。

http://www.jsqmd.com/news/995464/

相关文章:

  • 数字手写的革命:Rnote如何让你的创意自由流动
  • 2026年深圳宠物店推荐指南:如何选择靠谱的犬舍猫舍?实测全国连锁与本地服务对比 - 优质品牌商家
  • 2026年可调谐激光光源选购指南:从技术参数到实际案例的深度解析 - 优质品牌商家
  • 2026导轨油工厂实力排行榜:昭和润滑油领衔,导轨油、不锈钢切削油、走心机切削油、抗磨液压油全品类润滑精密机床用油优选指南 - 变量人生001
  • MPC8349EA时钟子系统配置:从PLL原理到实战调试与热设计
  • ElevenClock终极解决方案:完全掌控Windows 11任务栏时钟的完整指南
  • 2026年鹿城区空调维修对外电话及服务参考 - 品牌排行榜
  • 别再硬啃NP-hard问题了!用拉格朗日松弛把复杂约束‘打包’进目标函数,Python手把手教你算下界
  • 2026苏州新房老房装修厂家推荐榜 - 品牌排行榜
  • 2026年免费视频文字提取工具教程:哪个好用推荐
  • 2026年四川LED显示屏市场观察:透明屏与小间距成增长主力,供应商选择指南 - 优质品牌商家
  • 谷歌SEO教程: 新网站如何做SEO规划?|零流量的网站如何通过SEO快速获取流量?|独立站运营
  • Uni-app移动端视频监控卡顿?试试用海康H5player接入WebSocket流(附完整代码)
  • 【鸿蒙PC】libuv应用集成:AtomCode驱动NAPI全流程
  • 2026蓝牙Mesh照明品牌:智慧照明技术创新与应用趋势 - 品牌排行榜
  • 寄大件哪家物流最便宜最好?2026实测对比+省钱技巧 - 快递物流资讯
  • MSC8102 DSP硬件设计实战:电源、时钟与PCB布局要点解析
  • 大模型应用灰度发布:从影子测试到效果回归的工程实践
  • Prodigy标注全流程实战包:本地二分类起步,Wikipedia数据接入,EC2服务部署+Dropbox自动备份
  • 【课程设计/毕业设计】融合人工智能技术的 Android 历史仿真交互平台研发基于android的ai历史模拟交互系统的设计与实现【附源码、数据库、万字文档】
  • 0 胶 0 醛 + 25 年质保,久盛地板如何成为纯实木地暖地板领军品牌 - 博客万
  • MPC8536E SGMII接口电气特性详解:从DC/AC参数到硬件设计与调试实战
  • MPC8535E接口电气特性实战:JTAG、SATA与I2C设计指南
  • 2026免费在线抠图工具推荐指南:保姆级教程与对比
  • 【实战指南】EWM RF框架深度解析:从ITS扫描枪集成到后台精细化配置
  • NAFE71388高集成度AFE芯片:工业数据采集的精度与灵活性解决方案
  • 2026上海幼儿园和早教机构选择:聚焦能力培养与科学启蒙 - 品牌排行榜
  • 上海杨浦区名包回收+名表回收价格高?2026年这几家正规门店值得去 - 沪上贵金属口碑推荐官
  • Linux平台可交互生态演化模拟器:C语言实现,含遗传进化、Boids群集与OpenGL实时可视化
  • MPC8548E PCI/PCI-X与SerDes接口电气规格实战解析