决策树算法

决策树概念

决策树是⼀种树形结构,通过特征的不同来将样本数据划分到不同的分⽀(⼦ 树)中,最终,每个样本 ⼀定会划分到⼀个叶⼦节点中。我们可以将每个特征视 为⼀个问题(提问), 特征值的不同,就视为样本给出的不同答案,然后,我们就可 以根据⼀系列问题(特征), 将样本划分到不同的叶⼦节点中。决策树可以⽤于分 类与回归任务。

决策树的介绍: 决策树学习采⽤的是⾃顶向下的递归⽅法,其基本思想是以信 息熵为度量构造⼀棵熵值,下降最快的树,到叶⼦节点处的熵值为零,此时每个叶 节点中的实例都属于同⼀类。

训练决策树

序号拥有房产(X1)婚姻状态(X2)年收入(X3)能否偿还债务(Y)
1单身125
2已婚100
3单身100
4已婚110
5离婚60

6离婚95不能
7单身85不能
8已婚75

能 

9单身90 不能
10离婚220
11已婚94

决策树特征选择

信息熵

决策树的信息熵是⽤来度量样本集合纯度的指标。信息熵越⼤,表示样本集合 的不确定性越⼤;信息熵越⼩,表示样本集合的确定性越⾼。在决策树的构建过程 中,信息熵被⽤来作为划分属性的依据,通过计算不同属性划分后的信息熵来选择 最优划分属性,以使得整个决策树的熵值最⼩,从⽽使得整个决策系统的确定性最 ⾼。

计算⽅式

假设随机变量具有个值,分别为:V1,V2 ,V3... ,Vm。并且各个值出现的概率如 下:

则变量的信息期望值(信息熵)为:

不纯度

决策树的不纯度是指落在当前节点的样本类别分布的均衡程度。如果类别⼀ 致,那么不纯度为0,叶⼦节点和是相对纯的。在决策树的每个叶⼦节点中都会包 含⼀组数据,这组数据中,如果某⼀类标签占有较⼤的⽐例,我们就说叶⼦节 点“纯”,分枝分得好。某⼀类标签占的⽐例越⼤,叶⼦就越纯,不纯度就越低,分 枝就越好。如果没有哪⼀类标签的⽐例很⼤,各类标签都相对平均,则说叶⼦节 点”不纯“,分枝不好,不纯度⾼.

不纯度是决策树算法中⼀个重要的概念,它可以帮助我们判断在每个节点处进 ⾏分裂是否合适。⼀般来说,不纯度越低,说明数据在该节点处越能被分裂得均 匀,该节点的分裂效果越好。因此,决策树算法会选择不纯度下降最⼤的地⽅进⾏ 分裂。

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["font.family"] = "SimHei"
plt.rcParams["axes.unicode_minus"] = False
plt.rcParams["font.size"] = 12
p = np.linspace(0.01, 0.99, 100)
# 计算在不同⽐例下的信息熵。--- 信息熵公式
h = -p * np.log2(p) - (1 - p) * np.log2(1 - p)
plt.plot(p, h)
plt.xlabel("p取值")
plt.ylabel("信息熵")
plt.title("信息熵(不纯度)")
plt.show()

运行结果 

信息增益

  • f: 划分的特征。
  • Dp: ⽗节点,即使⽤特征f分割之前的节点。
  • IG(Dp,f): ⽗节点Dp使⽤特征f划分下,获得的信息增益。
  • Dj: ⽗节点Dp经过分割之后,会产⽣n个⼦节点, Dj为第j个⼦节点。
  • Np: ⽗节点 Dp包含样本的数量。
  • Nj: 第 j个⼦节点Dj包含样本的数量。
  • I: 不纯度度量标准。例如,之前介绍的信息熵,就是标准之⼀。 ---- 后⾯ 公式就是⽤信息熵H

出于简化与缩⼩组合搜索空间的考虑,很多库(包括scikit-learn)实现的都是⼆ 叉决策树,即每个⽗节点最多含有两个⼦节点(左⼦树节点与右⼦树节点),此 时,信息增益定义为:

