一、决策树概述

注:生产实践中,不使用决策树,太简单,而是使用决策树的升级版:集成学习算法
集成学习算法有:

  • Random Forest(随机森林)
  • Extremely Randomized Forest(极限随机森林)
  • Adaboost提升树
  • GBDT(梯度提升树)
  • XGBoost(极端梯度提升树)

注:企业重要决策,由于决策树很好的分析能力,在决策过程应用较多(比如:XGBoost), 可以选择特征

1、决策树概念

决策树思想的来源非常朴素,程序设计中的条件分支结构就是if-else结构,最早的决策树就是利用这类结构分割数据的一种分类学习方法。

  • 决策树算法采用的是自顶向下递归方法,其基本思想是以信息熵为度量构造一棵值下降最快的树,到叶子节点处熵值为零,此时每个叶节点中的实例都属于同一类。
  • 决策树是一种自上而下,对样本数据进行树形分类的过程,由结点有向边组成。结点分为内部结点叶结点,其中每个内部结点表示一个特征或属性叶结点表示类别。从顶部根结点开始,所有样本聚在一起。经过根结点的划分,样本被分到不同的子结点中。再根据子结点的特征进一步划分,直至所有样本都被归到某一个类别(即叶结点)中
  • 决策树:自顶向下,做一个信息熵下降最快的树,使得事件越来越确定。
  • 决策树算法的特点:决策树学习算法的最大优点是,它可以自学习。在学习的过程中,不需要使用者了解过多背景知识,只需要对训练实例进行较好的标注,就能够进行学习。从一类无序、无规则的事物 (概念 )中推理出决策树表示的分类规则。
  • 决策树分为两大类,回归树和分类树。
    • 回归树用于预测实数值,如明天的温度、用户的年龄、网页的相关程度;
    • 分类树用于分类标签值,如晴天/阴天/雾/雨、用户性别、网页是否是垃圾页面。
    • 回归树的结果加减是有意义的,如10岁+5岁-3岁=12岁,比如GBDT梯度提升树的核心就在于累加所有树的结果作为最终结果。
    • 分类树的结果加减则无意义,如男+男+女=到底是男是女?

决策树:

  • 是一种树形结构,本质是一颗由多个判断节点组成的树;
  • 其中每个内部节点表示一个属性上的判断;
  • 每个分支代表一个判断结果的输出;
  • 最后每个叶节点代表一种分类结果;
  • 决策树学习是以实例为基础的归纳;
  • 决策树学习采用的是自顶向下递归方法;

怎么理解这句话?通过一个对话例子

上面案例是女生通过定性的主观意识,把年龄放到最上面,那么如果需要对这一过程进行量化,该如何处理呢?
此时需要用到信息论中的知识:信息熵,信息增益

2、CART树(Category And Regression Tree)

CART是一棵二叉树,每一次分裂会产生两个子节点。CART树分为分类树和回归树。

  • 分类树:针对目标值为离散型的情况,比如预测一个动物是否是哺乳动物。

    • 如果是分类树,将选择能够最小化分裂后节点GINI值的分裂属性;
  • 回归树:针对目标值为连续值的情况,比如预测一个动物的年龄。
    • 如果是回归树,选择能够最小化两个节点样本均方误差的分裂属性。CART跟其他决策树算法一样,需要进行剪枝,才能防止算法过拟合从而保证算法的泛化性能。

二、分类树

sklearn.tree.DecisionTreeClassifier()

1、信息熵

物理学上,熵 Entropy 是“混乱”程度的量度。系统越有序,熵值越低;系统越混乱或者分散,熵值越高。
信息学上,1948年香农提出了信息熵(Entropy)的概念。

在信息论中,熵(英语:entropy)是接收的每条消息中包含的信息的平均量,又被称为信息熵、信源熵、平均自信息量。这里,“消息”代表来自分布或数据流中的事件、样本或特征。(熵最好理解为不确定性的量度而不是确定性的量度,因为越随机的信源的熵越大)

信息理论:

  1. 信息和消除不确定性是相联系的;
  2. 信息熵越大,信息越不确定,信息熵越小,信息越明确;
  3. 从信息的完整性上进行的描述:当系统的有序状态一致时,数据越集中的地方熵值越小,数据越分散的地方熵值越大;
  4. 从信息的有序性上进行的描述:当数据量一致时,系统越有序,熵值越低;系统越混乱或者分散,熵值越高;

信息熵(information entropy)是度量样本集合纯度最常用的一种指标。

假定当前样本集合 DDD 中第 kkk 类样本所占的比例为 pkp_kpk​ (k = 1, 2,. . . , |y|) ,

pk=CkCDp_k=\cfrac{C_k}{C_D}pk​=CD​Ck​​

  • CkC_kCk​ 是按目标值分类后第 kkk 类样本的数量;

  • CDC_DCD​为样本集合D的总数量;

则样本集合 DDD 的 “信息熵” 定义为:

Ent(D)=−∑k=1nCkCDlog2CkCD=−∑k=1npklog2pk=−(p1log2p1+p2log2p2+...+pnlog2pn)\color{violet}{Ent(D) = -\sum_{k=1}^{n}\cfrac{C_k}{C_D}log_2\cfrac{C_k}{C_D}=-\sum_{k=1}^{n}p_klog_2{p_k}=-(p_1log_2p_1+p_2log_2p_2+...+p_nlog_2p_n)}Ent(D)=−k=1∑n​CD​Ck​​log2​CD​Ck​​=−k=1∑n​pk​log2​pk​=−(p1​log2​p1​+p2​log2​p2​+...+pn​log2​pn​)

其中:Ent(D)Ent(D)Ent(D)的值越小,则样本集合 DDD 的纯度越高。单位为“比特”

案例01:
假设我们没有看世界杯的比赛,但是想知道哪支球队会是冠军,
我们只能猜测某支球队是或不是冠军,然后观众用对或不对来回答,
我们想要猜测次数尽可能少,你会用什么方法?
答案:
二分法:
假如有 16 支球队,分别编号,先问是否在 1-8 之间,如果是就继续问是否在 1-4 之间,
以此类推,直到最后判断出冠军球队是哪支。
如果球队数量是 16,我们需要问 4 次来得到最后的答案。那么世界冠军这条消息的信息熵就是 4比特。那么信息熵等于4,是如何进行计算的呢?

Ent(D)=−(p1∗log2p1+p2∗log2p2+...+p16∗log2p16)Ent(D) =-(p_1 * log_2p_1 + p_2 * log_2p_2 + ... + p_16 * log_2p_{16})Ent(D)=−(p1​∗log2​p1​+p2​∗log2​p2​+...+p1​6∗log2​p16​),
其中 p1p_1p1​, …, p16p_{16}p16​ 分别是这 16 支球队夺冠的概率。
当每支球队夺冠概率相等都是 116\cfrac{1}{16}161​ 的时:Ent(D)=−(16∗116∗log2116)=4Ent(D) = -(16 * \cfrac{1}{16} * log_2\cfrac{1}{16}) = 4Ent(D)=−(16∗161​∗log2​161​)=4
每个事件概率相同时,熵最大,这件事越不确定。

案例02:
篮球比赛里,有4个球队 {A,B,C,D} ,获胜概率分别为{1/2, 1/4, 1/8, 1/8}
求Ent(D)

2、分类树分类依据

2.1 信息增益

信息增益:以某特征划分数据集前后的熵的差值。熵可以表示样本集合的不确定性,熵越大,样本的不确定性就越大。因此可以使用划分前后集合熵的差值来衡量使用当前特征对于样本集合D划分效果的好坏。

信息增益:表示得知特征X的信息而使得类Y的信息熵减少的程度的量度。

一个属性的信息增益(或信息增益率、Gini系数的降低值)越大,表明该属性对样本的熵减少的能力越强,这个属性使得数据由不确定性变成确定性的能力越强。

计算机循环计算各个属性的各个样本点为裂分点时的信息增益,然后将信息增益最大的属性样本点作为本节点裂分点。

特征 aaa 对训练数据集 DDD 的信息增益 Gain(D,a)Gain(D,a)Gain(D,a) 定义为:集合 DDD 的信息熵 H(D)H(D)H(D) 与特征 aaa 给定条件下 DDD 的“信息条件熵” H(D∣a)H(D|a)H(D∣a) 之差,即:信息增益 = entroy(前) - entroy(后)。

