【机器学习笔记】【决策树】【分类树】

目录

一、初次简单使用

1.导入我们的数据集

2.查看我们的数据集

3.划分测试集和训练集 

查看训练集

查看测试集

查看测试集的标签

 4.使用决策树对我们的模型进行训练

5.使用graphviz查看我们的二叉树

二、优化决策树 

1.特征的贡献值

2.重要参数 

1.random_state & splitter

2.剪枝参数 

max_depth

min_samples_leaf & min_samples_split 

max_features & min_impurity_decrease

可视化查看如何选取参数的方法

class_weight & min_weight_fraction_leaf

3.重要的属性和接口 


一、初次简单使用

1.导入我们的数据集

from sklearn import tree
#导入红酒数据集
#sklearn的datasets库中有大量的数据集
from sklearn.datasets import load_wine
#从sklearn的模型选择中导入训练集,测试集分类
from sklearn.model_selection import train_test_split

2.查看我们的数据集

将我们的红酒数据放入wine中

wine=load_wine()

查看一下红酒数据集 

wine

【机器学习笔记】【决策树】【分类树】_第1张图片

#获取wine数据集中的数据
wine.data

【机器学习笔记】【决策树】【分类树】_第2张图片

#这里的标签为0,1,2,是一个三分类的数据集
wine.target

【机器学习笔记】【决策树】【分类树】_第3张图片

#查看数据集有几行几列
wine.data.shape

import pandas as pd
#将wine数据集的数据和标签联系起来,axis,连接方向为横向连接,也就是说左边的0-12列都是我们的红酒的数据,我们右边的最后一列是我们的标签
pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)

 【机器学习笔记】【决策树】【分类树】_第4张图片

#这些特征的标题
wine.feature_names

【机器学习笔记】【决策树】【分类树】_第5张图片

#类别
wine.target_names

3.划分测试集和训练集 

#30%用作测试集,剩下的70%用作训练集
#x所对应的是红酒的数据,而y对应的是红酒的标签
Xtrain,Xtest,Ytrain,Ytest=train_test_split(wine.data,wine.target,test_size=0.3)

查看训练集

Xtrain

【机器学习笔记】【决策树】【分类树】_第6张图片

Xtrain.shape

 

查看测试集

Xtest

【机器学习笔记】【决策树】【分类树】_第7张图片

查看测试集的标签

Ytrain

【机器学习笔记】【决策树】【分类树】_第8张图片

 4.使用决策树对我们的模型进行训练

#第一步:实例化
#classify,简写clf,分类器
clf=tree.DecisionTreeClassifier(criterion="entropy")
#第二步:将模型带入我们的分类器中进行训练
clf=clf.fit(Xtrain,Ytrain)
#第三步:给我们的训练结果打分
#这个score就得到了我们的打分结果,返回预测的准确度accuracy
score=clf.score(Xtest,Ytest)
#这个score在我们上面每一次重新划分测试集和训练集之后都是会发生变化的
#因为我们上面的train_test_split是随机划分测试集和训练集的,
#所以说每一次导入的数据和模型都是不一样的

#但是这个score每一次重新执行上面的三个步骤之后都会发生变化
#这是因为我们的sklearn再每一次建树的时候,并没有选择全部的特征,而是选取一部分特征,从中选取不纯度相关指标最优的作为分支用的结点,
#这样,每次生成的树也就不同了
#也就是说假设有一个果农,想要栽培出一棵最好的苹果树,果农最好的方法并不是从一个最好的苹果中选取一个最饱满的种子,然后将这一棵种子种下,
#这样不一定能够种出最好的果树
#果农可以采用更好的方法,就是同时种下一批种子,等待这些种子全部生根发芽,然后从这片树中找到一棵最好的苹果树,
#这也就是我们的sklearn所采用的的方法
#但是这样会让我们的模型不稳定了,每次跑出来的结果都不一样了。
#将在下面讲述如何解决
score

