1. 项目背景与数据概览
Rossmann是欧洲第二大药妆连锁品牌,在7个国家拥有超过3000家门店。销售预测对零售行业至关重要,直接影响库存管理、人员排班和促销策略。这个项目将带大家完整走一遍零售销量预测的实战流程,从原始数据加载到最终模型训练与分析。
我处理过多个零售行业的预测项目,发现Rossmann数据集有几个典型特点:一是存在门店间的区域差异,二是促销活动对销量影响显著,三是节假日效应明显。这些特性使得它成为练习时间序列预测的绝佳素材。
2. 数据加载与初步探索
2.1 数据文件结构解析
Rossmann官方数据集通常包含两个核心文件:
- train.csv:2013-2015年的每日销售记录
- store.csv:各门店的属性信息
用pandas加载时要注意日期列的解析:
import pandas as pd # 读取时指定日期解析器 train = pd.read_csv('train.csv', parse_dates=['Date']) store = pd.read_csv('store.csv') # 检查内存占用 print(f"训练集占用内存: {train.memory_usage().sum()/1024**2:.2f} MB")2.2 数据质量检查清单
在正式分析前必须完成的检查项:
- 缺失值检测:用
df.isnull().sum()逐列检查 - 异常值筛查:重点检查Sales为0或负值的记录
- 时间跨度验证:确认日期是否连续
- 门店覆盖检查:确保所有门店在store表中都有对应信息
经验提示:零售数据常见问题是促销期间的销量记录缺失,这需要特别关注
3. 特征工程深度解析
3.1 时间特征构造
时间特征是零售预测的核心,至少要包含:
# 基础时间特征 train['Year'] = train['Date'].dt.year train['Month'] = train['Date'].dt.month train['Week'] = train['Date'].dt.isocalendar().week train['DayOfWeek'] = train['Date'].dt.dayofweek train['DayOfYear'] = train['Date'].dt.dayofyear # 高级时间特征 train['IsMonthStart'] = train['Date'].dt.is_month_start.astype(int) train['IsMonthEnd'] = train['Date'].dt.is_month_end.astype(int)3.2 门店特征融合
store表包含的关键信息需要与销售数据关联:
# 合并数据集 full_data = pd.merge(train, store, on='Store', how='left') # 处理分类变量 store_types = {'a':1, 'b':2, 'c':3, 'd':4} full_data['StoreType'] = full_data['StoreType'].map(store_types)3.3 促销效应建模
促销活动的影响是非线性的,建议采用:
- 促销前效应:提前3天的销量变化
- 促销后效应:结束后1周的销量衰减
- 促销组合特征:当促销与节假日重叠时的特殊标记
4. 数据预处理关键步骤
4.1 异常值处理策略
对于零销量的特殊情况,需要区分:
- 门店歇业(合法零值)
- 数据记录错误(需修正)
处理代码示例:
# 确认歇业记录 closed_stores = full_data[full_data['Open']==0] valid_zero = closed_stores[closed_stores['Sales']==0] # 处理异常零值 full_data = full_data[~((full_data['Open']==1) & (full_data['Sales']==0))]4.2 缺失值填补技巧
不同特征的缺失值应采用不同策略:
- 竞争距离:用中位数填补+新增缺失标记
- 促销间隔:用业务默认值填补
- 天气数据:用最近门店的值插补
5. 模型训练与验证
5.1 基准模型选择
对于零售预测,建议从这些模型开始:
- XGBoost:处理混合特征效果最佳
- LightGBM:训练速度有优势
- Prophet:擅长捕捉季节效应
from sklearn.model_selection import TimeSeriesSplit from xgboost import XGBRegressor # 时间序列交叉验证 tscv = TimeSeriesSplit(n_splits=5) model = XGBRegressor(objective='reg:squarederror', n_estimators=1000) for train_idx, test_idx in tscv.split(X): X_train, X_test = X.iloc[train_idx], X.iloc[test_idx] y_train, y_test = y.iloc[train_idx], y.iloc[test_idx] model.fit(X_train, y_train) # 评估代码...5.2 特征重要性分析
通过SHAP值深入理解模型:
import shap explainer = shap.TreeExplainer(model) shap_values = explainer.shap_values(X_test) # 可视化 shap.summary_plot(shap_values, X_test)6. 实战中的经验教训
节假日处理陷阱:不同地区的节假日影响差异很大,需要按国家/地区单独处理
门店开业时长效应:新开门店的前3个月销量模式与稳定期完全不同
促销疲劳现象:连续促销的效果会递减,这个非线性关系需要特别建模
天气数据的使用:降雨量对销量的影响存在2-3天的滞后效应
关键建议:先用6个月的数据快速验证特征工程方案,再扩展到全量数据
7. 性能优化技巧
- 内存优化:将分类变量转换为category类型
cat_cols = ['Store', 'DayOfWeek', 'Promo'] full_data[cat_cols] = full_data[cat_cols].astype('category')- 并行处理:利用joblib加速特征计算
from joblib import Parallel, delayed def compute_feature(df): # 特征计算逻辑 return result results = Parallel(n_jobs=4)(delayed(compute_feature)(group) for _, group in full_data.groupby('Store'))- 增量训练:对于大规模数据,使用
partial_fit方法
8. 分析报告的关键要素
完整的销售预测报告应包含:
- 门店级预测准确度分布
- 误差的时间分布模式
- 重要特征贡献度排名
- 特殊事件的影响量化
- 不同产品类别的预测差异
我通常会使用Plotly创建交互式报告,方便业务方探索不同维度的预测结果。比如用热力图展示每周各天的预测误差模式,能直观发现周几的系统性预测偏差。