Gain(D,a)=Ent(D)−Ent(D∣a)Gain(D,a)=Ent(D)-Ent(D|a)Gain(D,a)=Ent(D)−Ent(D∣a);

  • Ent(D)=−∑k=1nCkCDlog2CkCDEnt(D) = -\sum_{k=1}^{n}\cfrac{C_k}{C_D}log_2\cfrac{C_k}{C_D}Ent(D)=−∑k=1n​CD​Ck​​log2​CD​Ck​​;

    • nnn 表示按目标值分类后的类的总数量
    • CDC_DCD​为集合 DDD 的样本总数量,
    • CkC_kCk​为按目标值分类后第 kkk 类中样本的数量;
  • Ent(D∣a)=∑k=1nCDakCDEnt(Dak)=∑k=1nCDakCD[−∑i=1mCDakiCDaklog2CDakiCDak]=−∑k=1nCDakCD[∑i=1mCDakiCDaklog2CDakiCDak]\color{violet}{Ent(D|a) = \sum_{k=1}^n\cfrac{C_{D_a^k}}{C_D}Ent(D_a^k) = \sum_{k=1}^n\cfrac{C_{D_a^k}}{C_D}[-\sum_{i=1}^{m}\cfrac{C^i_{D_a^k}}{C_{D_a^k}}log_2\cfrac{C^i_{D_a^k}}{C_{D_a^k}}] = -\sum_{k=1}^n\cfrac{C_{D_a^k}}{C_D}[\sum_{i=1}^{m}\cfrac{C^i_{D_a^k}}{C_{D_a^k}}log_2\cfrac{C^i_{D_a^k}}{C_{D_a^k}}]}Ent(D∣a)=∑k=1n​CD​CDak​​​Ent(Dak​)=∑k=1n​CD​CDak​​​[−∑i=1m​CDak​​CDak​i​​log2​CDak​​CDak​i​​]=−∑k=1n​CD​CDak​​​[∑i=1m​CDak​​CDak​i​​log2​CDak​​CDak​i​​]
    • nnn 表示按条件 aaa 的分类后的一级类数量, CDakC_{D_a^k}CDak​​ 表示集合 DDD 在条件 aaa 的分类条件下,一级类 kkk 中包含的样本数量
    • mmm 表示在条件 aaa 的分类条件下,一级类 kkk 中包含的的二级类数量,CDakiC^i_{D_a^k}CDak​i​ 表示在条件a分类条件下,一级类 kkk 所包含的二级类 iii 中所包含的样品数量
    • 信息条件熵,即:在条件 aaa 的分类下,分出 a1,a2,...,ak,...,ana_1, a_2, ..., a_k, ..., a_na1​,a2​,...,ak​,...,an​ 组,先分别求出这 nnn 组各自的信息熵,然后加权平均得到总的信息熵。

对于特征 aaa 与 bbb 与 ccc 而言,如果 Gain(D,a)>Gain(D,b)>Gain(D,c)Gain(D,a)>Gain(D,b)>Gain(D,c)Gain(D,a)>Gain(D,b)>Gain(D,c),说明这几个特征对于数据集 DDD 的重要性而言 a>b>ca>b>ca>b>c 。在做特征选择或者数据分析的时候,我们应该把特征 aaa 当做第一个分类标准,然后再考虑特征 bbb,最后考虑特征 ccc。

2.2 信息增益率

以信息增益作为划分训练数据集的特征,存在偏向于优先选择取值较多的特征的问题。可以使用信息增益比对这一问题进行校正。

Gainr(D,a)=Gain(D,a)Ent(a)=Ent(D)−Ent(D∣a)Ent(a)Gain_r(D,a)=\dfrac{Gain(D,a)}{Ent(a)}=\dfrac{Ent(D)-Ent(D|a)}{Ent(a)}Gainr​(D,a)=Ent(a)Gain(D,a)​=Ent(a)Ent(D)−Ent(D∣a)​

优化后解决了ID3分支过程中总喜欢偏向选择值较多的 属性

2.3 基尼系数(Gini index)

Gini(p)=∑k=1Kpk(1−pk)=1−∑k=1Kpk2=1−∑k=1K(∣Ck∣∣D∣)2Gini(p)=\sum_{k=1}^Kp_k(1-p_k)=1-\sum_{k=1}^Kp^2_k=1-\sum_{k=1}^K(\dfrac{|C_k|}{|D|})^2Gini(p)=k=1∑K​pk​(1−pk​)=1−k=1∑K​pk2​=1−k=1∑K​(∣D∣∣Ck​∣​)2

使用Gini系数的效果总体上比前两者好一点

3、分类树算法

名称 分支方式 对比① 对比② 对比③ 对比④ 对比⑤ 对比⑥
ID3 信息增益 只能处理离散型变量 只进行分类 对样本特征缺失值敏感 每个节点可以产生多叉分支 每个特征在层级之间不会复用 通过剪枝来权衡树的准确性与泛化能力
C4.5 信息增益率 可以处理离散型变量
也可以处理连续型变量
只进行分类 可以对缺失值进行不同方式的处理 每个节点可以产生多叉分支 每个特征在层级之间j可以复用 通过剪枝来权衡树的准确性与泛化能力
CART Gini系数 可以处理离散型变量
也可以处理连续型变量
可以进行分类回归 可以对缺失值进行不同方式的处理 每个节点只能产生2个分支
最后会形成二叉树
每个特征在层级之间j可以复用 直接利用全部数据发现所有可能的树结构进行对比

比信息增益划分的更加仔细。

4、分类树的损失函数

假定样本的总类别为 KKK 个。对于决策树的某叶结点 AAA,假定该叶节点 AAA 中含有样本总数为 nnn,其中第 kkk 类的样本数目为 nk,k=1,2,…,Kn_k,k=1,2,…,Knk​,k=1,2,…,K,则 n=n1+n2+...+nKn=n_1+n_2+...+n_Kn=n1​+n2​+...+nK​

  • 若叶结点 AAA中, jjj 类样本数 nj=nn_j=nnj​=n 而其余 K−1K-1K−1 类的样本数都为 0,n1=n2=…=nj−1=nj+1=…=nK=00,n_1=n_2=…=n_{j-1}=n_{j+1}=…=n_K=00,n1​=n2​=…=nj−1​=nj+1​=…=nK​=0 ,称该叶结点为纯叶节点
  • 若叶结点 AAA中,各类样本的数量都相等, n1=n2=…=nj=…=nK=nKn_1=n_2=…=n_j=…=n_K=\dfrac{n}{K}n1​=n2​=…=nj​=…=nK​=Kn​,则称该叶结点为均叶节点
  • 纯叶节点的信息熵 Hp=0H_p=0Hp​=0,最小;
  • 均叶节点的信息熵 Hu=lnKH_u=lnKHu​=lnK,最大;
  • 对所有叶节点的信息熵求和,该值越小说明对样本的分类越精确;
  • 各叶结点包含的样本数目不同,可使用加权求信息熵和,由于该值越小越好,所以称之为损失函数

C(T)=∑t∈leafNt⋅Ht(T)\color{violet}{C(T)=\sum_{t∈leaf}N_t·H_t(T)}C(T)=t∈leaf∑​Nt​⋅Ht​(T)

为了避免出现过拟合的现象,我们要对决策树进行剪枝。
决策树的剪枝类似一种参数正则化的过程,其选择正则化的参数是树的叶子节点的个数。

设决策树 T 的叶子节点个数为 |T|,t 是树 T 的叶子节点,该叶节点有 NtN_tNt​ 个样本点,其中 k 类的样本点有 NtkN_{tk}Ntk​ 个,Ht(T)H_t(T)Ht​(T) 为叶节点 t 上的经验熵,α⩾0 为正则化系数,则包含剪枝的决策树的损失函数可以定义为:


其中

  • 经验熵为:

  • 右边第一项表示误差大小,第二项表示模型的复杂度,也就是用叶节点表示,防止过拟化。

  • 损失函数中的第一项表示模型对训练数据的预测误差,也就是模型的拟合程度,第二项表示模型的复杂程度,通过参数 α 控制二者的影响力。一旦 α 确定,那么我们只要选择损失函数最小的模型即可。

5、分类树算法优缺点

  • 优点:

    • 简单的理解和解释,树木可视化;
    • 需要很少的数据准备,其他技术通常需要数据归一化;
    • 决策树算法可以用于小数据集;
    • 决策树算法的时间复杂度较小,为用于训练决策树的数据点的对数;
    • 对缺失值不敏感。
    • 效率高,决策树只需要一次构建,反复使用,每一次预测的最大计算次数不超过决策树的深度。
  • 缺点:

    • 对连续性的字段比较难预测。
    • 决策树学习者可以创建不能很好地推广数据的过于复杂的树,容易发生过拟合;
    • 当类别太多时,错误可能就会增加的比较快。
    • 忽略了属性之间的相关性,在处理特征关联性比较强的数据时表现得不是太好;
    • 对于各类别样本数量不一致的数据,在决策树当中,信息增益的结果偏向于那些具有更多数值的特征;
  • 改进:

    • 随机森林(集成学习的一种);
    • 减枝cart算法(决策树Api中已经实现),降低过拟合现象;通过DecisionTreeClassifier()方法里的min_samples_leaf参数来调节;如果设定min_samples_leaf=3,那么samples<3的叶子节点会被删除,防止分类太细化,决策树层数过深,产生过拟合。

