(十一)决策树

一,什么是决策树?

这棵决策树的深度为3,只要判断三次就可以分类

程序实现

加载鸢尾花数据集

import numpy as np

import matplotlib.pyplot as plt

from sklearn import datasets

from sklearn.tree import DecisionTreeClassifier

iris = datasets.load_iris()

X = iris.data[:,2:]

y = iris.target

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()

dt_clf = DecisionTreeClassifier(max_depth=2, criterion="entropy", random_state=42)

dt_clf.fit(X, y)  #criterion="entropy"表示熵

使用决策边界绘制函数:

plot_decision_boundary(dt_clf, 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()

分析决策流程:

特点:

  • 非参数学习算法
  • 可以解决分类问题
  • 天然可以解决多分类问题
  • 也可以解决回归问题(叶子的平均值)
  • 非常好的可解释性

问题:

  • 每个节点在哪个维度做划分?
  • 在某一维度上,要取哪个阈值进行划分呢?

二,信息熵

熵在信息论中代表随机变量不确定的的度量

  • 熵越大,数据的不确定性越高,越混乱
  • 熵越小,数据的不确定性越低,越规则

香农提出的信息熵公式:

p表示系统中每一类信息所占的比例(每种鸢尾花所占的比例)

可以计算:

H{1/3,1/3,1/3}=1.0986

H{1/10,2/10,7/10}=0.8018

H{1,0,0}=0

  • 熵越大,整个系统越不确定,熵最大时一般就是各类信息所占比例相同
  • 当所有信息集中在一类,整个系统就是确定的,此时熵就是0

信息熵的函数图像:

当系统只有俩类,公式可以写成:

程序:

import numpy as np

import matplotlib.pyplot as plt

def entropy(p):

    return -p * np.log(p) - (1-p) * np.log(1-p)

x = np.linspace(0.01, 0.99, 200) #x不能取1和0

plt.plot(x, entropy(x))

plt.show()

其函数图像是:

从图中也可以得出上述的结论。

因此我们得出解决问题的方法:

要求划分之后使得系统的信息熵降低,使系统变得更加确定

=>基于信息熵的最优划分方式

三,使用信息熵寻找最优划分

导入数据集,为了可视化方便依旧选取俩个维度特征

程序如上,结果同上:

模拟使用信息熵进行划分

定义划分函数:

def split(X, y, d, value):  #d表示维度,阈值是value

    index_a = (X[:,d] <= value) #返回布尔向量

    index_b = (X[:,d] > value)

    return X[index_a], X[index_b], y[index_a], y[index_b]

寻找d和value的值:

from collections import Counter #把y做成字典

from math import log

def entropy(y):

    counter = Counter(y)

    res = 0.0

    for num in counter.values():

        p = num / len(y)

        res += -p * log(p)

    return res

def try_split(X, y):

    best_entropy = float('inf') #信息熵初始化正无穷

    best_d, best_v = -1, -1

    for d in range(X.shape[1]): #在所有维度进行搜索

        sorted_index = np.argsort(X[:,d]) #返回索引

        for i in range(1, len(X)): #对每个样本进行遍历

            if X[sorted_index[i], d] != X[sorted_index[i-1], d]:

                v = (X[sorted_index[i], d] + X[sorted_index[i-1], d])/2

                X_l, X_r, y_l, y_r = split(X, y, d, v)

                p_l, p_r = len(X_l) / len(X), len(X_r) / len(X)

                e = p_l * entropy(y_l) + p_r * entropy(y_r) #总信息熵是加权平均

                if e < best_entropy:

                    best_entropy, best_d, best_v = e, d, v           

    return best_entropy, best_d, best_v

best_entropy, best_d, best_v = try_split(X, y)

print("best_entropy =", best_entropy)

print("best_d =", best_d)

print("best_v =", best_v)

X1_l, X1_r, y1_l, y1_r = split(X, y, best_d, best_v) #第一次划分

X2_l, X2_r, y2_l, y2_r = split(X1_r, y1_r, best_d2, best_v2) #第二次划分

四,基尼系数

与信息熵相似,对于基尼系数,越大意味着数据的不确定性越高,越小数据越确定

如果只有俩类:G=1-x^2-(1-x)^2=-2x^2+2x

基尼系数程序实现:

数据同上,但是调用决策树分类时注意改变参数:criterion="gini"

绘制的结果:

与信息熵的结果相同

模拟使用基尼系数进行划分:

重新定义一个基尼系数,剩下同上:

def gini(y):

    counter = Counter(y)

    res = 1.0

    for num in counter.values():

        p = num / len(y)

        res -= p**2

    return res

信息熵和基尼系数对比:

信息熵的计算比基尼系数稍慢

scikit-learn中默认使用基尼系数

大多数时候二者没有特别的效果优劣

五,CART与决策树中的超参数

Classification And Regression Tree

根据某一维度d和某一阈值的v进行划分

决策树的时间复杂度:

预测:O(logm)

训练:O(n*n*logm)

训练的时间复杂度太高

剪枝:降低复杂度,解决过拟合(限制树的高度就是剪枝手段)

数据生成:

import numpy as np

import matplotlib.pyplot as plt

from sklearn import datasets

from sklearn.tree import DecisionTreeClassifier

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()

dt_clf = DecisionTreeClassifier() #默认参数,高度默认就会一直划分

dt_clf.fit(X, y)

绘制决策边界:

可以看出,已经过拟合了

调参:

dt_clf2 = DecisionTreeClassifier(max_depth=2)  #限制深度

dt_clf2.fit(X, y)

dt_clf3 = DecisionTreeClassifier(min_samples_split=10) #至少要多少样本数据才进行拆分

dt_clf3.fit(X, y)

dt_clf4 = DecisionTreeClassifier(min_samples_leaf=6) #每个叶子至少需要多少样本点

dt_clf4.fit(X, y)

dt_clf5 = DecisionTreeClassifier(max_leaf_nodes=4) #最多有多少叶子节点

dt_clf5.fit(X, y)

CART中的超参数:

六,决策树解决回归问题

默认参数程序实现:

import numpy as np

import matplotlib.pyplot as plt

from sklearn import datasets

from sklearn.model_selection import train_test_split

from sklearn.tree import DecisionTreeRegressor

boston = datasets.load_boston()

X = boston.data

y = boston.target

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=666)

