决策树--分类树、回归树

决策树介绍

决策树(Decision Tree)是一种非参数的有监督学习方法,它能够从一系列有特征和标签的数据中总结出决策规则,并用树状图的结构来呈现这些规则,以解决分类和回归问题。
决策树算法的核心是要解决两个问题:
1)如何从数据表中找出最佳节点和最佳分枝?
2)如何让决策树停止生长,防止过拟合?

例如数据集:
在这里插入图片描述
目标是,将动物们分为哺乳类和非哺乳类。那根据已经收集到的数据,决策树算法为我们算出了下面的这棵决策树:
在这里插入图片描述

Sklearn中的决策树

模块sklearn.tree
sklearn中决策树的类都在”tree“这个模块之下。这个模块总共包含五个类:
在这里插入图片描述

sklearn的基本建模流程:
在这里插入图片描述
在这里插入图片描述

分类树

在这里插入图片描述
Criterion这个参数正是用来决定不纯度的计算方法的,不纯度越低,决策树对训练集的拟合越好。现在使用的决策树算法在分枝方法上的核心大多是围绕在对某个不纯度相关指标的最优化上。sklearn提供了两种选择:
1)输入”entropy“,使用信息熵(Entropy)
2)输入”gini“,使用基尼系数(Gini Impurity)
信息熵对不纯度更加敏感,对不纯度的惩罚最强。**但是在实际使用中,信息熵和基尼系数的效果基本相同。**信息熵的计算比基尼系数缓慢一些,因为基尼系数的计算不涉及对数。另外,因为信息熵对不纯度更加敏感,所以信息熵作为指标时,决策树的生长会更加“精细”,因此对于高维数据或者噪音很多的数据,信息熵很容易过拟合,基尼系数在这种情况下效果往往比较好。当然,这不是绝对的。

决策树的基本流程其实可以简单概括如下:
在这里插入图片描述
直到没有更多的特征可用,或整体的不纯度指标已经最优,决策树就会停止生长。

建立一棵树–红酒数据集

from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split

wine = load_wine()
#划分数据集
Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data, wine.target,test_size = 0.3)
clf = tree.DecisionTreeClassifier(criterion = "entropy") #建立模型
clf = clf.fit(Xtrain, Ytrain) #训练
score = clf.score(Xtest, Ytest) #预测打分,返回预测的准确度accuracy 0.8703703703703703

把决策树画出来

import graphviz
dot_data = tree.export_graphviz(clf
                               ,feature_names = wine.feature_names
                               ,class_names = ["class1","class2","class3"]
                               ,filled = True  #树图像的颜色
                               ,rounded = True  # 树图像的形状
                               ,out_file = None
                               )
graph = graphviz.Source(dot_data)

在这里插入图片描述

clf = tree.DecisionTreeClassifier(criterion = "entropy"
                                  ,random_state = 30 #控制随机性,长出同一棵树
                                  ,splitter = "random" #splitter也是用来控制决策树中的随机选项的 best/random
                                 ) 
clf = clf.fit(Xtrain, Ytrain) #训练
score = clf.score(Xtest, Ytest) #预测打分,返回预测的准确度accuracy 0.9074074074074074

剪枝参数

解决过拟合的问题:在训练集上表现很好,在测试集上却表现糟糕 为了让决策树有更好的泛化性,我们要对决策树进行剪枝。剪枝策略对决策树的影响巨大,正确的剪枝策略是优化 决策树算法的核心。sklearn为我们提供了不同的剪枝策略。

max_depth 限制树的最大深度,超过设定深度的树枝全部剪掉。 这是用得最广泛的剪枝参数,在高维度低样本量时非常有效。决策树多生长一层,对样本量的需求会增加一倍,所 以限制树深度能够有效地限制过拟合。在集成算法中也非常实用。实际使用时,建议从=3开始尝试,看看拟合的效 果再决定是否增加设定深度。

min_samples_leaf & min_samples_split min_samples_leaf限定,一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分 枝就不会发生,或者,分枝会朝着满足每个子节点都包含min_samples_leaf个样本的方向去发生。 一般搭配max_depth使用,在回归树中有神奇的效果,可以让模型变得更加平滑。这个参数的数量设置得太小会引 起过拟合,设置得太大就会阻止模型学习数据。一般来说,建议从=5开始使用。 min_samples_split限定,一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分枝,否则 分枝就不会发生。

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

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

代码:

限制层数 max_depth:

 #限制层数 max_depth
clf = tree.DecisionTreeClassifier(criterion="entropy"
                                 ,random_state=30
                                 ,splitter="random"
                                 ,max_depth=3   #限制层数是3层
                                # ,min_samples_leaf=10
                                # ,min_samples_split=10
                                 )
clf = clf.fit(Xtrain, Ytrain)
dot_data = tree.export_graphviz(clf
                               ,feature_names= wine.feature_names
                               ,class_names=["琴酒","雪莉","贝尔摩德"]
                               ,filled=True
                               ,rounded=True
                               ,out_file = None
                               )  