通过定义我们可知,信息增益就是⽗节点的不纯度减去所有⼦节点不纯度(加权)。

不纯度度量标准

不纯度可以采⽤如下⽅式度量:

  • 信息熵(Entropy)
  • 基尼系数(Gini Index)
  • 错误率(classification error)

信息熵

  • m: 节点D中含有样本的类别数量。
  • P(i|D): 节点D中,属于类别i 的样本占节点 D中样本总数的⽐例(概率)。

基尼系数

错误率

def gini(p):
 return 1 - np.sum(p ** 2, axis=1)
def entropy(p):
 return -np.sum(p * np.log2(p), axis=1)
def error(p):
 return 1 - np.max(p, axis=1)
# 定义概率的取值范围。
p = np.linspace(0.01, 0.99, 200)
# 计算概率组合。
parray = np.array([p, 1 - p]).T
print(parray)
# 计算信息熵。
en = entropy(parray)
# 计算缩放的信息熵。
en2 = en * 0.5
# 计算错误率。
err = error(parray)
# 计算基尼系数。
g = gini(parray)
fig = plt.figure()
for i, lab, ls, c, in zip([en, en2, g, err], ["信息熵", "信息熵(缩放)", "基尼系数", "错误率"],["-", ":", "--", "-."], ["r", "g", "b", "y"]):
 plt.plot(p, i, label=lab, linestyle=ls, lw=2, color=c)
 
plt.legend(loc="right", bbox_to_anchor=(1.55, 0.8))
plt.axhline(y=0.5, linewidth=1, color='k', linestyle="--")
plt.axhline(y=1.0, linewidth=1, color='k', linestyle="--")
plt.ylim([0, 1.1])
plt.xlabel("概率1取值")
plt.ylabel("纯度系数")
 
plt.show()

运行结果 

[0.94075377 0.05924623]
 [0.94567839 0.05432161]
 [0.95060302 0.04939698]
 [0.95552764 0.04447236]
 [0.96045226 0.03954774]
 [0.96537688 0.03462312]
 [0.97030151 0.02969849]
 [0.97522613 0.02477387]
 [0.98015075 0.01984925]
 [0.98507538 0.01492462]
 [0.99       0.01      ]]

决策树算法

决策树主要包含以下三种算法:

  • ID3 Iterative Dichotomiser
  • C4.5
  • CART(Classification And Regression Tree)

ID3 即信息增益

ID3(Iterative Dichotomiser3-迭代⼆分法)算法是⾮常经典的决策树算法,该算 法描述如下:

  • 使⽤多叉树结构。
  • 使⽤信息熵作为不纯度度量标准,选择信息增益最⼤的特征分割数据。

C4.5

C4.5算法是在ID3算法上改进⽽来,该算法描述如下:

  • 使⽤多叉树结构。
  • 仅⽀持分类,不⽀持回归。

不过,C4.5在ID3算法上,进⾏了⼀些优化,包括:

  • ⽀持对缺失值的处理。
  • ⽀持将连续值进⾏离散化处理。
  • 使⽤信息熵作为不纯度度量标准,但选择信息增益率(⽽不是信息增益)最⼤ 的特征分裂节点。

信息增益率的定义⽅式为:

CART

CART(Classification And Regression Tree),分类与回归树。该算法描述如 下:

  • 使⽤⼆叉树结构。
  • ⽀持连续值与缺失值处理。
  • 既⽀持分类,也⽀持回归。

使⽤基尼系数作为不纯度度量标准,选择基尼增益最⼤的特征分裂节点。 (分类)

使⽤MSE或MAE最⼩的特征分类节点。(回归)

回归决策树

当使⽤回归决策树时,与分类决策树会有所不同。回归任务的标签( 值)是连 续的,故之前以分类为基础的不纯度度量标准(信息熵,基尼系数与错误率)都不 适⽤于回归树,因此,在回归树中,⾃然也就没有信息增益,信息增益率或基尼增 益等概念了。可以说,分类决策树选择特征的⽅式,完全不适⽤于回归决策树。

分类决策树