dt_reg = DecisionTreeRegressor()

dt_reg.fit(X_train, y_train)

决策树非常容易过拟合,需要参数抑制

决策树的学习曲线:

依旧使用以上数据集

from sklearn.tree import DecisionTreeRegressor

from sklearn.metrics import mean_squared_error

我们首先定义绘制RMSE学习曲线的函数:

绘制曲线:

plot_learning_curve(DecisionTreeRegressor(), X_train, X_test, y_train, y_test)

R^2学习曲线:

调节最大深度:

plot_learning_curve_r2(DecisionTreeRegressor(max_depth=1), X_train, X_test, y_train, y_test)

plot_learning_curve_r2(DecisionTreeRegressor(max_depth=3), X_train, X_test, y_train, y_test)

plot_learning_curve_r2(DecisionTreeRegressor(max_depth=5), X_train, X_test, y_train, y_test)

七,决策树的局限性

决策边界是横平竖直的,解决非线性的问题泛化能力很弱,作为一个非参数学习方法,对个别的样本点非常的敏感!

数据同上

X_new = np.delete(X, 106, axis=0)  #删除一个样本点

y_new = np.delete(y, 106)

tree_clf2 = DecisionTreeClassifier(max_depth=2, criterion="entropy", random_state=42)

tree_clf2.fit(X_new, y_new)

删除一个样本点,决策边界变化非常大

但决策树的重要性在于使用集成学习的方式创建随机森林的算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值