注:企业重要决策,由于决策树很好的分析能力,在决策过程应用较多, 可以选择特征

6、scikit-learn分类树算法Api

class sklearn.tree.DecisionTreeClassifier(criterion=’gini’, max_depth=None,random_state=None)

  • criterion

    • 特征选择标准
    • “gini"或者"entropy”,前者代表基尼系数,后者代表信息增益。默认"gini",即CART算法。
  • min_samples_split

    • 内部节点再划分所需最小样本数
    • 这个值限制了子树继续划分的条件,如果某节点的样本数少于min_samples_split,则不会继续再尝试选择最优特征来进行划分。 默认是2.如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。我之前的一个项目例子,有大概10万样本,建立决策树时,我选择了min_samples_split=10。可以作为参考。
  • min_samples_leaf

    • 叶子节点最少样本数
    • 这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。 默认是1,可以输入最少的样本数的整数,或者最少样本数占样本总数的百分比。如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。之前的10万样本项目使用min_samples_leaf的值为5,仅供参考。
  • max_depth

    • 决策树最大深度
    • 决策树的最大深度,默认可以不输入,如果不输入的话,决策树在建立子树的时候不会限制子树的深度。一般来说,数据少或者特征少的时候可以不管这个值。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。常用的可以取值10-100之间
  • random_state

    • 随机数种子

7、决策树算法案例

使用决策树算法时,特征数据值不需要进行去量纲化归一化标准化处理。

7.1 鸢尾花分类

import numpy as np
import pandas as pd
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
from sklearn import treeif __name__ == '__main__':# 一、提取数据iris = datasets.load_iris()# 1.1 提取特征数据值、目标值X = iris.datay = iris.targetfeature_names = iris.feature_names# 二、特征工程# 2.1 分割训练集、测试集X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8)# 2.2 查看数据X_train_012 = pd.DataFrame(X_train, columns=feature_names)print('X_train_012 =\n', X_train_012.head(5))# 2.2.0 查看所有列数据的标准差,标准差越大,说明该列数据波动性越大,越容易分类std_all_012 = X_train_012.std(axis=0)print('type(std_all_012) = ', type(std_all_012), '----std_all_012 = \n', std_all_012)# 2.2.1 petal length (cm) 列的数据X_train_petal_length = X_train_012.iloc[:, 2]X_train_petal_length = np.sort(X_train_petal_length)print('type(X_train_petal_length) = ', type(X_train_petal_length), '----X_train_petal_length = X_train_012.iloc[:, 2] =\n', X_train_petal_length)index_2 = np.argsort(X_train_012.iloc[:, 2])y_train_012 = y_train[index_2]print('样本所属分类:y_train_012 = \n', y_train_012)# 2.2.2 根据petal length (cm)将类型0的花全部分类出去后,剩下类型1、类型2的花X_train_12 = X_train_012[y_train != 0]print('X_train_12.shape = ', X_train_12.shape, '----X_train_12 =\n', X_train_12.head(5))# 2.2.3 查看所有列数据的标准差,标准差越大,说明该列数据波动性越大,越容易分类std_all_12 = X_train_12.std(axis=0)print('type(std_all_12) = ', type(std_all_12), '----std_all_12 = \n', std_all_12)# 2.2.4 petal width (cm) 列的数据X_train_petal_width = X_train_12.iloc[:, 3]X_train_petal_width = np.sort(X_train_petal_width)print('type(X_train_petal_width) = ', type(X_train_petal_width), '----X_train_petal_width = X_train_12.iloc[:, 2] =\n', X_train_petal_width)index_3 = np.argsort(X_train_12.iloc[:, 3])y_train_12 = y_train[y_train != 0][index_3]print('样本所属分类:y_train_12 = \n', y_train_12)# 三、算法工程# 3.1 实例化分类决策树算法dt = DecisionTreeClassifier(criterion='entropy', max_depth=10, min_samples_leaf=1)dt.fit(X_train, y_train)# 四、模型评估# 4.1 测试集预测y_predict = dt.predict(X_test)print('测试集真实值:y_test = ', y_test)print('测试集预测值:y_predict = ', y_predict)# 4.2 模型准确度predict_score = dt.score(X_test, y_test)print('模型准确度:predict_score = ', predict_score)accuracy_score = accuracy_score(y_test, y_predict)print('模型准确度:accuracy_score = ', accuracy_score)# 五、画决策树plt.figure(figsize=(15, 12))_ = tree.plot_tree(dt, filled=True, feature_names=feature_names, max_depth=10)plt.savefig('./tree.jpg')

打印结果:

X_train_012 =sepal length (cm)        ...         petal width (cm)
0                6.3        ...                      2.5
1                5.5        ...                      1.1
2                6.2        ...                      1.5
3                6.5        ...                      2.0
4                7.2        ...                      1.8
[5 rows x 4 columns]
type(std_all_012) =  <class 'pandas.core.series.Series'> ----std_all_012 = sepal length (cm)    0.834152
sepal width (cm)     0.433473
petal length (cm)    1.799313
petal width (cm)     0.777232
dtype: float64
type(X_train_petal_length) =  <class 'numpy.ndarray'> ----X_train_petal_length = X_train_012.iloc[:, 2] =[1.  1.1 1.2 1.2 1.3 1.3 1.3 1.3 1.3 1.3 1.4 1.4 1.4 1.4 1.4 1.4 1.4 1.41.4 1.4 1.4 1.4 1.5 1.5 1.5 1.5 1.5 1.5 1.6 1.6 1.6 1.6 1.6 1.6 1.6 1.71.7 1.7 1.9 1.9 3.  3.3 3.3 3.5 3.6 3.7 3.8 3.9 3.9 3.9 4.  4.  4.  4.4.1 4.2 4.2 4.2 4.3 4.4 4.5 4.5 4.5 4.5 4.5 4.5 4.5 4.5 4.6 4.6 4.6 4.74.8 4.8 4.8 4.9 4.9 4.9 4.9 4.9 5.  5.  5.  5.  5.1 5.1 5.1 5.1 5.1 5.15.1 5.2 5.2 5.3 5.4 5.5 5.5 5.5 5.6 5.6 5.6 5.6 5.6 5.6 5.7 5.7 5.8 5.85.8 5.9 6.  6.  6.1 6.1 6.3 6.4 6.6 6.7 6.7 6.9]
样本所属分类:y_train_012 = [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 21 2 2 1 1 2 2 1 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 22 2 2 2 2 2 2 2 2]
X_train_12.shape =  (80, 4) ----X_train_12 =sepal length (cm)        ...         petal width (cm)
0                6.3        ...                      2.5
1                5.5        ...                      1.1
2                6.2        ...                      1.5
3                6.5        ...                      2.0
4                7.2        ...                      1.8
[5 rows x 4 columns]
type(std_all_12) =  <class 'pandas.core.series.Series'> ----std_all_12 = sepal length (cm)    0.675211
sepal width (cm)     0.342145
petal length (cm)    0.856249
petal width (cm)     0.424831
dtype: float64
type(X_train_petal_width) =  <class 'numpy.ndarray'> ----X_train_petal_width = X_train_12.iloc[:, 2] =[1.  1.  1.  1.  1.  1.1 1.1 1.1 1.2 1.2 1.3 1.3 1.3 1.3 1.3 1.3 1.3 1.31.3 1.3 1.4 1.4 1.4 1.4 1.4 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.51.6 1.6 1.6 1.7 1.7 1.8 1.8 1.8 1.8 1.8 1.8 1.8 1.8 1.8 1.8 1.8 1.9 1.91.9 2.  2.  2.  2.  2.  2.  2.1 2.1 2.1 2.1 2.2 2.2 2.2 2.3 2.3 2.3 2.32.3 2.3 2.4 2.4 2.4 2.5 2.5 2.5]
样本所属分类:y_train_12 = [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 2 2 1 1 1 1 1 1 1 21 1 1 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 22 2 2 2 2 2]
测试集真实值:y_test =  [0 2 1 0 1 2 2 1 1 0 1 0 1 2 2 0 1 2 0 1 1 0 2 0 1 0 1 1 1 0]
测试集预测值:y_predict =  [0 2 1 0 1 2 2 1 1 0 1 0 1 2 2 0 1 2 0 1 1 0 2 0 1 0 1 1 1 0]
模型准确度:predict_score =  1.0
模型准确度:accuracy_score =  1.0

