决策树算法讨论
(1)硬件环境
根据数据在纸上进行手动演算得到初期结果,使用电脑使用代码进行验证。
(2)软件环境
在电脑上验证时使用了python作为主要工具。
1.3 设计思想
(1)回归树概念:
回归决策树主要指CART(classification and regression tree)算法,内部结点特征的取值为“是”和“否”, 为二叉树结构。
所谓回归,就是根据特征向量来决定对应的输出值。回归树就是将特征空间划分成若干单元,每一个划分单元有一个特定的输出。因为每个结点都是“是”和“否”的判断,所以划分的边界是平行于坐标轴的。对于测试数据,我们只要按照特征将其归到某个单元,便得到对应的输出值。
划分的过程也就是建立树的过程,每划分一次,随即确定划分单元对应的输出,也就多了一个结点。当根据停止条件划分终止的时候,最终每个单元的输出也就确定了,也就是叶结点。
(2)回归树建立:
寻找切分点和确定输出值是回归决策树的核心。
1)切分点的选择使用最小二乘法
2)输出值的确定用单元内均值
原理如下:
1)设X和Y分别为输入和输出变量,并且Y是连续变量。给定训练数据集为D,其中x为输入实例,n为特征个数,i=1,2,...,N, N为样本容量。
2)特征空间的划分采用启发式方法,每次划分逐一考察当前集合中所有特征的所有取值,根据平方误差最小化准则选择其中最优的一个作为切分点。
也就是找出使要划分的两个区域平方误差和最小的j和s。
其中,c1,c2为划分后两个区域内固定的输出值,方括号内的两个min意为使用的是最优的c1和c2,也就是使各自区域内平方误差最小的c1和c2,易知这两个最优的输出值就是各自对应区域内Y的均值,所以上式可写为
(3)算法描述:
输入:训练数据集D;
输出:回归树f(x);
在训练数据集所在的输入空间中,递归地将每个区域划分为两个子区域并决定每个子区域上的输出值,构建二叉决策树:
1)选择最优切分变量j与切分点s,求解
遍历变量j,对固定的切分变量对j扫描切分点s,选择使上式达到最小值的对(j,s)。
2)用选定的对(j,s)划分区域并决定相应的输出值:
,
其中,,
3)继续对两个子区域调用步骤(1),(2),直至满足停止条件
(4) 将输入空间划分为M个区域
生成决策树:
其中I为指示函数,
例题:
将年收入定为Y,序号定为X,手动推演如下:
1.4 流程图
1.5 主要程序代码(要求必须有注释)
预测趋势的程序:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeRegressor #调用回归树模型
from sklearn import linear_model
# Data set
x = np.array(list(range(1, 11))).reshape(-1, 1) #序号作为输入值
y = np.array([12.5, 10, 7, 12, 9.5, 6, 22, 8.5, 7.5, 9]).ravel() #将收入当作输出值
# Fit regression model
model1 = DecisionTreeRegressor(max_depth=1) #决策树深度1
model2 = DecisionTreeRegressor(max_depth=3) #决策树深度3
model3 = linear_model.LinearRegression() #线性回归
model1.fit(x, y)
model2.fit(x, y)
model3.fit(x, y)
# Predict
X_test = np.arange(0.0, 10.0, 0.01)[:, np.newaxis] #确定x轴的范围
y_1 = model1.predict(X_test) #得到训练后返回的值进行预测
y_2 = model2.predict(X_test)
y_3 = model3.predict(X_test)
# Plot the results
plt.figure()
plt.scatter(x, y, s=20, edgecolor="black",
c="darkorange", label="data")
plt.plot(X_test, y_1, color="cornflowerblue",
label="max_depth=1", linewidth=2) #将预测数据的曲线带入图中
plt.plot(X_test, y_2, color="yellowgreen", label="max_depth=3", linewidth=2)
plt.plot(X_test, y_3, color='red', label='liner regression', linewidth=2)
plt.xlabel("data")
plt.ylabel("target")
plt.title("Decision Tree Regression")
plt.legend()
plt.show()
判断准确率的程序:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeRegressor #调用回归树模型
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
x = np.array(list(range(1, 11))).reshape(-1, 1)
y = np.array([12.5, 10, 7, 12, 9.5, 6, 22, 8.5, 7.5, 9]).ravel()
#创建模型
r_tree1 = DecisionTreeRegressor(max_depth=1)
r_tree3 = DecisionTreeRegressor(max_depth=3)
#训练模型
r_tree1.fit(x,y)
r_tree3.fit(x,y)
#求预测值
h1 = r_tree1.predict(x)
h3 = r_tree3.predict(x)
print('max_depths=1准确率:',r_tree1.score(x,y))
print('max_depths=3准确率:',r_tree3.score(x,y))
# 画图
plt.scatter(x,y,label='真实值')
plt.plot(x,h3,c='r',label='预测值')
plt.legend()
plt.show()
1.6 运行结果及分析
预测趋势的程序:
这个图的趋势和上面手动推演的结果基本一致,切分点在7.5和9.5左右。
判断准确率的程序:
输出结果为为:
因为决策树深度越深,正确率越高,因此可以将深度高的作为预测值,深度低的为真实值,从而得到更好的结果。