决策树分类实战:Sklearn API 调参 5 要点,泰坦尼克号预测准确率 0.82
决策树分类实战:Sklearn API 调参 5 要点,泰坦尼克号预测准确率 0.82
当面对泰坦尼克号乘客生存预测这样的分类任务时,决策树算法因其直观的解释性和较低的计算成本成为许多数据科学家的首选。但要让模型真正发挥潜力,关键在于理解如何通过参数调整来平衡过拟合与欠拟合。本文将深入剖析Scikit-learn中决策树分类器的5个核心参数,并通过完整的代码示例展示如何系统性地优化模型性能。
1. 决策树调参的核心逻辑
决策树算法通过递归地划分特征空间来实现分类,但简单的实现往往会导致模型过于复杂。Scikit-learn的DecisionTreeClassifier提供了12个可调参数,其中以下5个对模型性能影响最为显著:
- max_depth:控制树的垂直复杂度
- min_samples_split:限制节点继续分裂的最小样本数
- min_samples_leaf:设定叶节点的最小样本容量
- max_features:限制每次分裂考虑的特征数量
- criterion:选择分裂质量的衡量标准
这些参数本质上都在做同一件事:控制模型的复杂度。过大的树会记住训练数据中的噪声,而过小的树则无法捕捉数据中的关键模式。理想的参数组合应该使模型在测试集上达到最佳泛化性能。
实践提示:调参时应先控制树的深度(max_depth),再调整叶节点相关参数(min_samples_split/min_samples_leaf),最后考虑特征采样策略(max_features)
2. 泰坦尼克号数据集预处理
在开始调参前,我们需要准备高质量的数据。原始泰坦尼克号数据集包含以下关键特征:
import pandas as pd from sklearn.model_selection import train_test_split # 加载数据 titanic = pd.read_csv('titanic.csv') features = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked'] X = titanic[features] y = titanic['Survived'] # 处理缺失值和类别型特征 X['Age'].fillna(X['Age'].median(), inplace=True) X = pd.get_dummies(X, columns=['Sex', 'Embarked'], drop_first=True) # 划分训练测试集 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42)数据预处理的关键步骤:
- 用中位数填充Age缺失值
- 对性别和登船港口进行独热编码
- 保留20%数据作为最终测试集
3. 核心参数优化策略
3.1 max_depth:控制模型复杂度
max_depth是防止过拟合的第一道防线。通过网格搜索可以找到最佳深度:
from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import GridSearchCV param_grid = {'max_depth': range(3, 15)} grid_search = GridSearchCV( DecisionTreeClassifier(random_state=42), param_grid, cv=5, scoring='accuracy') grid_search.fit(X_train, y_train) print(f"最佳深度: {grid_search.best_params_['max_depth']}") print(f"验证集准确率: {grid_search.best_score_:.3f}")典型输出结果:
最佳深度: 5 验证集准确率: 0.8123.2 min_samples_split与min_samples_leaf
这两个参数共同控制树的水平复杂度:
| 参数 | 作用 | 推荐范围 | 对模型影响 |
|---|---|---|---|
| min_samples_split | 节点继续分裂的最小样本数 | 2-20 | 值越大树越简单 |
| min_samples_leaf | 叶节点的最小样本数 | 1-10 | 防止出现异常叶节点 |
联合调优代码示例:
param_grid = { 'min_samples_split': [2, 5, 10, 20], 'min_samples_leaf': [1, 2, 5, 10] } grid_search = GridSearchCV( DecisionTreeClassifier(max_depth=5, random_state=42), param_grid, cv=5) grid_search.fit(X_train, y_train)3.3 max_features:特征采样策略
这个参数控制每次分裂时考虑的特征数量,可以有效增加模型的随机性:
- 'auto':考虑所有特征(默认)
- 'sqrt':考虑特征总数的平方根
- 'log2':考虑log2(特征总数)
- 0.5:考虑50%的特征
实验表明,在泰坦尼克号数据集上使用'sqrt'策略能略微提升泛化能力。
3.4 criterion:分裂标准选择
Scikit-learn提供两种分裂标准:
- gini:基于基尼不纯度(默认)
- entropy:基于信息增益
虽然理论上entropy更合理,但在实际应用中两者差异通常小于1%。gini的计算效率略高,是大多数情况下的首选。
4. 完整调参流程与结果对比
综合所有参数的优化流程:
- 固定其他参数,优化max_depth
- 固定最佳max_depth,优化min_samples_split和min_samples_leaf
- 尝试不同的max_features策略
- 比较gini和entropy标准
最终模型配置:
best_dt = DecisionTreeClassifier( max_depth=5, min_samples_split=10, min_samples_leaf=2, max_features='sqrt', criterion='gini', random_state=42) best_dt.fit(X_train, y_train)性能对比表:
| 模型配置 | 训练集准确率 | 测试集准确率 | 过拟合程度 |
|---|---|---|---|
| 默认参数 | 0.983 | 0.799 | 严重 |
| 仅max_depth=5 | 0.827 | 0.810 | 轻微 |
| 所有优化参数 | 0.815 | 0.821 | 最优 |
5. 模型解释与特征重要性
决策树最大的优势在于其可解释性。我们可以可视化特征重要性:
import matplotlib.pyplot as plt features = X.columns importances = best_dt.feature_importances_ indices = np.argsort(importances)[::-1] plt.figure(figsize=(10,6)) plt.title("特征重要性") plt.bar(range(len(indices)), importances[indices]) plt.xticks(range(len(indices)), features[indices], rotation=90) plt.show()泰坦尼克号案例中,最重要的三个特征通常是:
- 性别(男性生存率显著更低)
- 乘客等级(头等舱生存率更高)
- 年龄(儿童优先获救)
通过调整这5个关键参数,我们成功将模型准确率从默认的79.9%提升到82.1%,同时显著降低了过拟合风险。实际项目中,可以进一步结合交叉验证和集成学习方法(如随机森林)来获得更稳定的性能表现。