7.2 泰坦尼克号幸存者预测

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier, export_graphvizdef decision():"""决策树对泰坦尼克号进行预测生死"""# 获取数据titanic = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")print('type(titanic) = ', type(titanic), '----titanic = \n', titanic.head(5))# 一、数据处理# 1.1 找出特征数据值和目标值xDataFrame = titanic[['pclass', 'age', 'sex']]ySeries = titanic['survived']print('type(xDataFrame) = ', type(xDataFrame), '----特征数据值,xDataFrame = \n', xDataFrame.head(5))print('type(ySeries) = ', type(ySeries), '----目标值,ySeries = \n', ySeries.head(5))# 缺失值处理xDataFrame['age'].fillna(xDataFrame['age'].mean(), inplace=True)# 二、特征工程# 2.1 分割数据集到训练集合测试集xTrainDataFrame, xTestDataFrame, yTrainSeries, yTestSeries = train_test_split(xDataFrame, ySeries, test_size=0.25)print('type(xTrainDataFrame) = ', type(xTrainDataFrame), '----xTrainDataFrame = \n', xTrainDataFrame.head(5))print('type(xTestDataFrame) = ', type(xTestDataFrame), '----xTestDataFrame = \n', xTestDataFrame.head(5))print('type(yTrainSeries) = ', type(yTrainSeries), '----yTrainSeries = \n', yTrainSeries.head(5))print('type(yTestSeries) = ', type(yTestSeries), '----yTestSeries = \n', yTestSeries.head(5))# 2.2 特征抽取(字典数据类型,当特征值是类别时,进行ont-hot编码)dv = DictVectorizer(sparse=False)  # 实例化字典类型数据的特征抽取器(默认值为sparse=True,为True时返回sparse矩阵,当为False时,返回矩阵)xTrainDictList = xTrainDataFrame.to_dict(orient="records")  # 将DataFrame格式的xTrain转为Dict字典类型xTestDictList = xTestDataFrame.to_dict(orient="records")  # 将DataFrame格式的xTest转为Dict字典类型print('type(xTrainDictList) = ', type(xTrainDictList), '----xTrainDictList[0] = \n', xTrainDictList[0])xTrainNdArray = dv.fit_transform(xTrainDictList)  # 训练集特征抽取,返回一个ndarray格式的ont-hot编码后的xTrainxTestNdArray = dv.transform(xTestDictList);  # 测试集特征抽取featureNamesList = dv.get_feature_names()print('type(featureNamesList) = ', type(featureNamesList), '----featureNamesList = \n', featureNamesList)print('type(xTrainNdArray) = ', type(xTrainNdArray), '----xTrainNdArray = \n', xTrainNdArray)print('type(xTestNdArray) = ', type(xTestNdArray), '----xTestNdArray = \n', xTestNdArray)# 三、算法工程# 3.1 实例化一个决策树估计器对象dec_estimator = DecisionTreeClassifier(criterion='gini', max_depth=5)  # 一般使用默认的gini系数,max_depth为决策树层数# 3.2 调用fit方法,进行训练dec_estimator.fit(xTrainNdArray, yTrainSeries)# 四、模型评估# 4.1 数据预测,得出预测结果predictTestSeries = dec_estimator.predict(xTestNdArray)print('type(predictTestSeries) = ', type(predictTestSeries), '----predictTestSeries = \n', predictTestSeries)# 4.2 计算准确率predictScore = dec_estimator.score(xTestNdArray, yTestSeries)  # 输入”测试集“的特征数据值、目标值print('type(predictScore) = ', type(predictScore), '----predictScore = ', predictScore)# 4.3 导出决策树的结构文件(dot格式)export_graphviz(dec_estimator, out_file="./tree.dot", feature_names=['年龄', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', '女性', '男性'])# windows安装graphviz软件,运行命令(dot -Tpng tree.dot -o tree.png)将dot文件转换为pdf、png,如果出现“Format: "png" not recognized. Use one of:”错误提示,则在管理员模式下打开cmd窗口,输入"dot -c",然后再运行命令。# http://webgraphviz.com/在线显示图片return Noneif __name__ == "__main__":decision()

dec_estimator = DecisionTreeClassifier(criterion=‘entropy’, max_depth=2)参数下的tree.dot文件转为tree.png图片:

dec_estimator = DecisionTreeClassifier(criterion=‘entropy’, max_depth=5)参数下的tree.dot文件转为tree.png图片:


dec_estimator = DecisionTreeClassifier(criterion=‘gini’, max_depth=10)参数下的tree.dot文件转为tree.png图片:

打印结果:

