决策树概述
决策树是一种分类和预测方法,有监督的学习算法,以树状图为基础,决策树利用分层的思想将一个复杂的问题分解为多个简单的判断问题,最后得到最大支持的决策结果。
优点:
可读性强,分类速度快,计算复杂度不高时,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关的特征数据
缺点:
可能产生过度匹配问题
构建决策树步骤
1.特征选择
2.决策树生成
3.决策树剪枝
1.特征选择
特征选择就是选择具有较强分类能力的特征,分类通过信息增益或者信息增益比来刻画。
有点类似于kd-tree的划分,他的划分是找出数据的方差最大的维度的中间值作为划分,反正都是要制定一个规则来作为划分的依据的。
决策树特征选择标准:局部最优特征,也就是当前数据集上哪个特征在划分数据类型时期决定性作用
个人理解,比如你区分一个人是男生还是女生,比如头发长度,胸部,皮肤等 最直观的就是胸部,所以最开始划分的时候胸部就是局部最优特征,这个例子有点……
1)信息增益
划分数据集的最大原则是:将无序数据集变得更加有序
个人理解,就是比如区分100个人是男是女,假如50个男的50个女的,你通过胸部来判断,那直接把男女区分开了 ,通过皮肤判断,区分成60个女,40个男(毕竟有些男的皮肤比较好,哈哈),通过头发长度判断55个女,45个男(有些男的留长发),这样的话肯定是通过胸部判断,纯度更好啊,因为分开的两个数据集分别都是纯爷们和纯妹纸,所以胸部就是信息增益最大的特征,分类能力最强的特征
衡量数据集合纯度的方法有:熵,基尼系数和方差,熵和基尼系数是针对分类的,方差是针对回归的
熵的概念:
设X是一个随机的离散变量,其概率分布为:
则随机变量X的熵为:
熵值越高,数据的无序程度就越高,数据集混合的数据越多
计算熵
import math
def calculate_entropy(dataset):
event_dic={}#创建一个事件字典,键为事件,键值是事件出现的次数
length=len(dataset)#数据集长度
for each in dataset:
if each in event_dic:#如果该事件在字典中
event_dic[each]+=1#则事件出现次数+1
else:
event_dic[each]=1#若事件不在字典中对其出现次数赋值为1
entropy=0.0
for key in event_dic:
prob=float(event_dic[key]/length)#计算某一事件在整个事件中的概率
entropy -= prob * math.log(prob,2)#计算熵
return entropy
2)划分数据集:
循环计算所有特征划分数据集后的香农熵,并利用原始数据集的熵和划分后的熵相减得到该特征划分的信息增益。取信息增益最大的划分,作为最好的划分方式。
比如上面那个例子,胸部为信息增益最大的部分,其次是头发长度和皮肤
2.决策树生成
决策树生成的典型算法有ID3算法和C4.5算法,他们生成树的过程类似,ID3采取的是信息增益作为特征选择的度量,而C4.5则采取的是信息增益比。
构建决策树原理:拿到一个数据集,可能改数据集具有多个特征,那么我们计算每个特征的熵,选择信息增益最大的特征值划分数据集,第一次划分只有可能会有多个子集,然后对子集再根据特征的熵进行划分,因此可以采用递归原理构建决策树。
递归结束条件:所有的数据被遍历完毕,或者自己中所有实例都具有相同分类
3.决策树剪枝
剪枝原因:决策树对训练数据的预测很准确,但是位置的数据分类却很差,这就产生过拟合现象。
解决过拟合的方法是控制模型的复杂度,对于决策树来说就是简化模型,成为剪枝
剪枝目的:平衡精度和复杂度,使模型精度够用并且复杂度降低,防止过拟合,提高泛化能力
1)损失函数
设决策树的子节点集合为T,t是T中的一个元素,设该节点有Nt个样本,其中k类的样本个数为Ntk个,共k个分类,则叶节点T的经验熵为:
则损失函数可以定义为:
上面损失函数,α为参数,控制复杂度和精度之间的影响,其较大模型选择越简单。
2)剪枝算法
剪枝之前的整体树为T1,剪掉一组叶节点后的整体树为T2,计算损失函数C(T1)和C(T2),如果剪掉之后的损失函数更小,则剪枝,否则不行。
Scikit-learn代码实现
1.回归决策树
python代码:
import numpy as np
from sklearn.tree import DecisionTreeRegressor
from sklearn.model_selection import train_test_split
#给出一个随机数据集
def create_data(n):#n为数据容量
np.random.seed(0)
x=5*np.random.rand(n,1)
y=np.sin(x).ravel()#散开
noise_num=(int)(n/5)
y[::5]+=3*(0.5-np.random.rand(noise_num))
return train_test_split(x,y,test_size=0.25,random_state=1)
#决策树回归测试函数
def test_DecisionTreeRegression(*data):
x_train,x_test,y_train,y_test=data
regr=DecisionTreeRegressor()
regr.fit(x_train,y_train)
print("training score:%f"%(regr.score(x_train,y_train)))
print("Testing score:%f"%(regr.score(x_test,y_test)))
x_train,x_test,y_train,y_test=create_data(100)
test_DecisionTreeRegression(x_train,x_test,y_train,y_test)
结果:
可以发现对训练集拟合的非常好,测试集要差很多,泛化能力较差
max_depth树的最大深度对回归的影响:决策树深度对应树复杂度,越深,模型越复杂
regr=DecisionRegression(max_depth=depth)
画出结果:
def test_DecisionTreeRegression(*data,maxdepth):
x_train,x_test,y_train,y_test=data
depths=np.arange(1,maxdepth#深度
train_scores=[]
test_scores=[]
for depth in depths:
regr=DecisionTreeRegressor(max_depth=depth)
regr.fit(x_train,y_train)
train_scores.append(regr.score(x_train,y_train))
test_scores.append(regr.score(x_test,y_test))
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
ax.plot(depths,train_scores,label="train scores")
ax.plot(depths,test_scores,label="test scores")
ax.set_xlabel("max_depth")
ax.set_ylabel("scores")
ax.set_title("Decision Regression")
ax.legend(framealpha=0.5)
plt.show()
结果:
二叉树最深为log2(100)=6.65,所以树的深度在7之后,也就无法划分了
2.分类决策树
python代码
import numpy as np
from sklearn.tree import DecisionTreeRegressor
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from sklearn import datasets
def load_data():#加载鸢尾花数据
iris=datasets.load_iris()
x_train=iris.data
y_train=iris.target
return train_test_split(x_train,y_train,test_size=0.25,random_state=0,stratify=y_train)
def test_DecisionTreeClassiffier(*data):#决策树分类
x_train, x_test, y_train, y_test = data
clf=DecisionTreeRegressor()
clf.fit(x_train,y_train)
print("Train score:%s"%(clf.score(x_train,y_train)))
print("test score:%s"%(clf.score(x_test,y_test)))
x_train,x_test,y_train,y_test=load_data()
test_DecisionTreeClassiffier(x_train,x_test,y_train,y_test)
结果:
DecisionTreeClassifier()可选择参数说明:
1.criterion:切分质量评价准则
‘gini’评价准则是基尼系数
‘entropy’评价准则是熵
2.splitter:切分原则
‘best’最优切分
‘random’随机切分
3.max_depth:树的最大深度
切分原则影响
def test_DecisionTreeClassiffier(*data):
x_train, x_test, y_train, y_test = data
splitters=['best','random']
for splitter in splitters:
clf=DecisionTreeRegressor(splitter=splitter)
clf.fit(x_train,y_train)
print("criterion:%s"%splitter)
print("Train score:%s"%(clf.score(x_train,y_train)))
print("test score:%s"%(clf.score(x_test,y_test)))
x_train,x_test,y_train,y_test=create_data(100)
test_DecisionTreeClassiffier(x_train,x_test,y_train,y_test)
结果:
其他的参数就不一一举例子了 可以自己试一下
参考:
《python大战机器学习》
https://blog.csdn.net/czliuming/article/details/51302411
https://blog.csdn.net/wjc1182511338/article/details/76793153