在R的gbm包中用adaboost做泰坦尼克预测遇异常值如何处理?
首先,我来拆解你遇到的两个核心问题:为什么预测值全接近1,以及如何得到正确的0/1分类结果。
一、预测值全接近1的可能原因
1. Adaboost分布的输出不是概率
你使用了distribution="adaboost",这是GBM实现Adaboost算法的模式,它采用指数损失函数。此时predict(..., type="response")返回的不是0-1之间的概率,而是样本属于正类(Survived=1)的分类得分。这个得分的正负对应分类(正得分对应1,负得分对应0),但数值本身没有概率意义——你看到的接近1的数值其实是模型给出的极端偏向正类的得分,不是概率。
2. 模型过拟合或参数设置不当
你的参数shrinkage=0.005非常小,同时设置了n.trees=500,这可能导致模型在训练集上过度拟合,尤其是如果interaction.depth=3对于你的数据集来说复杂度偏高的话。过拟合会让模型过度贴合训练集的噪声,最终偏向预测多数类(如果训练集中Survived=1的占比稍高,就可能全预测为1)。
3. 训练集标签分布极端
先快速检查训练集的Survived分布:
table(train$Survived)
如果其中某一类的占比超过90%(比如几乎全是Survived=1),模型会倾向于预测占比高的类别,这也会导致所有预测值偏向1。不过泰坦尼克数据集通常存活占比在38%左右,这个可能性较低,但还是建议排查。
二、如何得到正确的0/1二分类预测
针对你的情况,有两种解决方案:
方案1:基于Adaboost得分做分类
既然Adaboost的输出是得分,你可以以0为阈值,将得分大于0的样本预测为1,小于等于0的预测为0:
# 将得分转为0/1分类 pred_class = ifelse(predd.gbm > 0, 1, 0)
方案2:改用伯努利分布(推荐)
如果你希望得到0-1之间的概率值,更建议使用distribution="bernoulli"(二分类的对数损失),这是GBM做二分类任务的标准设置,此时type="response"返回的就是概率:
# 重新训练模型 fit.gbm = gbm(Survived ~ Age + Fare + SibSp + Parch + Pclass + Titles + Sex + Embarked, data=train, distribution = "bernoulli", # 改用伯努利分布 n.trees=500, interaction.depth=3, shrinkage=0.005) # 得到概率预测 pred_prob = predict(fit.gbm, newdata=train, type="response", n.trees=500) # 以0.5为阈值转为0/1分类(也可以根据需求调整阈值,比如不平衡数据集) pred_class = ifelse(pred_prob > 0.5, 1, 0)
额外建议:优化模型参数
如果改用伯努利分布后还是有异常,建议调整参数:
- 先降低
n.trees(比如从100开始尝试),同时调大shrinkage(比如0.01或0.1),避免过拟合; - 用
gbm.perf(fit.gbm)来确定最优的树数量,防止使用过多的树导致过拟合; - 检查特征是否有缺失值或异常值(比如Age的缺失),这也会影响模型性能。
内容的提问来源于stack exchange,提问作者Gravity Boy

