共计 3254 个字符,预计需要花费 9 分钟才能阅读完成。
背景介绍
鸢尾花数据集是机器学习领域的经典数据集,包含三种鸢尾花的 150 个样本,每个样本有 4 个特征(萼片长度、萼片宽度、花瓣长度、花瓣宽度)。这个数据集的特点是特征维度低、样本量适中,非常适合初学者练习分类算法。

虽然数据集看起来简单,但分类任务仍面临一些挑战:
- 不同种类的特征分布有重叠区域
- 单个决策树容易过拟合
- 需要找到区分 versicolor 和 virginica 这两个相似类别的有效方法
技术对比:单决策树 vs 集成方法
单决策树的优缺点
- 优点:
- 易于理解和解释
- 计算速度快
-
不需要特征缩放
-
缺点:
- 容易过拟合
- 对数据微小变化敏感
- 预测准确率通常不如集成方法
集成方法的优势
- Bagging(如 Random Forest):
- 通过自助采样降低方差
- 并行训练多个树
-
天然抗过拟合
-
Boosting(如 AdaBoost):
- 顺序训练弱学习器
- 聚焦难分类样本
- 通常比 Bagging 准确率更高
完整实现
下面是使用 scikit-learn 的完整代码实现:
# 导入必要库
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 accuracy_score
import matplotlib.pyplot as plt
import numpy as np
# 加载数据
iris = load_iris()
X, y = iris.data, iris.target
# 划分训练测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 单决策树
single_tree = DecisionTreeClassifier(max_depth=3, random_state=42)
single_tree.fit(X_train, y_train)
single_pred = single_tree.predict(X_test)
print(f"Single Tree Accuracy: {accuracy_score(y_test, single_pred):.2f}")
# 随机森林
rf = RandomForestClassifier(n_estimators=100, max_depth=3, random_state=42)
rf.fit(X_train, y_train)
rf_pred = rf.predict(X_test)
print(f"Random Forest Accuracy: {accuracy_score(y_test, rf_pred):.2f}")
# AdaBoost
ada = AdaBoostClassifier(DecisionTreeClassifier(max_depth=1),
n_estimators=50,
learning_rate=1.0,
random_state=42
)
ada.fit(X_train, y_train)
ada_pred = ada.predict(X_test)
print(f"AdaBoost Accuracy: {accuracy_score(y_test, ada_pred):.2f}")
参数调优指南
关键参数解析
- max_depth:
- 控制树的深度
- 值太小会欠拟合,太大会过拟合
-
建议从 3 开始尝试
-
n_estimators:
- 集成中树的数量
- 越多效果通常越好,但计算成本增加
-
随机森林建议 100-200,AdaBoost 建议 50-100
-
min_samples_split:
- 节点分裂所需最小样本数
- 防止过拟合
- 常用值 2 -10
调优示例代码
from sklearn.model_selection import GridSearchCV
# 定义参数网格
param_grid = {'max_depth': [2, 3, 5, 7],
'n_estimators': [50, 100, 200],
'min_samples_split': [2, 5, 10]
}
# 网格搜索
grid_search = GridSearchCV(RandomForestClassifier(random_state=42),
param_grid,
cv=5,
n_jobs=-1
)
grid_search.fit(X_train, y_train)
print(f"Best params: {grid_search.best_params_}")
print(f"Best score: {grid_search.best_score_:.2f}")
避坑指南
常见问题及解决方案
- 数据泄露:
- 错误:在预处理时对整个数据集进行标准化
-
正确:只在训练集上拟合 scaler,然后转换测试集
-
过拟合:
- 现象:训练集准确率高,测试集低
-
解决:减小 max_depth,增加 min_samples_split
-
类别不平衡:
- 现象:少数类识别率低
-
解决:使用 class_weight=’balanced’
-
随机性导致结果不稳定:
- 现象:每次运行结果不同
- 解决:设置 random_state 固定随机种子
性能分析与可视化
准确率对比
# 模型比较
models = {
'Single Tree': single_tree,
'Random Forest': rf,
'AdaBoost': ada
}
for name, model in models.items():
pred = model.predict(X_test)
print(f"{name} Accuracy: {accuracy_score(y_test, pred):.2f}")
决策边界可视化
# 可视化函数
def plot_decision_boundary(model, X, y, title):
# 只使用前两个特征
X = X[:, :2]
model.fit(X, y)
# 创建网格
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
np.arange(y_min, y_max, 0.02))
# 预测
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
# 绘图
plt.contourf(xx, yy, Z, alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, edgecolor='k')
plt.title(title)
plt.xlabel(iris.feature_names[0])
plt.ylabel(iris.feature_names[1])
plt.show()
# 绘制比较
plot_decision_boundary(single_tree, X_train, y_train, "Single Tree")
plot_decision_boundary(rf, X_train, y_train, "Random Forest")
plot_decision_boundary(ada, X_train, y_train, "AdaBoost")
延伸思考
- 如果数据集特征更多(比如几十个),哪些集成方法会表现更好?为什么?
- 对于类别极度不平衡的数据集(如欺诈检测),如何调整集成学习方法?
- 除了准确率,还有哪些指标更适合评估多分类问题?如何用 scikit-learn 计算这些指标?
通过这个实战练习,我们可以看到集成学习方法相比单决策树确实能够提高分类准确率,尤其是在区分相似类别时。建议读者尝试调整不同参数,观察模型性能变化,并扩展到其他数据集上应用这些技术。
正文完
发表至: 未分类
近三天内