5.使用graphviz查看我们的二叉树

feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸']
#查看建模出来的这棵树是什么样子的,我们需要导入graphviz库
import graphviz
dot_data=tree.export_graphviz(
    #第一个,输入已经训练好的模型
    clf,
    #第二个,特征的名字
    feature_names=feature_name,
    #第三个,标签的名字
    class_names=["琴酒","雪莉","贝尔摩德"],
    #要不要给每一个结点填充颜色,也就是我们下面的树中的每一个框中我们是否要填充颜色,
    #其中颜色越深,就代表着我们的不纯度越低,也就是说我们的纯度越高
    filled=True,
    #rounded表示是我们下面生成的树的结点是圆框的还是直角框的。
    rounded=True,
    
)
#将我们画的树给导出来
graph=graphviz.Source(dot_data)
graph
#每一个框的第一行都是对于下面两棵子树的分类标准
#第二行entropy是我们设置的不纯度的指标,
#越往下不纯度的指标是越来越少的,也就是纯度越来越高,到达叶子节点的时候不纯度是0,也就是确定了我们的标签类别
#samples包含的样本数量
#value是每一个样本标签数量的占比,就比方说根节点的框中43:50:31,就是说"琴酒","雪莉","贝尔摩德"的比例是43:50:31
#class是当前结点所属于的标签

【机器学习笔记】【决策树】【分类树】_第9张图片

二、优化决策树 

1.特征的贡献值

#从上面的树中我们看到决策树并没有将全部的特征都用于分类,但是我们怎么才能知道每一个特征对于决策树的贡献呢?
#使用下面的代码就能够求得每一个特征对于我们决策树的贡献
clf.feature_importances_
#对决策树的贡献值越大的,其数值就越高

#使用zip函数将我们的特征名字和具体的特征的贡献值联系起来
#我们注意到我们的类黄酮的特征贡献值是最高的。
#并且类黄酮就是我们的根节点,也就是说根节点的特征贡献值会是最高的
[*zip(feature_name,clf.feature_importances_)]

【机器学习笔记】【决策树】【分类树】_第10张图片

2.重要参数 

1.random_state & splitter

random_state用来设置分枝中的随机模式的参数,默认None,在高维度时随机性会表现更明显,低维度的数据(比如鸢尾花数据集),随机性几乎不会显现。输入任意整数,会一直长出同一棵树,让模型稳定下来。
splitter也是用来控制决策树中的随机选项的,有两种输入值,输入”best",决策树在分枝时虽然随机,但是还是会优先选择更重要的特征进行分枝(重要性可以通过属性feature_importances_查看),输入“random",决策树在分枝时会更加随机,树会因为含有更多的不必要信息而更深更大,并因这些不必要信息而降低对训练集的拟合。这也是防止过拟合的一种方式。当你预测到你的模型会过拟合,用这两个参数来帮助你降低树建成之后过拟合的可能性。当然,树一旦建成,我们依然是使用剪枝参数来防止过拟合。

#这里我们确定了随机模式是30,所以我们无论重复执行多少次下面的代码,得到的结果都是一样的
#random_state用来设置分枝中的随机模式的参数,默认None,在高维度时随机性会表现更明显,低维度的数据
#(比如鸢尾花数据集),随机性几乎不会显现。输入任意整数,会一直长出同一棵树,让模型稳定下来
clf=tree.DecisionTreeClassifier(criterion="entropy",random_state=30)
clf=clf.fit(Xtrain,Ytrain)
score=clf.score(Xtest,Ytest)#返回预测结果的准确度
score

#使用splitter也可以控制决策树的随机性
#有两种输入值,输入”best",决策树在分枝时虽然随机,但是还是会
#优先选择更重要的特征进行分枝(重要性可以通过属性feature_importances_查看),输入“random",决策树在
#分枝时会更加随机,树会因为含有更多的不必要信息而更深更大,并因这些不必要信息而降低对训练集的拟合。这
#也是防止过拟合的一种方式。当你预测到你的模型会过拟合,用这两个参数来帮助你降低树建成之后过拟合的可能
#性。当然,树一旦建成,我们依然是使用剪枝参数来防止过拟合。

