• 决策树算法-实战篇-鸢尾花及波士顿房价预测


    公号:码农充电站pro
    主页:https://codeshellme.github.io

    上篇文章介绍了决策树算法的理论篇,本节来介绍如何用决策树解决实际问题。

    决策树是常用的机器学习算法之一,决策树模型的决策过程非常类似人类做判断的过程,比较好理解。

    决策树可用于很多场景,比如金融风险评估,房屋价格评估,医疗辅助诊断等。

    要使用决策树算法,我们先来介绍一下 scikit-learn

    1,scikit-learn

    scikit-learn 是基于Python 的一个机器学习库,简称为sklearn,其中实现了很多机器学习算法。我们可以通过sklearn 官方手册 来学习如何使用它。

    sklearn 自带数据集

    要进行数据挖掘,首先得有数据。sklearn 库的datasets 模块中自带了一些数据集,可以方便我们使用。

    sklearn 自带数据集:

    1. 鸢尾花数据集:load_iris()
    2. 乳腺癌数据集:load_breast_cancer()
    3. 手写数字数据集:load_digits()
    4. 糖尿病数据集:load_diabetes()
    5. 波士顿房价数据集:load_boston()
    6. 体能训练数据集:load_linnerud()
    7. 葡萄酒产地数据集:load_wine()

    冒号后边是每个数据集对应的函数,可以使用相应的函数来导入数据。

    比如我们用如下代码导入鸢尾花数据集

    from sklearn.datasets import load_iris
    iris = load_iris()
    

    使用dir(iris) 查看iris 中包含哪些属性:

    >>> dir(iris)
    ['DESCR', 'data', 'feature_names', 'filename', 'frame', 'target', 'target_names']
    

    2,sklearn 中的决策树

    sklearn 库的tree 模块实现了两种决策树:

    • sklearn.tree.DecisionTreeClassifier 类:分类树的实现。
    • sklearn.tree.DecisionTreeRegressor 类:回归树的实现。

    分类树用于预测离散型数值,回归树用于预测连续性数值。

    sklearn 只实现了预剪枝,没有实现后剪枝

    DecisionTreeClassifier 类的构造函数

    def __init__(self, *,
           criterion="gini",
           splitter="best",
           max_depth=None,
           min_samples_split=2,
           min_samples_leaf=1,
           min_weight_fraction_leaf=0.,
           max_features=None,
           random_state=None,
           max_leaf_nodes=None,
           min_impurity_decrease=0.,
           min_impurity_split=None,
           class_weight=None,
           ccp_alpha=0.0):
    

    DecisionTreeClassifier 类的构造函数中的criterion 参数有2 个取值:

    • entropy:表示使用 ID3 算法(信息增益)构造决策树。
    • gini:表示使用CART 算法(基尼系数)构造决策树,为默认值。

    其它参数可使用默认值。

    sklearn 库中的决策分类树只实现了ID3 算法和CART 算法。

    DecisionTreeRegressor 类的构造函数

    def __init__(self, *,
          criterion="mse",
          splitter="best",
          max_depth=None,
          min_samples_split=2,
          min_samples_leaf=1,
          min_weight_fraction_leaf=0.,
          max_features=None,
          random_state=None,
          max_leaf_nodes=None,
          min_impurity_decrease=0.,
          min_impurity_split=None,
          ccp_alpha=0.0):
    

    DecisionTreeRegressor 类的构造函数中的criterion 参数有4 个取值:

    • mse:表示均方误差算法,为默认值。
    • friedman_mse:表示费尔德曼均方误差算法。
    • mae:表示平均误差算法。
    • poisson:表示泊松偏差算法。

    其它参数可使用默认值。

    3,构造分类树

    我们使用 sklearn.datasets 模块中自带的鸢尾花数据集 构造一颗决策树。


    在这里插入图片描述


    3.1,鸢尾花数据集

    鸢尾花数据集目的是通过花瓣的长度和宽度,及花萼的长度和宽度,预测出花的品种。

    这个数据集包含150条数据,将鸢尾花分成了三类(每类是50条数据),分别是:

    • setosa,用数字0 表示。
    • versicolor,用数字1 表示。
    • virginica,用数字2 表示。

    我们抽出3 条数据如下:

    5.1,3.5,1.4,0.2,0
    6.9,3.1,4.9,1.5,1
    5.9,3.0,5.1,1.8,2
    

    数据的含义:

    • 每条数据包含5 列,列与列之间用逗号隔开。
    • 从第1 列到第5 列,每列代表的含义是:花萼长度花萼宽度花瓣长度花瓣宽度花的品种
    • 在机器学习中,前4列称为特征值,最后1列称为目标值。我们的目的就是用特征值预测出目标值。

    将上面3 条数据,用表格表示就是:

    花萼长度 花萼宽度 花瓣长度 花瓣宽度 花的品种
    5.1 3.5 1.4 0.2 0
    6.9 3.1 4.9 1.5 1
    5.9 3.0 5.1 1.8 2

    3.2,构造分类树

    首先导入必要的类和函数:

    from sklearn.tree import DecisionTreeClassifier
    from sklearn.datasets import load_iris
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import accuracy_score
    

    其中:

    • DecisionTreeClassifier 类用于构造决策树。
    • load_iris() 函数用于导入数据。
    • train_test_split() 函数用于将数据集拆分成训练集与测试集。
    • accuracy_score() 函数用于为模型的准确度进行评分。

    导入数据集:

    iris = load_iris()   	# 准备数据集
    features = iris.data	# 获取特征集
    labels = iris.target    # 获取目标集
    

    将数据分成训练集测试集,训练集用于训练模型,测试集用于测试模型的准确度。

    train_features, test_features, train_labels, test_labels = 
    	train_test_split(features, labels, test_size=0.33, random_state=0)
    

    我们向train_test_split() 函数中传递了4 个参数,分别是:

    • features:特征集。
    • labels:目标集。
    • test_size=0.33:测试集数据所占百分比,剩下的数据分给训练集。
    • random_state=0:随机数种子。

    该函数返回4 个值,分别是:

    • train_features:训练特征集。
    • test_features:测试特征集。
    • train_labels:训练目标集。
    • test_labels:测试目标集。

    接下来构造决策树:

    # 用CART 算法构建分类树(你也可以使用ID3 算法构建)
    clf = DecisionTreeClassifier(criterion='gini')
    
    # 用训练集拟合构造CART分类树
    clf = clf.fit(train_features, train_labels)
    

    上面两句代码已经在注释中说明,最终我们得到了决策树clfclassifier 的缩写)。

    clf 预测测试集数据,test_predict 为预测结果:

    test_predict = clf.predict(test_features)
    

    计算预测结果的准确率:

    score = accuracy_score(test_labels, test_predict)
    score2 = clf.score(test_features, test_labels)
    print(score, score2)
    

    最终得出,sorcescore2都为 0.96,意思就是我们训练出的模型的准确率为96%

    函数accuracy_score()clf.score() 都可以计算模型的准确率,但注意这两个函数的参数不同。

    4,打印决策树

    为了清楚的知道,我们构造出的这个决策树cfl 到底是什么样子,可使用 graphviz 模块将决策树画出来。

    代码如下:

    from sklearn.tree import export_graphviz
    import graphviz
    
    # clf 为决策树对象
    dot_data = export_graphviz(clf)
    graph = graphviz.Source(dot_data)
    
    # 生成 Source.gv.pdf 文件,并打开
    graph.view()
    

    为了画出决策树,除了需要安装相应的 Python 模块外,还需要安装Graphviz 软件。

    由上面的代码,我们得到的决策树图如下:


    在这里插入图片描述


    我们以根节点为例,来解释一下每个方框里的四行数据(叶子节点是三行数据)都是什么意思。


    在这里插入图片描述


    四行数据所代表的含义:

    • 第一行X[3]<=0.75:鸢尾花数据集的特征集有4 个属性,所以对于X[n]中的n的取值范围为0<=n<=3X[0] 表示第1个属性,X[3] 表示第4 个属性。X[3]<=0.75 的意思就是当X[3] 属性的值小于等于0.75 的时候,走左子树,否则走右子树。
      • X[0] 表示花萼长度。
      • X[1] 表示花萼宽度。
      • X[2] 表示花瓣长度。
      • X[3] 表示花瓣宽度。
    • 第二行gini=0.666,表示当前的gini 系数值。
    • 第三行samples=100samples 表示当前的样本数。我们知道整个数据集有150 条数据,我们选择了0.33 百分比作为测试集,那么训练集的数据就占0.67,也就是100 条数据。根节点包含所有样本集,所以根节点的samples 值为100。
    • 第四行valuevalue 表示属于该节点的每个类别的样本个数,value 是一个数组,数组中的元素之和为samples 值。我们知道该数据集的目标集中共有3 个类别,分别为:setosaversicolorvirginica。所以:
      • value[0] 表示该节点中setosa 种类的数据量,即34。
      • value[1] 表示该节点中versicolor 种类的数据量,即31。
      • value[2] 表示该节点中virginica 种类的数据量,即35。

    4.1,打印特征重要性

    我们构造出来的决策树对象clf 中,有一个feature_importances_ 属性,如下:

    >>> clf.feature_importances_
    array([0, 0.02252929, 0.88894654, 0.08852417])
    

    clf.feature_importances_ 是一个数组类型,里边的元素分别代表对应特征的重要性,所有元素之和为1。元素的值越大,则对应的特征越重要。

    所以,从这个数组,我们可以知道,四个特征的重要性排序为:

    • 花瓣长度 > 花瓣宽度 > 花萼宽度 > 花萼长度

    我们可以使用下面这个函数,将该数组画成柱状图:

    import matplotlib.pyplot as plt
    import numpy as np
    
    # mode 是我们训练出的模型,即决策树对象
    # data 是原始数据集
    def plot_feature_importances(model, data):
        n_features = data.data.shape[1]
        plt.barh(range(n_features), model.feature_importances_, align='center')
        plt.yticks(np.arange(n_features), data.feature_names)
        plt.xlabel("Feature importance")
        plt.ylabel("Feature")
    
        plt.show()
    
    plot_feature_importances(clf, iris)
    

    下图是用plot_feature_importances() 函数生成的柱状图(红字是我添加的),从图中可以清楚的看出每个特种的重要性。

    在这里插入图片描述
    从该图中也可以看出,为什么决策树的根节点的特征是X[3]

    5,构造回归树

    我们已经用鸢尾花数据集构造了一棵分类树,下面我们用波士顿房价数据集构造一颗回归树。

    来看几条数据:

    在这里插入图片描述

    首先,我们认为房价是有很多因素影响的,在这个数据集中,影响房价的因素有13 个:

    1. "CRIM",人均犯罪率。
    2. "ZN",住宅用地占比。
    3. "INDUS",非商业用地占比。
    4. "CHAS",查尔斯河虚拟变量,用于回归分析。
    5. "NOX",环保指数。
    6. "RM",每个住宅的房间数。
    7. "AGE",1940 年之前建成的房屋比例。
    8. "DIS",距离五个波士顿就业中心的加权距离。
    9. "RAD",距离高速公路的便利指数。
    10. "TAX",每一万美元的不动产税率。
    11. "PTRATIO",城镇中教师学生比例。
    12. "B",城镇中黑人比例。
    13. "LSTAT",地区有多少百分比的房东属于是低收入阶层。

    数据中的最后一列的数据是房价:

    1. "MEDV" ,自住房屋房价的中位数。

    因为房价是一个连续值,而不是离散值,所以需要构建一棵回归树

    下面对数据进行建模,构造回归树使用DecisionTreeRegressor 类:

    from sklearn.tree import DecisionTreeRegressor
    from sklearn.datasets import load_boston
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error
    
    # 准备数据集
    boston = load_boston()
    
    # 获取特征集和房价
    features = boston.data
    prices = boston.target
    
    # 随机抽取33% 的数据作为测试集,其余为训练集
    train_features, test_features, train_price, test_price = 
        train_test_split(features, prices, test_size=0.33)
    
    # 创建CART回归树
    dtr = DecisionTreeRegressor()
    
    # 拟合构造CART回归树
    dtr.fit(train_features, train_price)
    
    # 预测测试集中的房价
    predict_price = dtr.predict(test_features)
    
    # 测试集的结果评价
    print('回归树准确率:', dtr.score(test_features, test_price)) 
    print('回归树r2_score:', r2_score(test_price, predict_price)) 
    print('回归树二乘偏差均值:', mean_squared_error(test_price, predict_price))
    print('回归树绝对值偏差均值:', mean_absolute_error(test_price, predict_price)) 
    

    最后四行代码是计算模型的准确度,这里用了4 种方法,输出如下:

    回归树准确率: 0.7030833400349499
    回归树r2_score: 0.7030833400349499
    回归树二乘偏差均值: 28.40730538922156
    回归树绝对值偏差均值: 3.6275449101796404
    

    需要注意,回归树与分类树预测准确度的方法不一样:

    • dtr.score():与分类树类似,不多说。
    • r2_score():表示R 方误差,结果与 dtr.score() 一样,取值范围是0 到1。
    • mean_squared_error():表示均方误差,数值越小,代表准确度越高。
    • mean_absolute_error():表示平均绝对误差,数值越小,代表准确度越高。

    可以用下面代码,将构建好的决策树画成图:

    from sklearn.tree import export_graphviz
    import graphviz
    
    # dtr 为决策树对象
    dot_data = export_graphviz(dtr)
    graph = graphviz.Source(dot_data)
    
    # 生成 Source.gv.pdf 文件,并打开
    graph.view()
    

    这棵二叉树比较大,你可以自己生成看一下。

    再来执行下面代码,看下特征重要性:

    import matplotlib.pyplot as plt
    import numpy as np
    
    # mode 是我们训练出的模型,即决策树对象
    # data 是原始数据集
    def plot_feature_importances(model, data):
        n_features = data.data.shape[1]
        plt.barh(range(n_features), model.feature_importances_, align='center')
        plt.yticks(np.arange(n_features), data.feature_names)
        plt.xlabel("Feature importance")
        plt.ylabel("Feature")
    
        plt.show()
    
    plot_feature_importances(dtr, boston)
    

    从生成的柱状图,可以看到LSTAT 对房价的影响最大:
    在这里插入图片描述

    6,关于数据准备

    本文中用到的数据是sklearn 中自带的数据,数据完整性比较好,所以我们没有对数据进行预处理。实际项目中,可能数据比较杂乱,所以在构建模型之前,先要对数据进行预处理。

    1. 要对数据有个清楚的认识,每个特征的含义。如果有特别明显的特征对我们要预测的目标集没有影响,则要将这些数据从训练集中删除。

    2. 如果某些特征有数据缺失,需要对数据进行补全,可以使用著名的 Pandas 模块对数据进行预处理。如果某特征的数据缺失严重,则应该将其从训练集中删除。对于需要补全的值:

      • 如果缺失的值是离散型数据,可以用出现次数最多的值去补全缺失值。
      • 如果缺失的值是连续型数据,可以用该特征的平均值去补全缺失值。
    3. 如果某些特征的值是字符串类型数据,则需要将这些数据转为数值型数据。

      • 可以使用 sklearn.feature_extraction 模块中的 DictVectorizer 类来处理(转换成数字0/1)。
    4. 在测试模型的准确率时,如果测试集中只有特征值没有目标值,就不好对测试结果进行验证。此时有两种方法来测试模型准确率:

      • 在构造模型之前,用 train_test_split() 函数将原始数据集(含有目标集)拆分成训练集和测试集。
      • 使用 sklearn.model_selection 模块中的 cross_val_score 函数进行K 折交叉验证来计算准确率。

    K 折交叉验证原理很简单

    1. 将数据集平均分成K 个等份,K 一般取10
    2. 使用K 份中的1 份作为测试数据,其余为训练数据,然后进行准确率计算。
    3. 进行多次以上步骤,求平均值。

    7,总结

    本篇文章介绍了如何用决策树来处理实际问题。主要介绍了以下知识点:

    • sklearn 是基于 Python 的一个机器学习库。
    • sklearn.datasets 模块中有一些自带数据集供我们使用。
    • sklearn.tree 中的两个类来构建分类树和回归树:
      • DecisionTreeClassifier 类:构造决策分类树,用于预测离散值。
      • DecisionTreeRegressor 类:构造决策回归树,用于预测连续值。
    • 分别介绍了两个类的构造函数中的 criterion 参数的含义。
    • 介绍了几个重要函数的用途:
      • train_test_split() 函数用于拆分数据集。
      • o.fit() 用于拟合决策树。(o 表示决策树对象)
      • o.predict() 用于预测数据。
      • o.score() 用于给模型的准确度评分。
      • accuracy_score() 函数用于给分类树模型评分。
      • r2_score() 函数用于给回归树模型评分。
      • mean_squared_error() 函数用于给回归树模型评分。
      • mean_absolute_error() 函数用于给回归树模型评分。
    • 介绍了如何给决策树画图。
    • 介绍了如何给特征重要性画图。

    (本节完。)


    推荐阅读:

    决策树算法-理论篇


    欢迎关注作者公众号,获取更多技术干货。

    码农充电站pro

  • 相关阅读:
    发现个atan2的正确使用方式
    Forward+ Shading架构
    fatal: unable to connect to gitee.com: gitee.com[0: 180.97.125.228]: errno=Unknown error 解决方案
    HDFS HA(高可用性)集群规划
    如何使用RTP引擎对语音编码进行转码
    关于 Angular 应用 tsconfig.json 中的 target 属性
    浅谈 Orbeon form builder 的权限控制
    关于 Angular 应用 tsconfig.json 中的 lib 属性
    orbeon form 通过 url 的方式同第三方应用集成的开发明细
    orbeon form 的配置介绍
  • 原文地址:https://www.cnblogs.com/codeshell/p/13984334.html
Copyright © 2020-2023  润新知