graph = graphviz.Source(dot_data)
graph.view()

在这里插入图片描述
得到的结果:

clf.score(Xtrain,Ytrain) #0.9516129032258065
clf.score(Xtest,Ytest) #0.9814814814814815

再限制叶子节点的样本数量 min_samples_leaf

 #再限制叶子节点的样本数量 min_samples_leaf
clf = tree.DecisionTreeClassifier(criterion="entropy"
                                 ,random_state=30
                                 ,splitter="random"
                                 ,max_depth=3   #限制层数是3层
                                 ,min_samples_leaf=10  #叶子节点样本数量要大于10
                                # ,min_samples_split=10
                                 )
clf = clf.fit(Xtrain, Ytrain)
dot_data = tree.export_graphviz(clf
                               ,feature_names= wine.feature_names
                               ,class_names=["class1","class2","class3"]
                               ,filled=True
                               ,rounded=True
                               ,out_file = None
                               )  
graph = graphviz.Source(dot_data)
graph.view()

在这里插入图片描述
得到的结果:

clf.score(Xtrain,Ytrain) #0.8709677419354839
clf.score(Xtest,Ytest) #0.9259259259259259

再限制中间节点的样本数量 min_samples_leaf

 #再限制中间节点的样本数量 min_samples_leaf
clf = tree.DecisionTreeClassifier(criterion="entropy"
                                 ,random_state=30
                                 ,splitter="random"
                                 ,max_depth=3   #限制层数是3层
                                #,min_samples_leaf=10  #叶子节点样本数量要大于10
                                 ,min_samples_split=25 #中间节点样本数量要大于25
                                 )
clf = clf.fit(Xtrain, Ytrain)
dot_data = tree.export_graphviz(clf
                               ,feature_names= wine.feature_names
                               ,class_names=["琴酒","雪莉","贝尔摩德"]
                               ,filled=True
                               ,rounded=True
                               ,out_file = None
                               )  
graph = graphviz.Source(dot_data)
graph.view()

在这里插入图片描述
得到的结果:

clf.score(Xtrain,Ytrain) # 0.8870967741935484
clf.score(Xtest,Ytest) # 0.9259259259259259

确定最优的剪枝参数

#确定最优的剪枝参数
#用for循环调整max_depth,再画图
import matplotlib.pyplot as plt
test = []
for i in range(10):
    clf = tree.DecisionTreeClassifier(max_depth=i+1
                                     ,criterion="entropy"
                                     ,random_state=30
                                     ,splitter="random"
                                     )
    clf = clf.fit(Xtrain, Ytrain)
    score = clf.score(Xtest, Ytest)
    test.append(score)
plt.plot(range(1,11),test,color="red",label="max_depth")
plt.legend()
plt.show()  #得到3是最优的

在这里插入图片描述


#apply返回每个测试样本所在的叶子节点的索引
clf.apply(Xtest)
#predict返回每个测试样本的分类/回归结果
clf.predict(Xtest)

在这里插入图片描述


回归树

在这里插入图片描述

criterion:回归树衡量分枝质量的指标,有三种:

  • mse,均方误差(mean squared error)
  • friedman_mse,费尔德曼均方误差
  • mae,绝对平均误差

clf.score返回的是R方

回归树

创建简单的数据集来试验回归树

import numpy as np
import matplotlib.pyplot as plt
rng = np.random.RandomState(1) #生成随机数种子
rng.rand(80,1) #生成80*1的二维数组,数据在0-1之间  np.random.rand(s数据结构)生成随机数组的函数

创建训练集:

# 训练集
X = np.sort(5 * rng.rand(80,1),axis = 0) # 得到X,生成0-5之间的随机数,80*1二维数组,在行上排序
y = np.sin(X).ravel()  #求x的正弦,再用ravel降维得到一维数据标签 
#给y添加噪声
y[::5] += 3 * (0.5 - rng.rand(16)) #y[::5]给y切片,y[行:列:步长]每5个取一个数+ 负0.5到0.5之间的随机数放大三倍

训练模型:

#训练模型
regr_1 = DecisionTreeRegressor(max_depth = 2)
regr_2 = DecisionTreeRegressor(max_depth = 5)
regr_1.fit(X, y)
regr_2.fit(X, y)

创建测试集并预测数据:

#测试集
X_test = np.arange(0.0, 5.0, 0.01)[:, np.newaxis]  # np.newaxis 升维度 (500,)->(500,1) 一维变成二维
y_1 = regr_1.predict(X_test)
y_2 = regr_2.predict(X_test) #得到回归结果

画图:

#画图
plt.figure()
plt.scatter(X, y, s = 20, edgecolor = "black", c = "darkorange", label = "data") #画散点图
plt.plot(X_test, y_1, color = "cornflowerblue", label = "max_depth = 2", linewidth = 2)
plt.plot(X_test, y_2, color = "yellowgreen", label = "max_depth = 5", linewidth = 2)
plt.xlabel("data")
plt.ylabel("target")
plt.title("Decision Tree Regression")
plt.legend()
plt.show()

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你是个什么橙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值