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


    目录

    一、初次简单使用

    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.导入我们的数据集

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

    2.查看我们的数据集

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

    wine=load_wine()

    查看一下红酒数据集 

    wine

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

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

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

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

     

    1. #这些特征的标题
    2. wine.feature_names

    1. #类别
    2. wine.target_names

    3.划分测试集和训练集 

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

    查看训练集

    Xtrain

    Xtrain.shape

     

    查看测试集

    Xtest

    查看测试集的标签

    Ytrain

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

    1. #第一步:实例化
    2. #classify,简写clf,分类器
    3. clf=tree.DecisionTreeClassifier(criterion="entropy")
    4. #第二步:将模型带入我们的分类器中进行训练
    5. clf=clf.fit(Xtrain,Ytrain)
    6. #第三步:给我们的训练结果打分
    7. #这个score就得到了我们的打分结果,返回预测的准确度accuracy
    8. score=clf.score(Xtest,Ytest)
    1. #这个score在我们上面每一次重新划分测试集和训练集之后都是会发生变化的
    2. #因为我们上面的train_test_split是随机划分测试集和训练集的,
    3. #所以说每一次导入的数据和模型都是不一样的
    4. #但是这个score每一次重新执行上面的三个步骤之后都会发生变化
    5. #这是因为我们的sklearn再每一次建树的时候,并没有选择全部的特征,而是选取一部分特征,从中选取不纯度相关指标最优的作为分支用的结点,
    6. #这样,每次生成的树也就不同了
    7. #也就是说假设有一个果农,想要栽培出一棵最好的苹果树,果农最好的方法并不是从一个最好的苹果中选取一个最饱满的种子,然后将这一棵种子种下,
    8. #这样不一定能够种出最好的果树
    9. #果农可以采用更好的方法,就是同时种下一批种子,等待这些种子全部生根发芽,然后从这片树中找到一棵最好的苹果树,
    10. #这也就是我们的sklearn所采用的的方法
    11. #但是这样会让我们的模型不稳定了,每次跑出来的结果都不一样了。
    12. #将在下面讲述如何解决
    13. score

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

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

    二、优化决策树 

    1.特征的贡献值

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

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

    2.重要参数 

    1.random_state & splitter

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

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

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

    将splitter设置为random的结果 

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

    这里树太大了,只截取了一部分 

     将splitter设置为best的结果 

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

     查看我们生成的树

    1. import graphviz
    2. dot_data = tree.export_graphviz(clf
    3. ,feature_names= feature_name
    4. ,class_names=["琴酒","雪莉","贝尔摩德"]
    5. ,filled=True
    6. ,rounded=True
    7. )
    8. graph = graphviz.Source(dot_data)
    9. graph

    2.剪枝参数 

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

    1. #我们的树对训练集的拟合程度如何?
    2. score_train = clf.score(Xtrain, Ytrain)
    3. 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个训练样本,这个节点才允许被分枝,否则分枝就不会发生。

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

    树太大了,只截了一部分 

     查看当前模型的打分结果

    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。

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

    1. import matplotlib.pyplot as plt
    2. test = []
    3. for i in range(10):
    4. #测试最大深度为多少的时候能让我们的树的score达到最高的值
    5. clf = tree.DecisionTreeClassifier(max_depth=i+1
    6. ,criterion="entropy"
    7. ,random_state=30
    8. ,splitter="random"
    9. )
    10. clf = clf.fit(Xtrain, Ytrain)
    11. score = clf.score(Xtest, Ytest)
    12. test.append(score)
    13. plt.plot(range(1,11),test,color="red",label="max_depth")
    14. plt.legend()
    15. plt.show()

    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)来给你的数据增维。

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

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

  • 相关阅读:
    中电金信技术实践|Redis哨兵原理及安装部署分享
    【SA8295P 源码分析 (一)】02 - SA8295P 的 LUN 及 分区表 配置详解
    Fastjson在实战中的检测与利用
    讲解器厂家深层互联重磅发布行业首个头戴式无线讲解器
    记一次 MySQL timestamp 精度问题的排查 → 过程有点曲折
    LabVIEW编程LabVIEW开发吉时利Keithley 7001开关例程与相关资料
    Euro-NCAP-2023 安全辅助避撞系统测试流程中文版
    MyBatis
    vivo 海量微服务架构最新实践
    GBase 8a MPP存储过程参考-2
  • 原文地址:https://blog.csdn.net/weixin_62684026/article/details/126794551