Kaggle 肥胖预测赛:4模型融合实战,加权法提升准确率至 0.916
Kaggle肥胖预测竞赛:四模型加权融合实战与性能优化策略
在数据科学竞赛中,单一模型往往难以捕捉数据中的所有复杂模式。本文将深入探讨如何通过随机森林、LightGBM、XGBoost和CatBoost四种模型的加权融合,在Kaggle肥胖风险预测竞赛中实现0.916的准确率。不同于基础教程,我们将聚焦于模型融合的实战细节、权重优化方法论以及避免过拟合的高级技巧,为中级Kaggle玩家提供可直接复用的进阶策略。
1. 竞赛背景与数据特性解析
肥胖风险预测是典型的多分类问题,目标是将个体分为7个体重类别(从体重不足到III级肥胖)。原始数据集包含18个特征,涵盖人口统计、饮食习惯、运动频率等多个维度。通过EDA分析,我们发现几个关键洞察:
- 性别与肥胖类型的强关联:Obesity_Type_II患者100%为男性,而Obesity_Type_III患者99%为女性
- BMI的隐含价值:虽然数据集中未直接提供BMI,但通过Height和Weight计算的BMI与目标变量相关性达0.89
- 类别不平衡问题:某些类别(如Obesity_Type_II)样本量仅为其他类别的1/5
# BMI特征工程代码示例 def extract_features(df): df['BMI'] = df['Weight']/(df['Height']**2) return df # 类别分布可视化 plt.figure(figsize=(10,6)) sns.countplot(x='NObeyesdad', data=train, order=train['NObeyesdad'].value_counts().index) plt.xticks(rotation=45) plt.title('Class Distribution')提示:在融合模型中,类别不平衡问题需要通过加权损失函数或过采样技术处理,否则模型会偏向多数类。
2. 基础模型构建与调优
2.1 随机森林的定制化改进
传统随机森林直接应用于该数据集只能达到0.897的准确率。我们通过以下改进提升至0.906:
- 类别权重调整:使用
class_weight="balanced_subsample" - 嵌入编码优化:采用MEstimateEncoder处理分类变量
- 特征选择:基于置换重要性剔除低贡献特征
from sklearn.ensemble import RandomForestClassifier from category_encoders import MEstimateEncoder rfc_pipeline = make_pipeline( MEstimateEncoder(cols=categorical_cols), RandomForestClassifier(n_estimators=500, max_depth=10, class_weight="balanced_subsample", random_state=42) )2.2 LightGBM的超参数优化
使用Optuna进行50轮贝叶斯优化,关键参数空间设计如下:
| 参数 | 搜索范围 | 最优值 |
|---|---|---|
| learning_rate | [0.001, 0.1] | 0.031 |
| max_depth | [2, 20] | 10 |
| lambda_l1 | [0.1, 20] | 0.0097 |
| lambda_l2 | [0.1, 20] | 0.0402 |
| num_leaves | [10, 1000] | 87 |
import optuna from lightgbm import LGBMClassifier def objective(trial): params = { 'learning_rate': trial.suggest_float('learning_rate', 0.001, 0.1, log=True), 'max_depth': trial.suggest_int('max_depth', 2, 20), 'lambda_l1': trial.suggest_float('lambda_l1', 0.1, 20, log=True), 'lambda_l2': trial.suggest_float('lambda_l2', 0.1, 20, log=True) } model = LGBMClassifier(**params) score = cross_val_score(model, X, y, scoring='accuracy').mean() return score study = optuna.create_study(direction='maximize') study.optimize(objective, n_trials=50)2.3 XGBoost与CatBoost的对比实验
两种梯度提升框架在相同数据上表现出不同特性:
XGBoost优势:
- 对数值型特征处理更鲁棒
- GPU加速效率更高(比CatBoost快约15%)
- 自定义损失函数更灵活
CatBoost优势:
- 自动处理类别变量,无需单独编码
- 对超参数敏感性较低
- 内置对抗过拟合机制
我们通过早停策略(early stopping)和动态学习率衰减优化两者表现:
# XGBoost早停实现 xgb_params = { 'eval_metric': 'mlogloss', 'early_stopping_rounds': 50, 'learning_rate': 0.05 } xgb.fit(X_train, y_train, eval_set=[(X_val, y_val)], verbose=10)3. 模型融合策略深度剖析
3.1 加权融合的数学原理
加权融合的核心公式为:
$$ P_{final}(y|x) = \sum_{i=1}^{n} w_i \cdot P_i(y|x) $$
其中$w_i$为第i个模型的权重,$\sum w_i = 1$。我们通过网格搜索确定最优权重组合:
| 模型 | 权重范围 | 最优权重 |
|---|---|---|
| RandomForest | [0, 0.4] | 0.1 |
| LightGBM | [0.2, 0.6] | 0.5 |
| XGBoost | [0.1, 0.5] | 0.3 |
| CatBoost | [0, 0.3] | 0.1 |
3.2 权重优化的实战代码
from itertools import product # 定义权重搜索空间 weight_space = { 'rfc': np.linspace(0, 0.4, 5), 'lgb': np.linspace(0.2, 0.6, 5), 'xgb': np.linspace(0.1, 0.5, 5), 'cat': np.linspace(0, 0.3, 4) } best_score = 0 best_weights = {} # 网格搜索最优组合 for w_rfc, w_lgb, w_xgb, w_cat in product(*weight_space.values()): total = w_rfc + w_lgb + w_xgb + w_cat if abs(total - 1.0) > 0.01: # 权重和≈1 continue # 加权预测 weighted_proba = (w_rfc*rfc_pred + w_lgb*lgb_pred + w_xgb*xgb_pred + w_cat*cat_pred) final_pred = weighted_proba.argmax(axis=1) score = accuracy_score(y_val, final_pred) if score > best_score: best_score = score best_weights = {'rfc':w_rfc, 'lgb':w_lgb, 'xgb':w_xgb, 'cat':w_cat} print(f"Best Weights: {best_weights}, Score: {best_score:.4f}")3.3 融合模型的性能对比
我们测试了五种权重组合的验证集表现:
| 组合编号 | RFC权重 | LGB权重 | XGB权重 | CAT权重 | 准确率 |
|---|---|---|---|---|---|
| 1 | 0.0 | 0.6 | 0.3 | 0.1 | 0.912 |
| 2 | 0.1 | 0.5 | 0.3 | 0.1 | 0.916 |
| 3 | 0.2 | 0.4 | 0.3 | 0.1 | 0.914 |
| 4 | 0.1 | 0.4 | 0.4 | 0.1 | 0.915 |
| 5 | 0.0 | 0.7 | 0.2 | 0.1 | 0.911 |
注意:实际应用中需用交叉验证评估权重稳定性,避免选择在特定fold过拟合的组合
4. 高级优化技巧与避坑指南
4.1 避免融合中的常见陷阱
- 相关性过高的模型:如果两个模型的预测结果相关系数>0.9,融合收益有限。建议先计算模型间的Spearman相关系数:
corr_matrix = pd.DataFrame({ 'RFC': rfc_pred.argmax(axis=1), 'LGB': lgb_pred.argmax(axis=1), 'XGB': xgb_pred.argmax(axis=1) }).corr(method='spearman')- 测试集泄露:在确定权重时,必须使用独立的验证集而非测试集
- 计算资源平衡:XGBoost和CatBoost的GPU实现可加速训练,但需注意显存限制
4.2 融合后的模型诊断
通过混淆矩阵分析发现,融合模型在Obesity_Type_II和Overweight_Level_II这两个最容易混淆的类别上表现提升最明显:
Predicted_0 Predicted_1 ... Predicted_6 Actual_0 0.94 0.02 ... 0.00 Actual_1 0.01 0.91 ... 0.00 ... Actual_6 0.00 0.00 ... 0.954.3 替代融合方案对比
除加权融合外,我们还实验了其他方法:
- Stacking:用逻辑回归作为元模型,但效果略差于加权法(0.913 vs 0.916)
- Voting:硬投票准确率仅0.902,软投票达0.914
- Blending:需要额外holdout集,在小数据场景不适用
最终选择加权融合因其:
- 实现简单
- 可解释性强
- 计算效率高
5. 完整实现与部署建议
5.1 端到端实现代码
# 模型训练 models = { 'rfc': RandomForestClassifier(**rfc_params), 'lgb': LGBMClassifier(**lgb_params), 'xgb': XGBClassifier(**xgb_params), 'cat': CatBoostClassifier(**cat_params) } # 存储各模型的OOF预测 oof_preds = {} for name, model in models.items(): model.fit(X_train, y_train) oof_preds[name] = model.predict_proba(X_val) # 加权融合 weights = {'rfc':0.1, 'lgb':0.5, 'xgb':0.3, 'cat':0.1} final_pred = np.zeros_like(oof_preds['rfc']) for name, pred in oof_preds.items(): final_pred += weights[name] * pred # 结果保存 submission = pd.DataFrame({ 'id': test_ids, 'NObeyesdad': final_pred.argmax(axis=1) }) submission.to_csv('submission.csv', index=False)5.2 实际应用建议
- 动态权重调整:当新增数据导致分布变化时,应重新优化权重
- 模型监控:部署后持续跟踪各模型的预测分布变化
- 资源优化:在实时性要求高的场景,可只保留效果最好的1-2个模型
在医疗健康等高风险领域,建议增加不确定性估计:当不同模型的预测差异较大时(如熵值>1.5),应标记为需要人工复核的案例。