sklearn机器学习:决策树的学习与调参

在没接触到机器学习的时候以为都是自己手写各种牛逼的算法,后来才晓得用sklearn这么个好用的库,既然大神给我们实现好了那没理由不去用啊,接下来会依次讲到如下内容

  1. 分类树
  2. 参数介绍与调参
  3. 交叉验证
  4. 回归树

由于篇幅问题,下次再使用决策树来做Kaggle的泰坦尼克号案例

关于决策树部门的理论学习以及sklearn官网,移步决策树[ID3,C4.5,CART]sklearn决策树

sklearn中的决策树

使用的是tree这个模块,主要包含以下几个类

在这里插入图片描述

分类树

class sklearn.tree.DecisionTreeClassifier (criterion=’gini’, splitter=’best’, max_depth=None,
min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None,
random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None,
class_weight=None, presort=False)

参数有点多,后面会挑一些主要的,经常用到的来讲

#1、导入需要的包
from sklearn.datasets import load_wine  #导入自带的红酒数据集
from sklearn import tree
from sklearn.model_selection import train_test_split #进行训练集数据集划分

#2、获取数据
wine = load_wine()

#3、划分训练集和测试集   注意顺序不能乱分别表示 训练集,测试集,训练集标签(类别),测试集标签(类别)
Xtrain,Xtest,Ytrain,Ytest=train_test_split(wine.data,wine.target,test_size=0.3)

#4、建立模型
clf = tree.DecisionTreeClassifier()  #实例化,全部选择了默认的参数
clf.fit(Xtrain,Ytrain)               #拟合
score=clf.score(Xtest,Ytest)         #模型评分
print(score) #输出结果是0.9259259259259259,还算不错

wine是个字典,key为data(特征集),target(标签),feature_names(特征名称),target_names(标签名称),DESCR(描述),来看一波吧

在这里插入图片描述

在这里插入图片描述

在第四步,即建立模型,虽然就三行代码,但是主要问题在于创建树实例的时候的参数,上面使用了默认值,实际上,当模型评分较低的时候就需要进行调参了,下面来看一些主要的参数。

参数1:criterion

criterion:划分依据,两个参数可填,使用"gini"那么则使用基尼系数来作为划分依据来进行节点划分,使
用"entropy"则使用信息增益来进行划分。sklearn使用优化版的CART算法来实现决策树的,难道是因为优化
的所以可以使用信息熵?默认使用的是gini,一般就使用它,真正使用的时候可以两个都试试。

参数2:random_state

关于这个参数找了一圈也没看到好好解释的,因为这个参数好像也没人会去动,前两天才看到有人细致的说了这个参数,同样使用上面的代码

在这里插入图片描述
输入[16]的代码,运行几次,发现得出的结果是不一样的,其实训练集测试集是不变的,按理说结果应该是一样的,为什么不一样?因为sklearn进行节点划分是这样的,并不是每次划分选择最优的特征,而是每次从中选取部分特征来进行划分才导致了这样的结果,这个跟跟随机森林的思想似乎很相似。有3种选择,默认是None,如果你想每次得到的结果不变(也就是每次长出来的树是一样的)使用个int值就行了。

参数3:splitter

节点上选择分割的策略,默认是"best"意思是在所有特征中选择最优的特征划分,可以选择"random"表示
随机选择的特征中选择最好的特征划分。如果特征巨多那么使用"random",否则就"best"好了。

修改完参数后,我们使用graphviz画出图形

#4、建立模型
clf = tree.DecisionTreeClassifier(criterion="gini"
                                  ,random_state=2
                                  ,splitter="random"
                                 )  
clf.fit(Xtrain,Ytrain)               #拟合
score=clf.score(Xtest,Ytest)         #模型评分
print(score)                 #输出0.8518518518518519
#5、画出图形
import graphviz

feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸']
class_name = ["鸡尾酒","红酒","苏打酒"]
data=tree.export_graphviz(clf
                     ,feature_names=feature_name  #特征
                     ,class_names=class_name      #类别
                     ,filled=True     #颜色填充 
                     ,rounded=True    #让边框变得圆润
                    )
graph=graphviz.Source(data)
graph

下面只截取了部分,实际树还还是挺深的
在这里插入图片描述

树太深那么意味着可能过拟合了,接下来进行剪枝,介绍剪枝参数