type(titanic) =  <class 'pandas.core.frame.DataFrame'> ----titanic = row.names pclass  survived   ...        ticket   boat     sex
0          1    1st         1   ...    24160 L221      2  female
1          2    1st         0   ...           NaN    NaN  female
2          3    1st         0   ...           NaN  (135)    male
3          4    1st         0   ...           NaN    NaN  female
4          5    1st         1   ...           NaN     11    male
[5 rows x 11 columns]type(xDataFrame) =  <class 'pandas.core.frame.DataFrame'> ----特征数据值,xDataFrame = pclass      age     sex
0    1st  29.0000  female
1    1st   2.0000  female
2    1st  30.0000    male
3    1st  25.0000  female
4    1st   0.9167    maletype(ySeries) =  <class 'pandas.core.series.Series'> ----目标值,ySeries = 0    1
1    0
2    0
3    0
4    1
Name: survived, dtype: int64type(xTrainDataFrame) =  <class 'pandas.core.frame.DataFrame'> ----xTrainDataFrame = pclass        age   sex
1128    3rd  31.194181  male
207     1st  31.194181  male
638     3rd  24.000000  male
1202    3rd  31.194181  male
127     1st  25.000000  maletype(xTestDataFrame) =  <class 'pandas.core.frame.DataFrame'> ----xTestDataFrame = pclass        age     sex
258     1st  18.000000  female
1274    3rd  31.194181    male
695     3rd  18.000000  female
10      1st  47.000000    male
220     1st  18.000000  femaletype(yTrainSeries) =  <class 'pandas.core.series.Series'> ----yTrainSeries = 1128    0
207     1
638     0
1202    0
127     1
Name: survived, dtype: int64
type(yTestSeries) =  <class 'pandas.core.series.Series'> ----yTestSeries = 258     1
1274    0
695     0
10      0
220     1
Name: survived, dtype: int64type(xTrainDictList) =  <class 'list'> ----xTrainDictList[0] = {'pclass': '3rd', 'age': 31.19418104265403, 'sex': 'male'}type(featureNamesList) =  <class 'list'> ----featureNamesList = ['age', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', 'sex=female', 'sex=male']type(xTrainNdArray) =  <class 'numpy.ndarray'> ----xTrainNdArray = [[31.19418104  0.          0.          1.          0.          1.        ][31.19418104  1.          0.          0.          0.          1.        ][24.          0.          0.          1.          0.          1.        ]...[24.          0.          0.          1.          1.          0.        ][11.          0.          0.          1.          1.          0.        ][31.19418104  0.          0.          1.          1.          0.        ]]type(xTestNdArray) =  <class 'numpy.ndarray'> ----xTestNdArray = [[18.          1.          0.          0.          1.          0.        ][31.19418104  0.          0.          1.          0.          1.        ][18.          0.          0.          1.          1.          0.        ]...[22.          0.          0.          1.          1.          0.        ][31.19418104  0.          0.          1.          0.          1.        ][31.19418104  0.          0.          1.          0.          1.        ]]type(predictTestSeries) =  <class 'numpy.ndarray'> ----predictTestSeries = [1 0 0 0 1 0 0 1 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 10 0 1 0 0 1 1 0 1 0 0 0 0 1 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 00 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 10 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 00 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 00 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 10 0 1 0 0 0 0 1 0 0 0 0 1 1 0 0 1 0 1 0 1 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1 00 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 10 0 1 0 0 1 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0]type(predictScore) =  <class 'numpy.float64'> ----predictScore =  0.8297872340425532

三、回归树

sklearn.tree.DecisionTreeRegressor()

  • 回归决策树算法不是构建方程,原理类似分类决策树。

四、分类树 v.s. 回归树

1、分类树总体流程

  • 我们以对人的性别预测为例来说明,假定训练集中有四个人A、B、C、D,性别分别是男,女(目标值),feature(特征)有“在网时长”、“购物金额”。
  • 我们知道C4.5分类树在每次分枝时,是穷举每一个feature的每一个阈值,找最好的分割点,即该分割点使得按照feature<=阈值,和feature>阈值为条件分成的两个分枝时的信息熵增益最大,即:特征 aaa 对训练数据集 DDD 的信息增益 Gain(D,a)=Ent(D)−Ent(D∣a)Gain(D,a)=Ent(D)-Ent(D|a)Gain(D,a)=Ent(D)−Ent(D∣a)。按照该标准分枝得到两个新节点。
  • 用同样方法继续分枝直到所有人都被分入性别唯一的叶子节点,或达到预设的终止条件,若最终叶子节点中的性别不唯一,则以多数人的性别作为该叶子节点的性别。

2、回归树总体流程

  • 我们以对人的年龄预测为例来说明,假定训练集中有四个人A、B、C、D,年龄分别是14,16,24,26(目标值),feature(特征)有“在网时长”、“购物金额”。
  • 不过在每个节点(不一定是叶子节点)都会得一个预测值,该预测值等于属于这个节点的所有人年龄的平均值。分枝时穷举每一个feature的每个阈值,找最好的分割点,但衡量最好的标准不再是最大熵,而是最小化均方误差,即该分割点使得按照feature<=阈值,和feature>阈值为条件分成的两个分枝的均方误差 1n∑i=1n(xi−μ)2\cfrac{1}{n}\sum^n_{i=1}(x_i-μ)^2n1​∑i=1n​(xi​−μ)2 之和最小。
  • 用同样方法继续分枝直到每个叶子节点上人的年龄都唯一或者达到预设的终止条件(如叶子个数上限),若最终叶子节点上人的年龄不唯一,则以该节点上所有人的平均年龄做为该叶子节点的预测年龄。

五、随机森林(样本随机,特征随机)

集成学习方法:通过建立几个模型组合的来解决单一预测问题。它的工作原理是生成多个分类器/模型,各自独立地学习和作出预测。这些预测最后结合成单预测,因此优于任何一个单分类的做出预测。

随机森林:是一个包含多个决策树的分类器,并且其输出的类别是由个别树输出的类别的众数而定,即所有决策树投票决定目标值的类别。
数据越复杂,随机森林的优势越明显,因为随机森林估计器中有很多超参数可以进行调优。

1、为什么使用随机森林

  1. 随机森林既可以用于分类问题,也可以用于回归问题;
  2. 过拟合是个关键的问题,可能会让模型的结果变得糟糕,但是对于随机森林来说,如果随机森林的树足够多,那么分类器就不会过拟合模型;
  3. 随机森林分类器可以处理缺失值;
  4. 随机森林分类器可以用分类值建模;

2、随机森林建造过程

随机森林中每棵树的建造过程:

  • NNN 来表示训练样本的总数量,MMM 表示特征总数目。
  • 随机选出 mmm 个特征用于该棵决策树,m<<Mm<<Mm<<M(mmm 远小于 MMM),mmm 过大容易过拟合。
  • 从总体的 NNN 个训练样本中以有放回抽样的方式随机取样 NNN 次,形成一个训练集(即bootstrap取样),并用未抽到的样本作测试集,评估其误差。
  • 在随机森林算法中,不用考虑各个特征之间的耦合关系(不需要用PCA处理),因为每棵树的 mmm 个特征是随机选出的,随机森林里的所有决策树一起可以消除特征的耦合影响;

3、随机森林和单棵树的关系

  • 随机森林里的所有树可以都使用决策树分类器;
  • 随机森林里的树也可以使用SVM、Logistic回归等其他分类器,习惯上,这些分类器组成的“总分类器”仍然叫做随机森林。

4、为什么要随机抽样训练集?

如果不进行随机抽样,每棵树的训练集都一样,那么最终训练出的树分类结果也是完全一样的。

5、为什么要有放回地抽样?

如果不是有放回的抽样,那么每棵树的训练样本都是不同的,都是没有交集的,这样每棵树都是“有偏的”,都是绝对“片面的”(当然这样说可能不对),也就是说每棵树训练出来都是有很大的差异的;而随机森林最后分类取决于多棵树(弱分类器)的投票表决。

6、随机森林分类器Api

class sklearn.ensemble.RandomForestClassifier(n_estimators=10, criterion=’gini’, max_depth=None, bootstrap=True, andom_state=None)

  • n_estimators:integer,optional(default = 10) 森林里的树木数量,实践中经验取值为:120,200,300,500,800,1200
  • criteria:string,可选(default =“gini”)分割特征的测量方法,一般使用默认的gini系数,比信息增益(entropy)划分准确一些;
  • max_depth:integer或None,可选(默认=无)树的最大深度
  • bootstrap:boolean,optional(default = True)是否在构建树时使用放回抽样
  • max_features:(default = auto),每个决策树的最大特征数量,
    • max_features=‘auto’:max_features=sqrt(n_features)
    • max_features=‘sqrt’:max_features=sqrt(n_features)
    • max_features=‘log2’:max_features=log2(n_features)
    • None:max_features = n_features

随机森林模型是稳健的:随机森林分类器比较容易调参,参数在一个很宽的范围内都能达到差不多的效果。相对比的,SVM就没那么稳健,SVM算法的参数取值里只有少数几个值能使得模型效果不错,参数稍微改动一下,模型效果就千差万别,相对不容易把握。

7、随机森林案例

import pandas as pd
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier, export_graphviz
from sklearn.ensemble import RandomForestClassifierdef decision():"""决策树对泰坦尼克号进行预测生死"""# 获取数据titanic = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")print('type(titanic) = ', type(titanic), '----titanic = \n', titanic.head(5))# 一、数据处理# 1.1 找出特征数据值和目标值xDataFrame = titanic[['pclass', 'age', 'sex']]ySeries = titanic['survived']print('type(xDataFrame) = ', type(xDataFrame), '----特征数据值,xDataFrame = \n', xDataFrame.head(5))print('type(ySeries) = ', type(ySeries), '----目标值,ySeries = \n', ySeries.head(5))# 缺失值处理xDataFrame['age'].fillna(xDataFrame['age'].mean(), inplace=True)# 二、特征工程# 2.1 分割数据集到训练集合测试集xTrainDataFrame, xTestDataFrame, yTrainSeries, yTestSeries = train_test_split(xDataFrame, ySeries, test_size=0.25)print('type(xTrainDataFrame) = ', type(xTrainDataFrame), '----xTrainDataFrame = \n', xTrainDataFrame.head(5))print('type(xTestDataFrame) = ', type(xTestDataFrame), '----xTestDataFrame = \n', xTestDataFrame.head(5))print('type(yTrainSeries) = ', type(yTrainSeries), '----yTrainSeries = \n', yTrainSeries.head(5))print('type(yTestSeries) = ', type(yTestSeries), '----yTestSeries = \n', yTestSeries.head(5))# 2.2 特征抽取(字典数据类型,当特征值是类别时,进行ont-hot编码)dv = DictVectorizer(sparse=False)  # 实例化字典类型数据的特征抽取器(默认值为sparse=True,为True时返回sparse矩阵,当为False时,返回矩阵)xTrainDictList = xTrainDataFrame.to_dict(orient="records")  # 将DataFrame格式的xTrain转为Dict字典类型xTestDictList = xTestDataFrame.to_dict(orient="records")  # 将DataFrame格式的xTest转为Dict字典类型print('type(xTrainDictList) = ', type(xTrainDictList), '----xTrainDictList[0] = \n', xTrainDictList[0])xTrainNdArray = dv.fit_transform(xTrainDictList)  # 训练集特征抽取,返回一个ndarray格式的ont-hot编码后的xTrainxTestNdArray = dv.transform(xTestDictList);  # 测试集特征抽取featureNamesList = dv.get_feature_names()print('type(featureNamesList) = ', type(featureNamesList), '----featureNamesList = \n', featureNamesList)print('type(xTrainNdArray) = ', type(xTrainNdArray), '----xTrainNdArray = \n', xTrainNdArray)print('type(xTestNdArray) = ', type(xTestNdArray), '----xTestNdArray = \n', xTestNdArray)# 三、算法工程(决策树)# # 3.1 实例化一个决策树估计器对象# dec_estimator = DecisionTreeClassifier(criterion='entropy', max_depth=2)  # 默认使用gini系数,或采用“entropy”信息增益,max_depth为决策树层数# # 3.2 调用fit方法,进行训练# dec_estimator.fit(xTrainNdArray, yTrainSeries)## # 四、模型评估# # 4.1 数据预测,得出预测结果# predictTestSeries = dec_estimator.predict(xTestNdArray)# # 4.2 计算准确率# predictScore = dec_estimator.score(xTestNdArray, yTestSeries)  # 输入”测试集“的特征数据值、目标值# # 4.3 导出决策树的结构文件(dot格式)# export_graphviz(dec_estimator, out_file="./tree.dot", feature_names=['年龄', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', '女性', '男性'])# # windows安装graphviz软件,运行命令(dot -Tpng tree.dot -o tree.png)将dot文件转换为pdf、png,如果出现“Format: "png" not recognized. Use one of:”错误提示,则在管理员模式下打开cmd窗口,输入"dot -c",然后再运行命令。# 三、算法工程(随机森林)# 3.1 实例化一个随机森林估计器对象(随机森林无法导出决策树的结构文件)rf = RandomForestClassifier()# 3.2 网格搜索进行超参数调优,构造一些参数的值进行搜索param = {"n_estimators": [120, 200, 300, 500, 800, 1200], "max_depth": [5, 8, 15, 25, 30]}# 网格搜索与交叉验证gc = GridSearchCV(rf, param_grid=param, cv=2)gc.fit(xTrainNdArray, yTrainSeries)# 四、模型评估predictTestSeries = gc.predict(xTestNdArray)scoreTest = gc.score(xTestNdArray, yTestSeries)print("在测试集上的预测结果,predictTestSeries =\n", predictTestSeries)print("在测试集上准确率,scoreTest = ", scoreTest)print("查看选择的参数模型:", gc.best_params_)return Noneif __name__ == "__main__":decision()

打印结果:

type(titanic) =  <class 'pandas.core.frame.DataFrame'> ----titanic = row.names pclass  survived   ...        ticket   boat     sex
0          1    1st         1   ...    24160 L221      2  female
1          2    1st         0   ...           NaN    NaN  female
2          3    1st         0   ...           NaN  (135)    male
3          4    1st         0   ...           NaN    NaN  female
4          5    1st         1   ...           NaN     11    male
[5 rows x 11 columns]type(xDataFrame) =  <class 'pandas.core.frame.DataFrame'> ----特征数据值,xDataFrame = pclass      age     sex
0    1st  29.0000  female
1    1st   2.0000  female
2    1st  30.0000    male
3    1st  25.0000  female
4    1st   0.9167    maletype(ySeries) =  <class 'pandas.core.series.Series'> ----目标值,ySeries = 0    1
1    0
2    0
3    0
4    1
Name: survived, dtype: int64type(xTrainDataFrame) =  <class 'pandas.core.frame.DataFrame'> ----xTrainDataFrame = pclass        age   sex
213     1st  31.194181  male
1243    3rd  31.194181  male
108     1st  44.000000  male
254     1st  61.000000  male
1198    3rd  31.194181  maletype(xTestDataFrame) =  <class 'pandas.core.frame.DataFrame'> ----xTestDataFrame = pclass        age     sex
836     3rd  37.000000    male
1290    3rd  31.194181    male
1233    3rd  31.194181  female
892     3rd  31.194181    male
62      1st  31.194181    maletype(yTrainSeries) =  <class 'pandas.core.series.Series'> ----yTrainSeries = 213     0
1243    0
108     1
254     0
1198    0
Name: survived, dtype: int64type(yTestSeries) =  <class 'pandas.core.series.Series'> ----yTestSeries = 836     0
1290    0
1233    0
892     0
62      0
Name: survived, dtype: int64type(xTrainDictList) =  <class 'list'> ----xTrainDictList[0] = {'pclass': '1st', 'age': 31.19418104265403, 'sex': 'male'}type(featureNamesList) =  <class 'list'> ----featureNamesList = ['age', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', 'sex=female', 'sex=male']type(xTrainNdArray) =  <class 'numpy.ndarray'> ----xTrainNdArray = [[31.19418104  1.          0.          0.          0.          1.        ][31.19418104  0.          0.          1.          0.          1.        ][44.          1.          0.          0.          0.          1.        ]...[31.19418104  0.          0.          1.          0.          1.        ][31.19418104  0.          0.          1.          1.          0.        ][64.          1.          0.          0.          1.          0.        ]]type(xTestNdArray) =  <class 'numpy.ndarray'> ----xTestNdArray = [[37.          0.          0.          1.          0.          1.        ][31.19418104  0.          0.          1.          0.          1.        ][31.19418104  0.          0.          1.          1.          0.        ]...[31.19418104  0.          0.          1.          0.          1.        ][26.          0.          0.          1.          0.          1.        ][ 8.          0.          1.          0.          1.          0.        ]]在测试集上的预测结果,predictTestSeries =[0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 11 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 00 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0 1 0 0 0 0 10 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 00 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 01 0 0 1 0 0 0 1 0 1 0 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 00 0 1 1 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 10 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 01 0 1 0 0 1 0 0 0 1 1 0 1 1 1 0 0 0 1 0 0 0 1 1 0 1 1 1 0 1 0 0 1]在测试集上准确率,scoreTest =  0.8237082066869301查看选择的参数模型: {'max_depth': 5, 'n_estimators': 300}

8、使用随机森林计算特征重要度

随机森林是常用的衡量特征重要性方法:计算正例经过的结点,使用经过节点的数目、经过节点的gini系数和等指标。或者,随机替换一列数据,重新建立决策树,计算模型的正确率变化,从而考虑这一列特征的重要性。

  • selection frequency
  • gini importance
  • permutation importance

9、随机森林的优缺点

9.1 随机森林的优点

  • 在当前所有算法中,具有极好的准确率
  • 能够有效地运行在大数据集上(“大”体现在样本数、特征数);
  • 能够处理具有高维特征的输入样本,而且不需要降维
  • 能够评估各个特征在分类问题上的重要性;
  • 对于缺省值问题也能够获得很好得结果;
  • 随机森林是使用最多的一种机器学习算法
  • 由于采用了集成算法,本身精度比大多数单个算法要好,所以准确性高
  • 在测试集上表现良好,由于两个随机性的引入,使得随机森林不容易陷入过拟合(样本随机,特征随机)
  • 在工业上,由于两个随机性的引入,使得随机森林具有一定的抗噪声能力,对比其他算法具有一定优势
  • 由于树的组合,使得随机森林可以处理非线性数据,本身属于非线性分类(拟合)模型
  • 它能够处理很高维度(feature很多)的数据,并且不用做特征选择,对数据集的适应能力强:既能处理离散型数据,也能处理连续型数据,数据集无需规范化
  • 训练速度快,可以运用在大规模数据集上
  • 可以处理缺省值(单独作为一类),不用额外处理
  • 由于有袋外数据(OOB),可以在模型生成过程中取得真实误差的无偏估计,且不损失训练数据量
  • 在训练过程中,能够检测到feature间的互相影响,且可以得出feature的重要性,具有一定参考意义
  • 由于每棵树可以独立、同时生成,容易做成并行化方法
  • 由于实现简单、精度高、抗过拟合能力强,当面对非线性数据时,适于作为基准模型

8.2 随机森林的缺点

  • 超参数调优,找不到合适的参数组合来调优。
  • 当随机森林中的决策树个数很多时,训练时需要的空间和时间会比较大
  • 随机森林中还有许多不好解释的地方,有点算是黑盒模型
  • 在某些噪音比较大的样本集上,RF的模型容易陷入过拟合

六、极限森林(Extremely Randomized Forest)

决策树,进行裂分时候,根据信息增益最大进行裂分,刻板, 情深不寿,慧极必伤。

极限森林: 1、样本随机 2、分裂条件随机(每次裂分不是按照最好的裂分条件裂分,即不是按照信息增益最大值裂分)

  • 像在随机森林中一样,使用候选特征的随机子集,但不是寻找最有区别的阈值,
  • 而是为每个候选特征随机绘制阈值,
  • 并选择这些随机生成的阈值中的最佳阈值作为划分规则。
from sklearn.ensemble import RandomForestClassifier, ExtraTreesClassifier
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifierif __name__ == "__main__":"""极限森林对泰坦尼克号进行预测生死"""# 获取数据wine = datasets.load_wine()# 一、数据处理# 1.1 找出特征数据值和目标值X = wine['data']y = wine['target']print('type(X) = ', type(X), '----特征数据值,X = \n', X)print('type(y) = ', type(y), '----目标值,y = \n', y)# 二、特征工程# 2.1 分割数据集到训练集合测试集x_train_Ndarray, x_test_Ndarray, y_train_Ndarray, y_test_Ndarray = train_test_split(X, y, test_size=0.2)print('type(x_train_Ndarray) = ', type(x_train_Ndarray), '----x_train_Ndarray = \n', x_train_Ndarray)print('type(x_test_Ndarray) = ', type(x_test_Ndarray), '----x_test_Ndarray = \n', x_test_Ndarray)print('type(y_train_Ndarray) = ', type(y_train_Ndarray), '----y_train_Ndarray = \n', y_train_Ndarray)print('type(y_test_Ndarray) = ', type(y_test_Ndarray), '----y_test_Ndarray = \n', y_test_Ndarray)# 三、算法工程(极限森林)# 3.1 实例化一个极限森林估计器对象et = ExtraTreesClassifier(n_estimators=100)# 3.2 调用fit方法,进行训练et.fit(x_train_Ndarray, y_train_Ndarray)# 3.3 计算准确率score = et.score(x_test_Ndarray, y_test_Ndarray)  # 输入”测试集“的特征数据值、目标值print("单个极限森林的准确度:score = ", score)# 四、对比模型01:算法工程(随机森林)# 4.1 实例化一个随机森林估计器对象rf = RandomForestClassifier(n_estimators=100)# 4.2 调用fit方法,进行训练rf.fit(x_train_Ndarray, y_train_Ndarray)# 4.3 计算准确率score01 = rf.score(x_test_Ndarray, y_test_Ndarray)  # 输入”测试集“的特征数据值、目标值print("单个随机森林的准确度:score01 = ", score01)# 五、对比模型0:2:随机多次创建决策树,计算准确率平均值score02 = 0for i in range(100):X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)dt_clf = DecisionTreeClassifier()dt_clf.fit(X_train, y_train)score02 += dt_clf.score(X_test, y_test)score02 = score02 / 100print('决策树多次运行准确率:score02 = ', score02)# 六、对比模型03:随机多次创建随机森林,计算准确率平均值score03 = 0for i in range(100):X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)clf = RandomForestClassifier(n_estimators=100)clf.fit(X_train, y_train)score03 += clf.score(X_test, y_test)score03 = score03 / 100print('随机森林多次运行准确率:score03 = ', score03)# 七、对比模型03:随机多次创建随机森林,计算准确率平均值score04 = 0for i in range(100):X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)clf = RandomForestClassifier(n_estimators=100)clf.fit(X_train, y_train)score04 += clf.score(X_test, y_test)score04 = score04 / 100print('极限森林多次运行准确率:score04 = ', score04)

打印结果:

type(X) =  <class 'numpy.ndarray'> ----特征数据值,X = [[1.423e+01 1.710e+00 2.430e+00 ... 1.040e+00 3.920e+00 1.065e+03][1.320e+01 1.780e+00 2.140e+00 ... 1.050e+00 3.400e+00 1.050e+03][1.316e+01 2.360e+00 2.670e+00 ... 1.030e+00 3.170e+00 1.185e+03]...[1.327e+01 4.280e+00 2.260e+00 ... 5.900e-01 1.560e+00 8.350e+02][1.317e+01 2.590e+00 2.370e+00 ... 6.000e-01 1.620e+00 8.400e+02][1.413e+01 4.100e+00 2.740e+00 ... 6.100e-01 1.600e+00 5.600e+02]]
type(y) =  <class 'numpy.ndarray'> ----目标值,y = [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 11 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 11 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 22 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
type(x_train_Ndarray) =  <class 'numpy.ndarray'> ----x_train_Ndarray = [[1.208e+01 1.330e+00 2.300e+00 ... 1.070e+00 3.210e+00 6.250e+02][1.420e+01 1.760e+00 2.450e+00 ... 1.050e+00 2.850e+00 1.450e+03][1.237e+01 1.070e+00 2.100e+00 ... 1.040e+00 2.770e+00 6.600e+02]...[1.358e+01 2.580e+00 2.690e+00 ... 7.400e-01 1.800e+00 7.500e+02][1.237e+01 9.400e-01 1.360e+00 ... 1.050e+00 1.820e+00 5.200e+02][1.388e+01 1.890e+00 2.590e+00 ... 8.800e-01 3.560e+00 1.095e+03]]
type(x_test_Ndarray) =  <class 'numpy.ndarray'> ----x_test_Ndarray = [[1.410e+01 2.020e+00 2.400e+00 1.880e+01 1.030e+02 2.750e+00 2.920e+003.200e-01 2.380e+00 6.200e+00 1.070e+00 2.750e+00 1.060e+03][1.208e+01 1.830e+00 2.320e+00 1.850e+01 8.100e+01 1.600e+00 1.500e+005.200e-01 1.640e+00 2.400e+00 1.080e+00 2.270e+00 4.800e+02][1.316e+01 3.570e+00 2.150e+00 2.100e+01 1.020e+02 1.500e+00 5.500e-014.300e-01 1.300e+00 4.000e+00 6.000e-01 1.680e+00 8.300e+02][1.184e+01 2.890e+00 2.230e+00 1.800e+01 1.120e+02 1.720e+00 1.320e+004.300e-01 9.500e-01 2.650e+00 9.600e-01 2.520e+00 5.000e+02][1.237e+01 1.170e+00 1.920e+00 1.960e+01 7.800e+01 2.110e+00 2.000e+002.700e-01 1.040e+00 4.680e+00 1.120e+00 3.480e+00 5.100e+02][1.221e+01 1.190e+00 1.750e+00 1.680e+01 1.510e+02 1.850e+00 1.280e+001.400e-01 2.500e+00 2.850e+00 1.280e+00 3.070e+00 7.180e+02][1.264e+01 1.360e+00 2.020e+00 1.680e+01 1.000e+02 2.020e+00 1.410e+005.300e-01 6.200e-01 5.750e+00 9.800e-01 1.590e+00 4.500e+02][1.437e+01 1.950e+00 2.500e+00 1.680e+01 1.130e+02 3.850e+00 3.490e+002.400e-01 2.180e+00 7.800e+00 8.600e-01 3.450e+00 1.480e+03][1.285e+01 1.600e+00 2.520e+00 1.780e+01 9.500e+01 2.480e+00 2.370e+002.600e-01 1.460e+00 3.930e+00 1.090e+00 3.630e+00 1.015e+03][1.182e+01 1.470e+00 1.990e+00 2.080e+01 8.600e+01 1.980e+00 1.600e+003.000e-01 1.530e+00 1.950e+00 9.500e-01 3.330e+00 4.950e+02][1.402e+01 1.680e+00 2.210e+00 1.600e+01 9.600e+01 2.650e+00 2.330e+002.600e-01 1.980e+00 4.700e+00 1.040e+00 3.590e+00 1.035e+03][1.317e+01 5.190e+00 2.320e+00 2.200e+01 9.300e+01 1.740e+00 6.300e-016.100e-01 1.550e+00 7.900e+00 6.000e-01 1.480e+00 7.250e+02][1.349e+01 3.590e+00 2.190e+00 1.950e+01 8.800e+01 1.620e+00 4.800e-015.800e-01 8.800e-01 5.700e+00 8.100e-01 1.820e+00 5.800e+02][1.229e+01 1.410e+00 1.980e+00 1.600e+01 8.500e+01 2.550e+00 2.500e+002.900e-01 1.770e+00 2.900e+00 1.230e+00 2.740e+00 4.280e+02][1.258e+01 1.290e+00 2.100e+00 2.000e+01 1.030e+02 1.480e+00 5.800e-015.300e-01 1.400e+00 7.600e+00 5.800e-01 1.550e+00 6.400e+02][1.345e+01 3.700e+00 2.600e+00 2.300e+01 1.110e+02 1.700e+00 9.200e-014.300e-01 1.460e+00 1.068e+01 8.500e-01 1.560e+00 6.950e+02][1.363e+01 1.810e+00 2.700e+00 1.720e+01 1.120e+02 2.850e+00 2.910e+003.000e-01 1.460e+00 7.300e+00 1.280e+00 2.880e+00 1.310e+03][1.242e+01 1.610e+00 2.190e+00 2.250e+01 1.080e+02 2.000e+00 2.090e+003.400e-01 1.610e+00 2.060e+00 1.060e+00 2.960e+00 3.450e+02][1.251e+01 1.730e+00 1.980e+00 2.050e+01 8.500e+01 2.200e+00 1.920e+003.200e-01 1.480e+00 2.940e+00 1.040e+00 3.570e+00 6.720e+02][1.369e+01 3.260e+00 2.540e+00 2.000e+01 1.070e+02 1.830e+00 5.600e-015.000e-01 8.000e-01 5.880e+00 9.600e-01 1.820e+00 6.800e+02][1.373e+01 4.360e+00 2.260e+00 2.250e+01 8.800e+01 1.280e+00 4.700e-015.200e-01 1.150e+00 6.620e+00 7.800e-01 1.750e+00 5.200e+02][1.208e+01 1.130e+00 2.510e+00 2.400e+01 7.800e+01 2.000e+00 1.580e+004.000e-01 1.400e+00 2.200e+00 1.310e+00 2.720e+00 6.300e+02][1.390e+01 1.680e+00 2.120e+00 1.600e+01 1.010e+02 3.100e+00 3.390e+002.100e-01 2.140e+00 6.100e+00 9.100e-01 3.330e+00 9.850e+02][1.368e+01 1.830e+00 2.360e+00 1.720e+01 1.040e+02 2.420e+00 2.690e+004.200e-01 1.970e+00 3.840e+00 1.230e+00 2.870e+00 9.900e+02][1.299e+01 1.670e+00 2.600e+00 3.000e+01 1.390e+02 3.300e+00 2.890e+002.100e-01 1.960e+00 3.350e+00 1.310e+00 3.500e+00 9.850e+02][1.387e+01 1.900e+00 2.800e+00 1.940e+01 1.070e+02 2.950e+00 2.970e+003.700e-01 1.760e+00 4.500e+00 1.250e+00 3.400e+00 9.150e+02][1.383e+01 1.650e+00 2.600e+00 1.720e+01 9.400e+01 2.450e+00 2.990e+002.200e-01 2.290e+00 5.600e+00 1.240e+00 3.370e+00 1.265e+03][1.207e+01 2.160e+00 2.170e+00 2.100e+01 8.500e+01 2.600e+00 2.650e+003.700e-01 1.350e+00 2.760e+00 8.600e-01 3.280e+00 3.780e+02][1.419e+01 1.590e+00 2.480e+00 1.650e+01 1.080e+02 3.300e+00 3.930e+003.200e-01 1.860e+00 8.700e+00 1.230e+00 2.820e+00 1.680e+03][1.222e+01 1.290e+00 1.940e+00 1.900e+01 9.200e+01 2.360e+00 2.040e+003.900e-01 2.080e+00 2.700e+00 8.600e-01 3.020e+00 3.120e+02][1.179e+01 2.130e+00 2.780e+00 2.850e+01 9.200e+01 2.130e+00 2.240e+005.800e-01 1.760e+00 3.000e+00 9.700e-01 2.440e+00 4.660e+02][1.229e+01 3.170e+00 2.210e+00 1.800e+01 8.800e+01 2.850e+00 2.990e+004.500e-01 2.810e+00 2.300e+00 1.420e+00 2.830e+00 4.060e+02][1.277e+01 3.430e+00 1.980e+00 1.600e+01 8.000e+01 1.630e+00 1.250e+004.300e-01 8.300e-01 3.400e+00 7.000e-01 2.120e+00 3.720e+02][1.247e+01 1.520e+00 2.200e+00 1.900e+01 1.620e+02 2.500e+00 2.270e+003.200e-01 3.280e+00 2.600e+00 1.160e+00 2.630e+00 9.370e+02][1.320e+01 1.780e+00 2.140e+00 1.120e+01 1.000e+02 2.650e+00 2.760e+002.600e-01 1.280e+00 4.380e+00 1.050e+00 3.400e+00 1.050e+03][1.334e+01 9.400e-01 2.360e+00 1.700e+01 1.100e+02 2.530e+00 1.300e+005.500e-01 4.200e-01 3.170e+00 1.020e+00 1.930e+00 7.500e+02]]
type(y_train_Ndarray) =  <class 'numpy.ndarray'> ----y_train_Ndarray = [1 0 1 1 1 0 0 1 2 0 2 1 1 1 0 1 0 2 2 1 0 0 2 0 1 2 0 2 2 2 2 1 1 0 1 2 02 1 0 0 0 1 1 0 0 2 1 1 2 1 2 1 2 1 1 0 1 0 0 1 2 1 2 0 0 1 0 1 0 1 2 2 22 1 2 1 0 1 0 1 1 2 1 0 2 0 2 1 2 1 0 1 0 2 0 0 0 1 2 0 0 2 0 1 1 0 0 2 12 2 0 0 0 2 1 0 2 0 0 1 1 1 0 1 1 2 1 2 0 2 1 1 0 2 2 1 2 1 0]
type(y_test_Ndarray) =  <class 'numpy.ndarray'> ----y_test_Ndarray = [0 1 2 1 1 1 1 0 0 1 0 2 2 1 2 2 0 1 1 2 2 1 0 0 1 0 0 1 0 1 1 1 1 1 0 1]
单个极限森林的准确度:score =  0.9722222222222222
单个随机森林的准确度:score01 =  0.9166666666666666
决策树多次运行准确率:score02 =  0.909722222222222
随机森林多次运行准确率:score03 =  0.9780555555555561
极限森林多次运行准确率:score04 =  0.9800000000000003

机器学习-有监督学习-分类算法:决策树算法【CART树:分类树(基于信息熵;分类依据:信息增益、信息增益率、基尼系数)、回归树(基于均方误差)】【损失函数:叶节点信息熵和】【对特征具有很好的分析能力】相关推荐

  1. 分类算法——决策树算法及其R实现

    决策树定义 以鸢尾花为例子来说明: 观察上图,判决鸢尾花的思考过程可以这么来描述:花瓣的长度小于2.4cm的是setosa(图中绿色的分类),长度大于2.4cm的呢?可以通过宽度来判别,宽度小于1.8 ...

  2. 机器学习算法——决策树算法详细介绍,并使用sklearn实现案例预测,可视化决策树

    目录 一.决策树算法简介 二.决策树分类原理 1.熵 1.1 概念 1.2 案例 2.决策树的划分依据一:信息增益 2.1 概念 2.2 案例: 3.决策树的划分依据二:信息增益率 3.1 概念 3. ...

  3. Python机器学习--算法--决策树算法

    决策树算法 决策树算法类型: 决策树是一系列算法,而不是一个算法. 决策树包含了 ID3分类算法,C4.5分类算法,Cart分类树算法,Cart回归树算法. 决策树既可以做分类算法,也可以做回归算法. ...

  4. 机器学习朴素贝叶斯算法+tkinter库界面实现好瓜坏西瓜分类

    机器学习朴素贝叶斯算法+tkinter库界面实现好瓜坏西瓜分类 一.界面实现 from tkinter import * from tkinter import ttk import NBdef ma ...

  5. 决策树算法--CART分类树算法

    ID3和C4.5算法,生成的决策树是多叉树,只能处理分类不能处理回归.而CART(classification and regression tree)分类回归树算法,既可用于分类也可用于回归. 分类 ...

  6. 机器学习-决策树算法ID3实现,含例子(红酒分类)

    决策树原理实现代码如下所示:(参考自机器学习实践 Peter Harrington). import mathx=[[0,1,"no"],[0,1,"no"], ...

  7. 机器学习算法:决策树算法

    1.基本定义   决策树(Decision Tree)是一种基本的分类和回归算法.该算法模型呈树形结构,主要由结点和有向边组成.结点又分为两种类型:内部结点和叶子结点.内部结点表示在一个属性或特征上的 ...

  8. 机器学习决策树算法cart剪枝

    目录 1 为什么要剪枝 2 常用的减枝方法 2.1 预剪枝 2.2 后剪枝 3 小结 1 为什么要剪枝 在决策树学习中,为了尽可能正确分类训练样本,结点划分过程将不断重复,有时会造成决策树分支过多,这 ...

  9. FlyAI小课堂:python机器学习笔记:深入学习决策树算法原理

    分类技术(或分类法)是一种根据输入数据建立分类模型的系统方法,分类法的例子包括决策分类法,基于规则的分类法,神经网络,支持向量机和朴素贝叶斯分类法.这些技术都使用一种学习算法(learning alg ...

最新文章

  1. 【青少年编程】【一级】舞者凯希
  2. 还是畅通工程(1233 并查集+kruskal)
  3. 亿级用户下的新浪微博平台架构阅读心得
  4. Mysql动态数据多条件查询
  5. 高精度计算(High-Precision_Calculation)
  6. oracle 慕课课程_我在慕课网学习到的oracle
  7. Java BufferedReader
  8. 阶段3 3.SpringMVC·_07.SSM整合案例_01.ssm整合说明
  9. umpy知识点补充:np.vstack()np.hstack()
  10. 一键下载百度文库/豆丁/道客巴巴文档,支持导出PDF,Word,txt 文件
  11. CxImage使用介绍
  12. 计算机无法启动printspooler,Win7系统下print spooler服务无法启动的解决方法
  13. C#使用MathNet的矩阵与向量运算示例
  14. WORD2013使用技巧——调整序号中制表位的大小
  15. 计算机内无法使用搜狗,电脑搜狗输入法不能用怎么办
  16. 无线测温系统在高低压开关柜内的运行---安科瑞 顾城
  17. 关于 - TypeError: dict.get() takes no keyword arguments
  18. TSMC HPC工艺介绍
  19. 解决Mac苹果笔记本键盘背光灯不亮的问题
  20. C语言遍历windows目录文件 并对文件进行读写操作

热门文章

  1. 关于安装mvvmlight后出现命名空间名“Practices”或是Locator不存在的问题
  2. Inner peace
  3. 练习题目-锦鱼吐泡泡
  4. java 计算器 键盘输入_Java实现windows7标准型计算器
  5. 基于javaweb的汽配商城系统(java+html+javascript+jsp+mysql)
  6. 用canvas画一个五星红旗
  7. 在linux里安装/卸载mysql
  8. facebook最新客户端_忘记Facebook:Zoom是科技行业最新的问题之子
  9. vb.net限制软件使用次数_小程序客服消息怎么使用、有没有什么限制?
  10. 基于EKF的车辆状态估计系统建模