决策树详解与sklearn实战

机器学习 | 决策树详解与sklearn实战

一、sklearn概述

scikit-learn(又写作sklearn)是一个开源的Python机器学习工具包,通过NumPy、SciPy和Matplotlib等库实现高效的算法应用,涵盖了几乎所有主流机器学习算法。

在实际工程应用中,我们通常:

  1. 分析采集到的数据
  2. 根据数据特征选择适合的算法
  3. 在工具包中调用算法、调整参数
  4. 获取需要的信息

sklearn正是这样一个能帮助我们高效实现算法应用的工具包。


二、决策树工作原理

2.1 什么是决策树

决策树(Decision Tree)是一种非参数的有监督学习方法,能够从有特征和标签的数据中总结出决策规则,用树状图结构呈现,解决分类和回归问题。

2.2 决策树的核心概念

决策树由三种节点组成:

节点类型 描述
根节点 没有进边,有出边。包含最初的特征提问
中间节点 既有进边也有出边,进边只有一条,出边可以有多条
叶子节点 有进边,没有出边,每个叶子节点都是一个类别标签

父节点和子节点:两个相连的节点中,接近根节点的是父节点,另一个是子节点。

2.3 决策树要解决的两个核心问题

  1. 如何从数据表中找出最佳节点和最佳分枝?
  2. 如何让决策树停止生长,防止过拟合?

三、sklearn中的决策树

3.1 tree模块

sklearn中决策树的类都在tree模块下:

用途
tree.DecisionTreeClassifier 分类树
tree.DecisionTreeRegressor 回归树
tree.export_graphviz 导出为DOT格式,画图专用
tree.ExtraTreeClassifier 高随机版本的分类树
tree.ExtraTreeRegressor 高随机版本的回归树

3.2 sklearn建模基本流程

python 复制代码
from sklearn import tree

# 1. 导入模块
clf = tree.DecisionTreeClassifier()

# 2. 实例化
clf = clf.fit(X_train, y_train)

# 3. 用训练集数据训练模型
result = clf.score(X_test, y_test)

# 4. 导入测试集,从接口调用需要的信息

四、DecisionTreeClassifier 重要参数详解

4.1 criterion(不纯度计算方法)

作用:决定不纯度的计算方法,帮助找出最佳节点和最佳分枝。

决策树算法通过不纯度来衡量节点的质量。不纯度越低,决策树对训练集的拟合越好。sklearn提供两种选择:

参数值 计算方法
"gini" 基尼系数(Gini Impurity)
"entropy" 信息熵(Entropy)

公式

  • 基尼系数:Gini(t)=1−∑i=0c−1p(i∣t)2Gini(t) = 1 - \sum_{i=0}^{c-1}p(i|t)^2Gini(t)=1−∑i=0c−1p(i∣t)2
  • 信息熵:Entropy(t)=−∑i=0c−1p(i∣t)log2p(i∣t)Entropy(t) = -\sum_{i=0}^{c-1}p(i|t)log_2p(i|t)Entropy(t)=−∑i=0c−1p(i∣t)log2p(i∣t)

选择建议

场景 推荐
默认 基尼系数
数据维度很大,噪音很多 基尼系数
维度低,数据比较清晰 两者皆可
决策树拟合程度不够 信息熵

信息熵对不纯度更敏感,计算比基尼系数慢,但惩罚更强。高维数据或噪音多时容易过拟合。


4.2 random_state & splitter(随机性控制)

random_state:设置分枝中的随机模式参数

  • 默认None,高维度时随机性更明显
  • 输入任意整数,可以长出同一棵树,让模型稳定

splitter:控制分枝的随机程度

行为
"best" 优先选择更重要的特征进行分枝
"random" 更加随机,树更深更大

当预测模型会过拟合时,可用这两个参数降低过拟合可能性。


4.3 剪枝参数(防止过拟合)

在不加限制的情况下,决策树会生长到不纯度指标最优或没有更多特征可用,这样往往会导致过拟合------在训练集上表现好,但在测试集上表现糟糕。

max_depth

限制树的最大深度,超过设定深度的树枝全部剪掉。

在高维度低样本量时非常有效,建议从=3开始尝试。

min_samples_leaf & min_samples_split
参数 作用
min_samples_leaf 限定一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本
min_samples_split 限定一个节点必须包含至少min_samples_split个训练样本才允许被分枝

建议从=5开始使用。如果类别不多的分类问题,=1通常就是最佳选择。

max_features