# 决策分类树
from sklearn.datasets import load_iris  # 鸢尾花
from sklearn.model_selection import train_test_split # 划分
from sklearn.tree import DecisionTreeClassifier  

X,y = load_iris(return_X_y=True)
load_iris(return_X_y=True)
X = X[:,:2]
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.25,random_state=1)
# 实例化算法对象 ---模型 
tree = DecisionTreeClassifier()
# 拟合数据
tree.fit(X_train,y_train)
# 训练集 评分 
print(tree.score(X_train, y_train))
# 测试集 评分
print(tree.score(X_test, y_test))

运行结果

0.9464285714285714
0.631578947368421

from sklearn.datasets import load_iris 
from sklearn.model_selection import train_test_split 
from sklearn.tree import DecisionTreeClassifier 
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import accuracy_score
# 加载数据集 
iris = load_iris() 
# 划分数据集为训练集和测试集(70%训练,30%测试) 
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target
, test_size=0.3, random_state=8)
print(X_train.shape)
print(y_train.shape)
# 创建决策树分类器并进⾏训练 
classifier = DecisionTreeRegressor(random_state=8) 
classifier.fit(X_train, y_train)
# 使⽤模型进⾏预测 
y_pred = classifier.predict(X_test)
# 计算准确率评估模型的性能,越⾼越好。 
accuracy = accuracy_score(y_test, y_pred) 
print(f'Accuracy: {accuracy}')

运行结果

(105, 4)
(105,)
Accuracy: 0.9111111111111111

回归决策树

from sklearn.datasets import load_iris 
from sklearn.model_selection import train_test_split 
from sklearn.tree import DecisionTreeClassifier 
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import accuracy_score
# 加载数据集 
iris = load_iris() 
# 划分数据集为训练集和测试集(70%训练,30%测试) 
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target
, test_size=0.3, random_state=8)
print(X_train.shape)
print(y_train.shape)
# 创建决策树分类器并进⾏训练 
classifier = DecisionTreeRegressor(random_state=8) 
classifier.fit(X_train, y_train)
# 使⽤模型进⾏预测 
y_pred = classifier.predict(X_test)
# 计算准确率评估模型的性能,越⾼越好。 
accuracy = accuracy_score(y_test, y_pred) 
print(f'Accuracy: {accuracy}')

运行结果

(105, 4)
(105,)
Accuracy: 0.9111111111111111

from matplotlib.colors import ListedColormap

def plot_decision_boundary(model,X,y):
 # 设置三个分类
 color = ['r','g','b']
 marker = ['o','v','x']
 # 获取标签
 class_label = np.unique(y)
 # 定义颜色图 
 cmap = ListedColormap(color[:len(class_label)])
 
 # 获取最小值和最大值
 x1_min,x2_min = np.min(X,axis=0)
 x1_max,x2_max = np.max(X,axis=0)
 print(X.shape)
 # 在原范围内取更多值
 x1 = np.arange(x1_min-1,x1_max+1,0.02)
 x2 = np.arange(x2_min-1,x2_max+1,0.02)
 #笛卡尔积
 X1,X2 = np.meshgrid(x1,x2)
 # print(X1.shape)  # (175,295)
 # print(X2.shape)  # (175,295)
 
 Z = model.predict(np.array([X1.ravel(), X2.ravel()]).T).reshape(X1.shape)
 
 # 绘制等高线 
 plt.contourf(X1,X2,Z,cmap=cmap,alpha=0.5)
 
 #绘制 
 for i,class_ in enumerate(class_label):
  plt.scatter(x=X[y==class_,0], y=X[y==class_,1],c=cmap.colors[i],label=class_,marker=marker[i])
  plt.legend()
 
plt.figure(figsize=(15,10))
for index,depth in enumerate([1,4,7,12],start=1):
 plt.subplot(2,2,index)
 plt.title(f'最大深度:{depth}')
 tree = DecisionTreeClassifier(random_state=1,max_depth=depth)
 tree.fit(X_train,y_train)
 plot_decision_boundary(tree, X_test,y_test)

运行结果

(38, 2)
(38, 2)
(38, 2)
(38, 2)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值