将splitter设置为random的结果 

#将splitter设置为random来查看我们的训练的模型的准确率
clf = tree.DecisionTreeClassifier(criterion="entropy"
    ,random_state=30
    #这里的splitter如果在添加之后让我们的模型的准确性更高,我们就将将这个参数保留
    #如果这个splitter让我们的模型准确率变低了,我们就将这个参数注释掉
    ,splitter="random"
)
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest)
score

这里树太大了,只截取了一部分 【机器学习笔记】【决策树】【分类树】_第11张图片

 将splitter设置为best的结果 

#将splitter设置为best来查看我们的训练的模型的准确率
clf = tree.DecisionTreeClassifier(criterion="entropy"
    ,random_state=30
    #这里的splitter如果在添加之后让我们的模型的准确性更高,我们就将将这个参数保留
    #如果这个splitter让我们的模型准确率变低了,我们就将这个参数注释掉
    ,splitter="best"
)
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest)
score

 查看我们生成的树

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

【机器学习笔记】【决策树】【分类树】_第12张图片

2.剪枝参数 

在不加限制的情况下,一棵决策树会生长到衡量不纯度的指标最优,或者没有更多的特征可用为止。这样的决策树往往会过拟合,这就是说,它会在训练集上表现很好,在测试集上却表现糟糕。我们收集的样本数据不可能和整体的状况完全一致,因此当一棵决策树对训练数据有了过于优秀的解释性,它找出的规则必然包含了训练样本中的噪声,并使它对未知数据的拟合程度不足。

#我们的树对训练集的拟合程度如何?
score_train = clf.score(Xtrain, Ytrain)
score_train

为了让决策树能够有更好的泛化性,我们要就决策树进行剪枝。剪枝策略对决策树的影响巨大,正确的剪枝策略是优化决策树算法的核心。
sklearn为我们提供了不同的剪枝策略

max_depth

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

min_samples_leaf & min_samples_split 

min_samples_leaf限定,一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分枝就不会发生,或者,分枝会朝着满足每个子节点都包含min_samples_leaf个样本的方向去发生一般搭配max_depth使用,在回归树中有神奇的效果,可以让模型变得更加平滑。这个参数的数量设置得太小会引起过拟合,设置得太大就会阻止模型学习数据。一般来说,建议从=5开始使用。如果叶节点中含有的样本量变化很大,建议输入浮点数作为样本量的百分比来使用。同时,这个参数可以保证每个叶子的最小尺寸,可以在回归问题中避免低方差,过拟合的叶子节点出现。对于类别不多的分类问题,=1通常就是最佳选择。

min_samples_split限定,一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分枝,否则分枝就不会发生。

clf = tree.DecisionTreeClassifier(criterion="entropy"
    ,random_state=30
    ,splitter="random"
    #限定我们的树的深度只有4层,后面多余4层的部分全部都被砍掉了    
    ,max_depth=4
    #一个节点在分枝后的每个子节点都必须包含至少5个训练样本
    ,min_samples_leaf=5
    #一个节点必须要包含至少10个训练样本,这个节点才允许被分枝
    ,min_samples_split=10
)
clf = clf.fit(Xtrain, Ytrain)
dot_data = tree.export_graphviz(clf
    ,feature_names= feature_name
    ,class_names=["琴酒","雪莉","贝尔摩德"]
    ,filled=True
    ,rounded=True
)
graph = graphviz.Source(dot_data)
graph

树太大了,只截了一部分 【机器学习笔记】【决策树】【分类树】_第13张图片

 查看当前模型的打分结果

clf.score(Xtrain,Ytrain)

clf.score(Xtest,Ytest)

max_features & min_impurity_decrease