限制分枝时考虑的特征个数,超过限制个数的特征会被舍弃。

在不知道特征重要性的情况下强行设定可能导致模型学习不足。

min_impurity_decrease

限制信息增益的大小,信息增益小于设定数值的分枝不会发生。


4.4 目标权重参数(处理样本不平衡)

class_weight:对样本标签进行平衡,给少量标签更多权重。

场景:比如银行判断信用卡违约(是vs否 = 1%:99%),即使全预测成"否"正确率也有99%,这时需要调整权重。

min_weight_fraction_leaf :基于权重的剪枝参数,与class_weight配合使用。


五、重要属性和接口

属性

feature_importances_:查看各个特征对模型的重要性

python 复制代码
clf.feature_importances_
[*zip(feature_name, clf.feature_importances_)]

四个核心接口

接口 功能
fit(X_train, y_train) 训练模型
score(X_test, y_test) 返回预测准确度
apply(X_test) 返回每个测试样本所在的叶子节点索引
predict(X_test) 返回每个测试样本的标签
python 复制代码
# 训练和评估
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest)

# 查看特征重要性
clf.feature_importances_

# 预测
clf.apply(Xtest)    # 返回叶子节点索引
clf.predict(Xtest)  # 返回分类结果

六、实战:绘制决策树

python 复制代码
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
import graphviz

# 1. 导入数据
wine = load_wine()

# 2. 分训练集和测试集
Xtrain, Xtest, Ytrain, Ytest = train_test_split(
    wine.data, wine.target, test_size=0.3
)

# 3. 建立模型
clf = tree.DecisionTreeClassifier(criterion="entropy", random_state=30)
clf = clf.fit(Xtrain, Ytrain)

# 4. 评估
score = clf.score(Xtest, Ytest)

# 5. 绘制决策树
feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚',
                '类黄酮','非黄烷类酚类','花青素','颜色强度',
                '色调','od280/od315稀释葡萄酒','脯氨酸']

dot_data = tree.export_graphviz(
    clf,
    feature_names=feature_name,
    class_names=["琴酒","雪莉","贝尔摩德"],
    filled=True,
    rounded=True
)
graph = graphviz.Source(dot_data)
graph

七、总结

决策树核心知识点

类别 内容
七个参数 Criterion、random_state、splitter、max_depth、min_samples_leaf、max_features、min_impurity_decrease
一个属性 feature_importances_
四个接口 fit、score、apply、predict

超参数调优建议

通过学习曲线来判断最优参数------以超参数取值为横坐标,模型度量指标(score)为纵坐标绘制曲线。

调参没有绝对的答案,一切都要看数据本身。

不同数据集的模型选择

数据集类型 最擅长的模型
月亮型数据 最近邻算法、RBF支持向量机、高斯过程
环形数据 最近邻算法、高斯过程
对半分数据 朴素贝叶斯、神经网络、随机森林

八、剪枝策略

|

新增参数 说明
min_samples_split 节点分枝前的最小样本数门槛
max_leaf_nodes 限制最大叶子节点数
min_impurity_split 已废弃,用min_impurity_decrease替代
presort 是否预排序加速拟合
max_depth 限制树的最大深度,超过设定深度的树枝全部剪掉
python 复制代码
clf = tree.DecisionTreeClassifier(criterion="entropy"
                                 ,random_state=30
                                 ,splitter="random"
                                 ,max_depth=3
                                 ,min_samples_leaf=10
                                 ,min_samples_split=10
                                 )
clf = clf.fit(Xtrain, Ytrain)
 
相关推荐
Lewiis1 小时前
趣谈排序算法
算法·排序算法
ComputerInBook1 小时前
数字图像处理(4版)——第 8 章——图像压缩与水印(上)(Rafael C.Gonzalez&Richard E. Woods)
人工智能·算法·计算机视觉·图像压缩·图像水印
刀法如飞2 小时前
Python列表去重:从新手三连到高阶特技,20种解法全收录
python·算法·编程语言
minji...2 小时前
算法题 动态规划
算法·动态规划
水蓝烟雨2 小时前
3337. 字符串转换后的长度 II
算法·leetcode
MegaDataFlowers2 小时前
SiliconCompiler workflow
算法
_日拱一卒2 小时前
LeetCode:226翻转二叉树
数据结构·算法·leetcode
BirdenT3 小时前
20260424紫题训练
c++·算法
还是阿落呀3 小时前
基本控制结构
开发语言·c++·算法