1 理论部分
需要弄清楚几个概念
信息熵,决策树,决策树优化, 剪枝 ,决策树可视化
1 信息熵(Entropy 单位bit)
每条消息包含的信息的平均量(信息熵越大 信息量越大 系统越无序,具有更高的不确定性, 越混乱)
信息量: I(xi)=−logp(xi) (负号: 概率越小 logp(xi)越小 -logp(xi)越大)
信息熵其实是一个随机变量信息量的数学期望
image.png
2 决策树
决策树是一种树形结构,其中每个内部节点表示一个属性上的测试,每个分支代表一个测试输出,每个叶节点代表一种类别。
3 决策树优化
决策树模型生成后会存在欠拟合和过拟合的问题。如何解决这些问题就是决策树优化需要考虑的。
4 剪枝
防止决策树过拟合的过程
5 决策树可视化
导入一些模块,将树形结构展示给用户
-
决策树的直观理解
根据“年收入” “房产” “婚姻情况” 判断一个人是否有偿还能力
决策树类似代码中的if else else if .......
2D2B7764-0DE7-4890-B3DB-F4737D2E5690.png -
比特化
IMG_3046.JPG
变量所占比特位计算方式
image.png
信息熵 = 比特化随机变量X占用比特位的数学期望
- 条件熵
H(Y|X) 给定条件X 随机变量Y的信息熵
H(Y|X) = H(X,Y)-H(X)
决策树构建过程
从根节点开始 测试待分类项对应的特征属性 并按照其值选择输出分支,直到叶子节点,将叶子节点存放的类别作为决策结果
构建步骤:
1 将所有的特征看成一个一个的节点
2 遍历当前所有的特征的每一种分割方式 找到最好的分割点,将数据划分为不同的子节点(关键是找到最好的分割点)
3 循环遍历 最终得到每个子节点足够纯
决策树特征属性类型
离散值 不要求生成二叉树 一个属性就是一个分支
离散值 生成二叉树 按"属于此子集"和“不属于此子集”划分
连续值 确定一个分割点 split_point 按照“>split_point”和"<=split_point"分为两个分支
AC805900-793C-419B-A8CF-634284F9DF82.png image.png决策树 量化纯度
Gini系数 熵(Entrory) 错误率
越大 越不纯 越小越纯
信息增益度
当计算出各个特征属性的量化纯度值后,使用信息增益度来选择出当前数据集的分割特征属性。如果信息增益度值越大,表示在该特征属性上会损失的纯度越大,那么该属性越应该在决策树的上层。计算公式如下: image.png
Gain为A在特征对训练数据集D的信息增益,它为集合D的经验熵H(D)与特征A给定条件下D的经验条件熵H(D|A)之差。
Gain= 蓝色区域 = H(D) - H(D|A)
image.png
如果信息增益度值越大,表示在该特征属性上会损失的纯度越大,那么该属性越应该在决策树的上层。
决策树算法停止条件
1 方式一 当每个子节点只有一种类型的时候停止构建(会树的节点过多 导致过拟合)
2 方式二 当前节点的样本数小于某个阈值 同时迭代次数到达某个特定的值时 停止构建
1 决策树最大深度 max_depth
2 min_samples_split 最小样本数
3 min_samples_leaf 最少叶子节点数
4 max_leaf_nodes 最大叶子节点数
5 min_impurity_split 节点划分不纯度
分两类: 分类树和回归树 分类树用来分类标签值 回归树用来预测连续值
常见算法 ID3,C4.5,CART
决策树算法效果评估
1 跟一般的分类算法一样 采用混淆矩阵来进行计算准确率,召回率,精确率
2 叶子节点的纯度值总和 值越小 效果越好
重点回顾:
1、Gain为A在特征对训练数据集D的信息增益,它为集合D的经验熵H(D)与特征A给定条件下D的经验条件熵H(D|A)之差。
2、不能将所有叶子节点的信息熵单纯的求和,还得乘上一个权重值,权重值=当前叶子节点的样本个数/总的样本个数。比如说上图中有房产/总样本 = 0.4 无房产/总样本 = 0.6
image.png
思考:
在决策树中的每一个节点都能够表示一个系统,都能够计算其信息熵(系统稳定程度)。
如果将这些信息熵单纯的求和结果会不太理想。比如有100个节点,前99个节点中有很多数据,但是第100个节点只有1条数据。按理说,这第100个节点对于整个系统的不稳定性起了非常小的作用。如果还有一个节点,这个节点里有大量的数据,且结果都为分类0,那么可以认为这个节点的划分比较成功,在计算整个决策树总损失的算法中,该节点要占用一个较大的比例。
所以:不能将所有叶子节点的信息熵单纯的求和,还得乘上一个权重值,权重值=当前叶子节点的样本个数/总的样本个数。
A893A364-28A4-4AFA-94F9-FD6F6174978C.png IMG_3054.JPG C2A26E5A-2A7B-41E9-A447-A7326943FE5D.png
决策树常见算法
IMG_3056.JPG 00A63FA8-79BA-4E2E-AAAE-37D3166A42A6.png2 代码实现
# -*- coding: utf-8 -*-
# @Time : 2018/12/20 下午7:11
# @Author : scl
# @Email : 1163820757@qq.com
# @File : 决策树莺尾花(全).py
# @Software: PyCharm
'''
决策树案例 莺尾花数据分类
'''
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
import warnings
from sklearn.model_selection import train_test_split #测试集和训练集
from sklearn.preprocessing import MinMaxScaler #归一化处理库
from sklearn.tree import DecisionTreeClassifier
from sklearn.feature_selection import SelectKBest #特征选择
from sklearn.feature_selection import chi2 #卡方统计量
from sklearn.decomposition import PCA #主成分分析
## 设置属性防止中文乱码
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
warnings.filterwarnings('ignore', category=FutureWarning)
path = './datas/iris.data'
data = pd.read_csv(path, header = None)
x = data[list(range(4))]
# print(np.array(data[4]))
y = pd.Categorical(data[4]).codes #这个分类的分类代码
# print(y)
print("总样本数目:%d 特征属性数目%d"%(x.shape))
x_train, x_test, y_train, y_test = train_test_split(x, y,train_size = 0.8,
test_size=0.2,random_state=14)
## 因为需要体现以下是分类模型,因为DecisionTreeClassifier是分类算法,要求y必须是int类型
y_train = y_train.astype(np.int)
y_test = y_test.astype(np.int)
# 数据标准化
ss = MinMaxScaler()
x_train = ss.fit_transform(x_train)
x_test = ss.fit_transform(x_test)
# 特征选择
ch2 = SelectKBest(chi2,k=3)
x_train = ch2.fit_transform(x_train,y_train)
x_test = ch2.transform(x_test)
select_name_index = ch2.get_support(indices=True)
print ("对类别判断影响最大的三个特征属性分布是:",ch2.get_support(indices=False))
print(select_name_index)
# 降维处理
pca = PCA(n_components=2)
x_train = pca.fit_transform(x_train,y_train)
x_test = pca.transform(x_test)
# 模型加载
model = DecisionTreeClassifier(criterion='entropy',max_depth=20,random_state=0)
model.fit(x_train,y_train)
predict_hat = model.predict(x_test)
print("预测值%s"%(predict_hat))
print("训练集上的准确率%s"%(model.score(x_train,y_train)))
print("测试集准确率%s"%(model.score(x_test,y_test)))
print("特征的权重%s"%(model.feature_importances_)) #重要性权重,值越大表示该特征对于目标属性y的影响越大
# 画图 横竖轴
# 横轴采样范围 x1_min x1_max
x1_min = np.min((x_train.T[0].min(),x_test.T[0].min()))
x1_max = np.max((x_test.T[0].max(),x_train.T[0].max()))
x2_min = np.min((x_train.T[1].min(),x_test.T[1].min()))
x2_max = np.max((x_train.T[1].max(),x_test.T[1].max()))
print("横轴采样范围 [%s %s]"%(x1_min,x1_max))
print("纵轴采样范围 [%s %s]"%(x2_min,x2_max))
N = 100 #采样点
t1 = np.linspace(x1_min,x1_max,N)
t2 = np.linspace(x2_min,x2_max,N)
x1, x2 = np.meshgrid(t1,t2) # 生成网格采样点
x_show = np.dstack((x1.flat,x2.flat))[0] #测试点
y_show_hat = model.predict(x_show) #预测值
y_show_hat = y_show_hat.reshape(x1.shape) #使之与输入的形状相同
print(y_show_hat.shape)
print(y_show_hat[0])
print(y_show_hat[1])
# 画图 画样本点
plt_light = mpl.colors.ListedColormap(['#A0FFA0', '#FFA0A0', '#A0A0FF'])
plt_dark = mpl.colors.ListedColormap(['g', 'r', 'b'])
plt.figure(facecolor='w')
## 画一个区域
plt.pcolormesh(x1,x2,y_show_hat,cmap = plt_light)
# 画测试数据的点信息
plt.scatter(x_test.T[0], x_test.T[1], c=y_test.ravel(), edgecolors='k', s=150, zorder=10, cmap=plt_dark, marker='*') # 测试数据
# 画训练数据的点信息
plt.scatter(x_train.T[0], x_train.T[1], c=y_train.ravel(), edgecolors='k', s=40, cmap=plt_dark) # 全部数据
plt.xlabel(u'特征属性x1', fontsize=15)
plt.ylabel(u'特征属性x2', fontsize=15)
plt.xlim(x1_min, x1_max)
plt.ylim(x2_min, x2_max)
plt.grid(True)
plt.title(u'鸢尾花数据的决策树分类', fontsize=18)
plt.show()
#基于原始数据前3列比较一下决策树在不同深度的情况下错误率
x_train4, x_test4, y_train4, y_test4 = train_test_split(x.iloc[:,:2],y,train_size=0.7,test_size=0.3,random_state=14)
depths = np.arange(1,15)
err_list = []
for d in depths:
clf = DecisionTreeClassifier(criterion='entropy',max_depth=d,min_samples_split=10)
clf.fit(x_train4,y_train4)
score = clf.score(x_test4,y_test4)
err = 1- score
err_list.append(err)
print('树的深度%d 训练集上的正确率%.5f'%(d,clf.score(x_train4,y_train4)))
print("树的深度%d 测试集合上正确率%.5f"%(d,score))
plt.figure(facecolor='w')
plt.plot(depths, err_list,'ro-',lw=3)
plt.xlabel(u'决策树的深度',fontsize=16)
plt.ylabel(u'错误率',fontsize=16)
plt.grid(True)
plt.title(u'树的深度导致过拟合(欠拟合)问题')
plt.show()
效果图
决策树.png 决策树深度分析.png
3 决策树可视化
pic.png安装 graphviz服务
1 ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
2 brew install graphviz
3 怎么使用
新建pic.dot文件
digraph pic {
Hello -> World
}
打开终端 在pic.dot文件所在目录 dot pic.dot -T png -o pic.png
brew install graphviz
pip install pydotplus
import pydotplus
from sklearn import tree
dot_data = tree.export_graphviz(model,out_file=None)
graph = pydotplus.graph_from_dot_data(dot_data)
# graph.write_png("0.png")
graph.write_pdf("iris2.pdf")
image.png
网友评论