调参

参数4:max_depth

限制树生长的最大深度,可以填整数或者None,默认就是None,表示让树一直生长下去直到所有的叶节点
都属于同一类别或者叶节点的包含的样本数小于min_samples_split 设置的样本数,那么就停止生长。注
意:这是用的最广泛的剪枝参数了,一般从3开始调。

使用同样的代码,但是设置最大深度为3,再来看评分

#4、建立模型
clf = tree.DecisionTreeClassifier(criterion="gini"
                                  ,random_state=2
                                  ,splitter="random"
                                  ,max_depth=3
                                 )  
clf.fit(Xtrain,Ytrain)               #拟合
score=clf.score(Xtest,Ytest)         #模型评分
print(score)   #输出0.9074074074074074,提高了

参数5:min_samples_leaf

可以填int或者float,对于int,表示一个节点如果分支后存在节点的包含的样本数量小于该int值那么这个节点
就不会进行分支。默认是1,也就是只要分出来的节点包含至少一个样本就会进行分支。浮点数是表示百分比(占比)
的意思,注意:这个也是重要的剪枝参数。同时,这个参数可以保证每个叶子的最小尺寸,可以在回归问题中避免低
方差,过拟合的叶子节点出现。对于类别不多的分类问题,=1通常就是最佳选择

参数5:min_samples_split

一个节点至少包含min_samples_split个样本才会进行分支,默认是2。

参数6:max_features

限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃,但其方法比较暴力,是直接限制可以使用的特征数量
而强行使决策树停下的参数,在不知道决策树中的各个特征的重要性的情况下,强行设定这个参数可能会导
致模型学习不足。如果希望通过降维的方式防止过拟合,建议使用PCA,ICA或者特征选择模块中的降维算法,默认是None考虑所有特征

参数7:min_impurity_decrease

限制信息增益的大小,信息增益小于设定数值的分枝不会发生。这是在0.19版本中更新的功能

参数8:class_weight

指定样本各类别的的权重,主要是为了防止训练集某些类别的样本过多导致训练的决策树过于偏向这些类别。这里
可以自己指定各个样本的权重如果使用“balanced”,则算法会自己计算权重,样本量少的类别所对应的样本权重会高。

在默认参数的情况下,树会一直生长下去直到满足条件。可能在某些大型数据集上树会长的巨大,可以提交设置好剪枝参数。下面介绍参数设置的一些建议

  1. 如果样本的维度很大,那么先进行降维,使用PCA,ICA等降维手段或者特征选择
  2. 树太深容易产生过拟合,设置参数max_depth=3为初始值,然后慢慢增大
  3. 对于min_samples_leaf,和min_samples_split的值如果设置过小则容易产生过拟合,设置过大那么不利于树的学习,所以可以使用min_samples_leaf=5为初始值再慢慢进行调整。如果样本量变化很大那么使用百分比(浮点数)。注意:这些都是官方原话,有博士说,如果样本量不是巨大,那么不要去管这两个值,否则可以使用min_samples_leaf=5为初始值再慢慢进行调整,并且可以增大min_samples_split。

学习曲线
比如对于参数max_depth,哪个值最好呢?画出学习曲线去看即可

#确定最优剪枝参数    超参数学习曲线
test=[]
Xtrain,Xtest,Ytrain,Ytest=train_test_split(wine.data,wine.target,test_size=0.3)
for i in range(10):
    clf = tree.DecisionTreeClassifier(criterion="entropy"
                                      ,random_state=30
                                      ,splitter="random"
                                      ,max_depth=i+1
                                     )
    clf.fit(Xtrain,Ytrain)
    score=clf.score(Xtest,Ytest)
    test.append(score);

import matplotlib.pyplot as plt

plt.figure(figsize=(20,8),dpi=80)
plt.plot(range(1,11),test)
plt.show();
再来介绍1个属性和4个接口

画出的图形如下

在这里插入图片描述
显然max_depth=3的时候最好模型预测效果是最好的。

属性:feature_importances_
获取各个特征的重要性

接口:fit,score,apply,predict

apply(Xtest) :得到每个测试样本所在的叶子节点的索引
predict(Xtest):得到每个测试样本的预测值(分类或回归的结果)

在这里插入图片描述

回归树

