共计 2777 个字符,预计需要花费 7 分钟才能阅读完成。
赛题背景与数据特点分析
2025 泰迪杯数据挖掘挑战赛 B 题聚焦于一个典型的商业预测问题,要求参赛者基于历史销售数据、用户行为日志和外部环境因素,预测未来某段时间内的产品销量。数据集呈现以下显著特点:

- 多源异构数据 :包含结构化交易记录(CSV)、非结构化的用户评论(JSON)以及天气等外部 API 数据
- 时空双重维度 :数据同时具有时间序列特性(日粒度)和空间维度(区域门店分布)
- 严重类别不平衡 :爆款商品与长尾商品的销量差异达 3 个数量级
- 数据质量问题突出 :约 15% 的字段存在缺失,部分传感器数据存在明显异常波动
技术选型对比
针对上述特点,我们对关键技术方案进行了对比评估:
- 缺失值处理 :
- 简单删除法(适用于缺失率 <5% 的非关键字段)
- 多重插补(MICE)VS 均值 / 中位数填充(后者计算效率更高)
-
最终选择基于随机森林的缺失值预测(对非线性关系建模更准确)
-
特征工程 :
- 传统统计特征(移动平均、同比环比)VS 深度学习自动特征提取(后者需要足够数据量支撑)
-
最终采用混合策略:人工构造业务特征 + AutoFE 工具辅助
-
建模算法 :
- XGBoost:更适合处理结构化特征
- LightGBM:训练速度更快,内存占用更低
- 最终选择 LightGBM 作为基线模型,配合 CatBoost 处理类别型变量
核心实现细节
数据清洗流程
-
缺失值处理 :
# 使用随机森林预测缺失的单价字段 from sklearn.ensemble import RandomForestRegressor def impute_missing_values(df, target_col): # 分割完整数据与缺失数据 known = df[df[target_col].notnull()] unknown = df[df[target_col].isnull()] # 准备特征(排除目标列和其他高缺失率列)features = [col for col in df.columns if col not in [target_col, 'high_missing_column']] # 训练预测模型 rf = RandomForestRegressor(n_estimators=100, random_state=42) rf.fit(known[features], known[target_col]) # 预测并填补缺失值 predicted = rf.predict(unknown[features]) df.loc[df[target_col].isnull(), target_col] = predicted return df -
异常值检测 :
- 使用 IQR 方法识别数值型异常
- 对文本数据采用规则过滤(如评论长度 >500 字符视为垃圾内容)
特征工程方法
- 时序特征构造 :
- 滑动窗口统计量(7 天 /30 天均值)
- 日期特性(星期几、是否节假日)
-
季节分解(STL)得到的趋势 / 周期分量
-
文本特征提取 :
# 使用 TF-IDF 提取评论关键词 from sklearn.feature_extraction.text import TfidfVectorizer tfidf = TfidfVectorizer(max_features=100, stop_words='english') comment_features = tfidf.fit_transform(df['user_comments']) df = pd.concat([df, pd.DataFrame(comment_features.toarray())], axis=1) -
交叉特征生成 :
- 商品类别 × 促销标志
- 天气情况 × 门店位置
模型构建
采用分层抽样解决类别不平衡问题,LightGBM 关键参数配置:
params = {
'boosting_type': 'gbdt',
'objective': 'regression',
'metric': 'rmse',
'num_leaves': 31,
'learning_rate': 0.05,
'feature_fraction': 0.9,
'bagging_fraction': 0.8,
'bagging_freq': 5,
'verbose': 0,
'min_data_in_leaf': 20 # 防止过拟合
}
性能优化
- 特征选择 :
- 通过 SHAP 值评估特征重要性
-
递归特征消除(RFE)保留 Top50% 特征
-
超参数调优 :
# 使用 Optuna 进行贝叶斯优化 import optuna def objective(trial): params = {'num_leaves': trial.suggest_int('num_leaves', 20, 60), 'max_depth': trial.suggest_int('max_depth', 3, 12), 'min_child_samples': trial.suggest_int('min_child_samples', 10, 50), 'learning_rate': trial.suggest_float('learning_rate', 0.01, 0.1) } model = LGBMRegressor(**params) scores = cross_val_score(model, X, y, cv=5, scoring='neg_mean_squared_error') return np.mean(scores) study = optuna.create_study(direction='maximize') study.optimize(objective, n_trials=100)
避坑指南
- 时间泄漏问题 :
- 严禁使用未来数据(如用 2 月的统计量预测 1 月销量)
-
建议采用时间序列交叉验证(TimeSeriesSplit)
-
评估指标误解 :
- 比赛使用 RMSLE 而非 RMSE,需对预测值做 log1p 变换
-
自定义评估函数示例:
def rmsle(y_true, y_pred): y_pred = np.clip(y_pred, 0, None) # 确保非负 return np.sqrt(np.mean(np.power(np.log1p(y_true) - np.log1p(y_pred), 2))) -
内存优化 :
- 将 category 类型字段手动转换为 pandas 的 category 类型
- 对数值列使用 astype(np.float32) 降低精度
延伸思考
- 进阶方向 :
- 尝试时序深度学习模型(如 N -BEATS、TFT)
-
构建异构模型融合(RNN 处理时序 + GBDT 处理表格数据)
-
业务迁移 :
- 将比赛方案适配到零售行业的库存优化系统
- 考虑实时预测场景下的模型更新策略
结语
通过本次比赛实践,我们系统性地掌握了从原始数据到预测模型的完整 pipeline。特别值得注意的是,数据挖掘竞赛与实际业务场景的核心差异在于:比赛追求单一指标最大化,而业务场景更需要模型的稳定性和可解释性。建议读者在后续实践中,尝试将本文技术方案应用到自己的业务数据中,并持续关注模型在生产环境中的表现。
正文完