一般max_depth使用,用作树的”精修“ max_features限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃。和max_depth异曲同工, max_features是用来限制高维度数据的过拟合的剪枝参数,但其方法比较暴力,是直接限制可以使用的特征数量 而强行使决策树停下的参数,在不知道决策树中的各个特征的重要性的情况下,强行设定这个参数可能会导致模型 学习不足。如果希望通过降维的方式防止过拟合,建议使用PCA,ICA或者特征选择模块中的降维算法。

min_impurity_decrease限制信息增益(父节点和子节点的信息熵的差(子节点的信息熵一定会小于父节点的信息熵))的大小,信息增益小于设定数值的分枝不会发生。这是在0.19版本中更新的 功能,在0.19版本之前时使用min_impurity_split。

 确认最优的剪枝参数 那具体怎么来确定每个参数填写什么值呢?这时候,我们就要使用确定超参数的曲线来进行判断了,继续使用我们 已经训练好的决策树模型clf。超参数的学习曲线,是一条以超参数的取值为横坐标,模型的度量指标为纵坐标的曲 线,它是用来衡量不同超参数取值下模型的表现的线。在我们建好的决策树里,我们的模型度量指标就是score。

可视化查看如何选取参数的方法

import matplotlib.pyplot as plt
test = []
for i in range(10):
    #测试最大深度为多少的时候能让我们的树的score达到最高的值
    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()

【机器学习笔记】【决策树】【分类树】_第14张图片

class_weight & min_weight_fraction_leaf

        完成样本标签平衡的参数。样本不平衡是指在一组数据集中,标签的一类天生占有很大的比例。比如说,在银行要 判断“一个办了信用卡的人是否会违约”,就是是vs否(1%:99%)的比例。这种分类状况下,即便模型什么也不 做,全把结果预测成“否”,正确率也能有99%。因此我们要使用class_weight参数对样本标签进行一定的均衡,给 少量的标签更多的权重,让模型更偏向少数类,向捕获少数类的方向建模。该参数默认None,此模式表示自动给 与数据集中的所有标签相同的权重。 (你在倒入决策树的时候,你什么都不写的话,class_weight会自动帮你调整不平衡,使其为1:1,)

        有了权重之后,样本量就不再是单纯地记录数目,而是受输入的权重影响了,因此这时候剪枝,就需要搭配min_ weight_fraction_leaf这个基于权重的剪枝参数来使用。另请注意,基于权重的剪枝参数(例如min_weight_ fraction_leaf)将比不知道样本权重的标准(比如min_samples_leaf)更少偏向主导类。如果样本是加权的,则使 用基于权重的预修剪标准来更容易优化树结构,这确保叶节点至少包含样本权重的总和的一小部分。

3.重要的属性和接口 

属性是在模型训练之后,能够调用查看的模型的各种性质。对决策树来说,最重要的是feature_importances_,能够查看各个特征对模型的重要性。
sklearn中许多算法的接口都是相似的,比如说我们之前已经用到的fit和score,几乎对每个算法都可以使用。除了这两个接口之外,决策树最常用的接口还有apply和predict。apply中输入测试集返回每个测试样本所在的叶子节点的索引,predict输入测试集返回每个测试样本的标签。
在这里不得不提的是,所有接口中要求输入X_train和X_test的部分,输入的特征矩阵必须至少是一个二维矩阵。sklearn不接受任何一维矩阵作为特征矩阵被输入。如果你的数据的确只有一个特征,那必须用reshape(-1,1)来给矩阵增维;如果你的数据只有一个特征和一个样本,使用reshape(1,-1)来给你的数据增维。

#只需要输入测试集的特征
#apply返回每个测试样本所在的叶子节点的索引
clf.apply(Xtest)

#只需要输入测试集的特征
#predict返回每个测试样本的分类/回归结果
clf.predict(Xtest)

你可能感兴趣的:(机器学习,机器学习,决策树,python)