class sklearn.tree.DecisionTreeRegressor (criterion=’mse’, splitter=’best’, max_depth=None,
min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None,
random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, presort=False)

几乎所有的参数都和回归树是一样的,接口和属性也是一样,没有标签是否均衡的问题,因为回归问题不存在标签。主要说一下criterion属性

划分依据有三种:"“mse”",“friedman_mse”,"“mae”"

在这里插入图片描述

意思大概就是,对与 m m m表示在区域 R m R_m Rm,其中包含了 N m N_m Nm个样本,对与节点的划分最常用的使用均方误差和绝对平均误差。具体的介绍参考决策树[ID3,C4.5,CART],只看里面的回归树部分即可。默认使用的就是mse。但是回归树的接口score返回的是R平方而不是mse。
在这里插入图片描述

交叉验证

交叉验证分为:简单交叉验证,S折交叉验证,留一交叉验证
S折交叉验证是最为常用的,sklearn中也是使用了这种方式,方法如下:首先随机的将已给数据切分为S个互不相交的大小相同的子集;然后利用S-1个子集的数据训练模型,利用余下的子集进行测试模型;将这一过程对可能的S种选择重复进行;最后选出S次评测中平均误差最小的模型。

from sklearn.model_selection import cross_val_score  #交叉验证模块
from sklearn.datasets import load_boston #波士顿房间数据集,回归
from sklearn import tree

boston = load_boston()
dtr = tree.DecisionTreeRegressor()
#数据集分成10份,每次9份训练模型,一份测试,一共进行十次,得到10个结果,通常会取均值
score=cross_val_score(dtr,boston.data,boston.target,cv=10)
score

输出:

array([ 0.53441308,  0.63264076, -1.5888095 ,  0.40937024,  0.65865512,
    0.41838375,  0.21994768,  0.34436505, -3.40097382, -0.96772501])

注意到,得到的结果有负数有正数,这是因为默认的评分准则是R评方,可以指定使用mse(使用的是负数,去掉负号就是mse结果了)

score = cross_val_score(dtr,boston.data,boston.target,cv=10,scoring="neg_mean_squared_error")
score

输出:

array([-16.72137255, -12.02647059, -16.81921569, -90.13490196,
       -15.82529412, -36.55431373, -12.9186    , -92.5836    ,
       -67.3012    , -37.6402    ])

再回到回归树,来做个回归树的小例子,这也是官网的回归树的小例子。
训练样本就是正弦曲线上的点,但是存在噪音。现在使用两颗高度不同的回归树来进行拟合,并对测试集进行预测,将结果画出来

from sklearn import tree
import numpy as np
import matplotlib.pyplot as plt

#1、创建随机数据集
rng=np.random.RandomState(1) # 获取随机数种子,保证每次获取的随机数都是一样的
#生成80行一列的数据集,从小到大排列
#为什么要生成二维的?因为sklearn进行拟合的时候要求不能是一维的
X=np.sort(rng.rand(80,1)*5,axis=0)
y=np.sin(X).flatten() #二维变一维,或者使用ravel,只是我没学过这个
y[::5]+=3*(0.5-rng.rand(16)) #设置噪声点

#2、模型拟合  两棵树的最大深度一个是2一个是5
dtr1=tree.DecisionTreeRegressor(max_depth=2)  
dtr2=tree.DecisionTreeRegressor(max_depth=5)
dtr1.fit(X,y)
dtr2.fit(X,y)

#3、进行预测  同样的要将数据转成二维的
l=np.arange(0.0,5.0,0.01)
Xtest=l.reshape(np.size(l),1)
y1=dtr1.predict(Xtest)
y2=dtr2.predict(Xtest)


#4、绘图

plt.figure(figsize=(15,8),dpi=50)#设置画板

plt.scatter(X,y,edgecolor="black",c="darkorange", label="data")
plt.plot(Xtest,y1,color="cornflowerblue",label="max_depth=2", linewidth=2)
plt.plot(Xtest,y2,color="yellowgreen", label="max_depth=5", linewidth=2)
plt.xlabel("data")
plt.ylabel("target")
plt.title("Decision Tree Regression")
plt.legend() #前面的图形设置了label就得设置这个,否则就不显示标记
plt.show()

画出的图形如下

在这里插入图片描述

显然深度为5的树过拟合了,过多的关注了噪声点。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值