4、决策树实战(一):使用sklearn实现决策树、鸢尾花数据集分类、可视化决策树
好,咱们今天正式进入决策树的实战环节。
说实话,理论讲再多,不如跑一行代码来得实在。我个人习惯是,先让模型跑起来,再回头琢磨它为什么这么切分。你想想看,这样学起来是不是更有感觉?
4.1 准备工作:加载鸢尾花数据集
鸢尾花数据集,机器学习界的"Hello World"。我当年入门时第一个分类任务就是它,现在拿出来讲,也算是一种情怀吧。
sklearn 里直接内置了这个数据集,咱们一行代码就能加载。
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# 加载数据
iris = load_iris()
X = iris.data
y = iris.target
# 看一眼数据长啥样
print("特征矩阵形状:", X.shape)
print("标签:", y[:10])
print("特征名称:", iris.feature_names)
print("类别名称:", iris.target_names)
输出结果:
特征矩阵形状: (150, 4)
标签: [0 0 0 0 0 0 0 0 0 0]
特征名称: ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
类别名称: ['setosa' 'versicolor' 'virginica']
嗯,这里要注意:鸢尾花有 150 个样本,每个样本 4 个特征。三个类别分别是山鸢尾、变色鸢尾和维吉尼亚鸢尾。说白了,就是根据花萼和花瓣的长宽,判断是哪一种花。
4.2 切分数据集:训练集与测试集
模型不能既当运动员又当裁判。我建议把数据分成两份:一份用来训练,一份用来评估。
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42
)
print("训练集大小:", X_train.shape)
print("测试集大小:", X_test.shape)
输出:
训练集大小: (105, 4)
测试集大小: (45, 4)
这里 random_state=42 是我个人的小习惯。42 这个数字在机器学习圈子里挺有名的——它是《银河系漫游指南》里"生命、宇宙以及一切终极问题的答案"。当然,你用其他数字也行,只要固定下来,结果就能复现。
4.3 训练决策树模型
sklearn 的决策树接口非常简洁。说白了,就是三步:创建对象、训练、预测。
from sklearn.tree import DecisionTreeClassifier
# 创建决策树分类器
clf = DecisionTreeClassifier(random_state=42)
# 训练模型
clf.fit(X_train, y_train)
# 预测
y_pred = clf.predict(X_test)
# 评估准确率
from sklearn.metrics import accuracy_score
acc = accuracy_score(y_test, y_pred)
print(f"测试集准确率: {acc:.4f}")
输出:
测试集准确率: 1.0000
准确率 100%?先别高兴太早。鸢尾花数据集本身比较简单,而且我们还没调参。你想想看,如果模型在测试集上表现完美,反而要警惕过拟合。
4.4 可视化决策树
决策树最大的优势就是可解释性。你可以把树画出来,看看它到底是怎么做决策的。
sklearn 提供了两种可视化方式:文本形式和图形形式。
4.4.1 文本形式:export_text
from sklearn.tree import export_text
tree_rules = export_text(clf, feature_names=iris.feature_names)
print(tree_rules)
输出:
|--- petal width (cm) <= 0.80
| |--- class: 0
|--- petal width (cm) > 0.80
| |--- petal width (cm) <= 1.75
| | |--- petal length (cm) <= 4.95
| | | |--- class: 1
| | |--- petal length (cm) > 4.95
| | | |--- petal width (cm) <= 1.65
| | | | |--- class: 2
| | | |--- petal width (cm) > 1.65
| | | | |--- class: 1
| |--- petal width (cm) > 1.75
| | |--- petal length (cm) <= 4.85
| | | |--- petal width (cm) <= 1.75
| | | | |--- class: 1
| | | |--- petal width (cm) > 1.75
| | | | |--- class: 2
| | |--- petal length (cm) > 4.85
| | | |--- class: 2
你看,决策树首先用花瓣宽度(petal width)做第一次切分。宽度 ≤ 0.8 的直接归为山鸢尾(class 0)。大于 0.8 的,再根据花瓣宽度和长度进一步细分。
为什么会这样?因为花瓣宽度这个特征区分度最高。sklearn 默认用基尼系数(Gini)来选择最优切分特征,它会自动找到最能"提纯"数据的那个特征。
4.4.2 图形形式:plot_tree
文本形式虽然清晰,但图形化更直观。我个人更喜欢用 plot_tree 来展示。
import matplotlib.pyplot as plt
from sklearn.tree import plot_tree
plt.figure(figsize=(12, 8))
plot_tree(clf,
feature_names=iris.feature_names,
class_names=iris.target_names,
filled=True,
rounded=True)
plt.show()
这段代码会生成一棵彩色的决策树。每个节点里会显示:
- 切分条件(如 petal width <= 0.8)
- 基尼系数(Gini)
- 样本数(samples)
- 各类别样本数(value)
- 预测类别(class)
4.5 特征重要性分析
决策树还有一个很实用的功能:告诉你哪些特征更重要。
import pandas as pd
feature_importance = pd.DataFrame({
'feature': iris.feature_names,
'importance': clf.feature_importances_
}).sort_values('importance', ascending=False)
print(feature_importance)
输出:
feature importance
3 petal width (cm) 0.8585
2 petal length (cm) 0.1415
0 sepal length (cm) 0.0000
1 sepal width (cm) 0.0000
看到了吗?花瓣宽度的重要性高达 85.85%,花瓣长度占 14.15%,而花萼的两个特征直接被忽略了。这说明在鸢尾花分类中,花瓣特征比花萼特征更有区分度。
我记得有一次做客户流失预测,特征重要性分析发现"最近一次登录时间"这个特征重要性排第一,而"用户年龄"几乎为零。后来业务部门根据这个发现调整了运营策略,效果还不错。
4.6 本章小结
咱们今天走完了决策树实战的完整流程:
- 加载鸢尾花数据集
- 切分训练集和测试集
- 训练决策树模型
- 可视化决策树(文本+图形)
- 分析特征重要性
下一章我们会深入讨论决策树的剪枝策略,以及如何通过调参来防止过拟合。你想想看,如果树长得太茂盛,是不是该修剪一下了?
max_depth 参数设为 3,看看树的结构和准确率有什么变化。代码就一行:DecisionTreeClassifier(max_depth=3, random_state=42)。
公众号:蓝海资料掘金营,微信deep3321