决策树——自学第十一篇

1、决策树

招聘机器学习算法工程师的时候,往往会对应聘者的条件进行筛选,如图所示,叶子结点是根据已知的信息做出的决策,该决策树的深度为3
在这里插入图片描述

  • 决策树是非参数学习算法
  • 可以解决多分类问题
  • 也可以解决回归问题(通过得到的叶子结点的那一类的数据的平均值预测最终得值)
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets

iris=datasets.load_iris()
x=iris.data[:,2:]
y=iris.target
print(y)
plt.scatter(x[y==0,0],x[y==0,1])
plt.scatter(x[y==1,0],x[y==1,1])
plt.scatter(x[y==2,0],x[y==2,1])
plt.show()

from sklearn.tree import DecisionTreeClassifier
tree=DecisionTreeClassifier(max_depth=5,criterion='entropy')   #最高深度,熵
tree.fit(x,y)
def plot_tree(model, axis):
    x0, x1 = np.meshgrid(
        np.linspace(axis[0], axis[1], int((axis[1] - axis[0]) * 100)).reshape(-1, 1),
        np.linspace(axis[2], axis[3], int((axis[3] - axis[2]) * 100)).reshape(-1, 1)
    )
    X_new = np.c_[x0.ravel(), x1.ravel()]

    y_predict = model.predict(X_new)
    zz = y_predict.reshape(x0.shape)

    from matplotlib.colors import  ListedColormap
    custom_map=ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])
    plt.contourf(x0,x1,zz,linewidth=5,cmap=custom_map)

plot_tree(tree,axis=[0.5,7.5,0,3])
plt.scatter(x[y==0,0],x[y==0,1])
plt.scatter(x[y==1,0],x[y==1,1])
plt.scatter(x[y==2,0],x[y==2,1])
plt.show()

在这里插入图片描述

2、信息熵和基尼系数

(1)信息熵:
我们通过决策树进行分类的时候,会产生很多的分类节点,这些节点都是判断条件,在进行分类前我们需要得到两类信息:1、每个节点在哪个维度做划分。2、划分的值是多少。
信息熵:
熵在信息论中代表随机变量不确定度的度量
熵越大,数据的不确定性越高;熵越小,数据的不确定度越低
公式: H = i = 1 k p i l o g ( p i ) H=-\sum_{i=1}^{k}p_{i}log\left ( p_{i} \right )
一个系统中有k类信息,每个信息的信息量的比例为 p i p_{i}
举例:有三类数据,分别占比为{1/10 , 2/10 , 7/10},信息熵为0.8018
有三类,分别占比为{0,0,1},信息熵为0 。由此可见第二例中全为第三类,所以是最确定的,所以信息熵最低。
目的:找到某一种划分,使得划分后信息熵降低

(2)基尼系数
公式: G = 1 i = 1 k p i 2 G=1-\sum_{i=1}^{k}p_{i}^{2}
性质:和信息熵一样,基尼系数越小,数据越确定,基尼系数越高,数据的不确定度越高。

(3)信息熵vs基尼系数

  • 熵的计算比基尼系数的计算慢
  • sklearn中默认为基尼系数
  • 大多数时候二者没有特别的效果优劣

3、sklearn使用决策树

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

iris=datasets.make_moons()
x,y=datasets.make_moons(noise=0.25,random_state=666)

plt.scatter(x[y==0,0],x[y==0,1])
plt.scatter(x[y==1,0],x[y==1,1])
plt.show()

from sklearn.tree import DecisionTreeClassifier
dt_tree=DecisionTreeClassifier()  #如果不定义超参数,则决策树会一直向下划分,直到基尼系数都为0
dt_tree.fit(x,y)

def plot_tree(model, axis):
    x0, x1 = np.meshgrid(
        np.linspace(axis[0], axis[1], int((axis[1] - axis[0]) * 100)).reshape(-1, 1),
        np.linspace(axis[2], axis[3], int((axis[3] - axis[2]) * 100)).reshape(-1, 1)
    )
    X_new = np.c_[x0.ravel(), x1.ravel()]

    y_predict = model.predict(X_new)
    zz = y_predict.reshape(x0.shape)

    from matplotlib.colors import  ListedColormap
    custom_map=ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])
    plt.contourf(x0,x1,zz,linewidth=5,cmap=custom_map)

plot_tree(dt_tree,axis=[-1.5,2.5,-1.0,1.5])
plt.scatter(x[y==0,0],x[y==0,1])
plt.scatter(x[y==1,0],x[y==1,1])
plt.show()

在这个决策树分类器中,不使用任何的超参数,则分类器默认将决策树一直向下划分,直到所有的基尼系数都为0。由下图可以看出此分类过拟合了。
在这里插入图片描述
(1)在分类器中传入超参数max_depth=2(规定树的深度为2)

dt_tree2=DecisionTreeClassifier(max_depth=2)
dt_tree2.fit(x,y)
plot_tree(dt_tree2,axis=[-1.5,2.5,-1.0,1.5])
plt.scatter(x[y==0,0],x[y==0,1])
plt.scatter(x[y==1,0],x[y==1,1])
plt.show()

可以看到没有发生过拟合,并且可能发生了欠拟合。
在这里插入图片描述

(2)再传入另一个超参数min_samples_split=10,表示对于一个节点来说,至少需要多少个样本数据才会继续划分下去。

dt_tree3=DecisionTreeClassifier(min_samples_split=10)
dt_tree3.fit(x,y)
plot_tree(dt_tree3,axis=[-1.5,2.5,-1.0,1.5])
plt.scatter(x[y==0,0],x[y==0,1])
plt.scatter(x[y==1,0],x[y==1,1])
plt.show()

在这里插入图片描述
由上图可以看出,该超参数能有效改善过拟合,该超参数数值越高越不容易发生过拟合,当然数值太高会发生欠拟合。
(3)第三个输入的超参数是min_samples_leaf=6,表示叶子结点至少应该有几个样本。如果数值越少,则对该数据越敏感,越容易发生过拟合。

dt_tree4=DecisionTreeClassifier(min_samples_leaf=6)

在这里插入图片描述
(4)第四个超参数是max_leaf_nodes=4,表示最多有多少个叶子结点,叶子结点越多,模型越复杂,越容易发生过拟合。

dt_tree5=DecisionTreeClassifier(max_leaf_nodes=4)

在这里插入图片描述可以通过网格搜索的方式,找到这些超参数之间的平衡关系,并找到最好的一个组合。

扫描二维码关注公众号,回复: 3325001 查看本文章

4、决策树解决回归问题

from sklearn import datasets
boston=datasets.load_boston()
x=boston.data
y=boston.target

from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,random_state=666)
#加载决策树的回归模型
from sklearn.tree import DecisionTreeRegressor
dt_reg=DecisionTreeRegressor()
dt_reg.fit(x_train,y_train)

print(dt_reg.score(x_test,y_test))
print(dt_reg.score(x_train,y_train))

输出为:

0.58304453845759
1.0

可以看出该模型对训练集的得分为1,对测试集的得分很低,很明显的过拟合现象。需要改变超参数来减少过拟合现象。

5、决策树的局限性

  • 决策边界都是与坐标轴平行,具有局限性,不能很好的划分类别。
    在这里插入图片描述
    因为边界都是横平竖直,所以就会呈现上面的分类,这样明显是不对的。
  • 决策树对个别数据敏感(如果删掉几个数据,可能决策边界就会不同)(非参数学习法的通病)

猜你喜欢

转载自blog.csdn.net/yh_1021/article/details/82814913
今日推荐