共计 1967 个字符,预计需要花费 5 分钟才能阅读完成。
背景与问题
鸢尾花分类是机器学习入门的经典案例,但传统单一决策树在实际应用中存在明显缺陷。当我在实际项目中使用单棵决策树时,发现了两个典型问题:

- 模型容易过拟合:即使对训练数据达到 100% 准确率,测试集表现可能骤降
- 预测结果不稳定:数据微小变动会导致完全不同的树结构
而鸢尾花数据集本身的特点也带来挑战:
- 特征维度低(仅 4 个),需要高效的特征组合方式
- 样本量小(150 条),限制了复杂模型的发挥空间
- 类别完全平衡(各 50 条),可能掩盖模型对少数类的识别问题
集成学习方案选择
通过实验对比两种主流集成方法:
Bagging 代表:随机森林 (Random Forest)
- 核心思想:并行训练多棵差异化的决策树,通过投票降低方差
- 优势:
- 内置特征随机选择,增强多样性
- 天然抗过拟合
Boosting 代表:AdaBoost
- 核心思想:序列化训练,后续树专注修正前序树的错误
- 优势:
- 对难样本的识别能力更强
- 通常需要更少的基学习器
小数据集选择建议 :优先尝试随机森林,因其对参数敏感度低且训练更快。当发现某些类别识别率持续偏低时,可换用 AdaBoost。
完整实现代码
# 环境准备
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
import matplotlib.pyplot as plt
import seaborn as sns
# 数据加载与分割
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.3, random_state=42)
# 随机森林实现
rf = RandomForestClassifier(
n_estimators=100, # 树的数量,后续会讨论如何选择
max_depth=3, # 控制单棵树复杂度
random_state=42
)
rf.fit(X_train, y_train)
# 评估与可视化
print("随机森林性能:")
print(classification_report(y_test, rf.predict(X_test)))
# 特征重要性
feat_importances = pd.Series(rf.feature_importances_, index=iris.feature_names)
feat_importances.nlargest(4).plot(kind='barh')
plt.title('Feature Importance')
plt.show()
关键参数优化
通过网格搜索寻找最佳参数组合:
- n_estimators(树的数量):
- 通常 50-200 足够,继续增加收益递减
-
可用学习曲线观察准确率变化
-
max_depth(树的最大深度):
- 小数据集建议 3 - 5 层
- 过深会导致过拟合(观察训练 / 测试集差距)
# 参数影响示例
n_estimators_range = range(10, 200, 10)
scores = []
for n in n_estimators_range:
model = RandomForestClassifier(n_estimators=n, random_state=42)
model.fit(X_train, y_train)
scores.append(model.score(X_test, y_test))
plt.plot(n_estimators_range, scores)
plt.xlabel('Number of Trees')
plt.ylabel('Accuracy')
plt.show()
实践中的避坑指南
- 类别不平衡处理 :
- 虽然本数据集平衡,但实际项目中可通过 class_weight 参数调整
-
对 AdaBoost 使用 SAMME.R 算法提升少数类识别
-
特征缩放误区 :
- 决策树不需要特征标准化!
-
但同类量纲有助于解释特征重要性
-
交叉验证要点 :
- 小数据集建议用 5 折以上
- 确保每折都包含所有类别(StratifiedKFold)
延伸思考
- 如何将本方案迁移到其他分类任务?
- 当特征数量远大于样本量时(如基因数据),需要调整哪些策略?
- 为什么说集成学习在在线学习场景中面临挑战?
通过这个项目,我深刻体会到:对于小型结构化数据集,合理调参的随机森林往往能提供『开箱即用』的优秀表现。下次遇到类似问题时,不妨先从这个 baseline 开始迭代。
正文完
发表至: 未分类
近三天内
