核心:划分点选择 + 输出值确定。
信息增益准则对可取值数目较多的属性有所偏好,为解决这种偏好问题,C4.5算法使用“增益率”。但是,增益率准则对可取值数目较少的属性有所偏好!
数据集的纯度还可以使用基尼值来表示,基尼指数最小的属性作为最优化分属性。
预剪枝:在决策树的生成过程中,对每个节点在划分前进行估计,若当前划分不能带来决策树泛化性能的提升,则停止划分并将当前节点标记为叶节点。节省训练开销,但是会带来欠拟合。
后剪枝:先生成一颗完整的决策树,自低而上的对非叶节点进行考察,若将该节点对应的子树替换为叶节点能带来泛化性能的提升,则将该子树替换为叶节点。后剪枝通常比预剪枝保留更多的分支,欠拟合的风险更小,泛化性能优于预剪枝。
如果数据存在缺失值时,划分决策树时需要考虑两个问题:
如何在属性缺失的情况下进行划分属性选择?
给定划分属性,若样本在该属性上的值缺失,如何对样本进行划分?–修改权重,将同一个样本以不同概率划分到不同的子节点中。
另一个问题,决策树的分类边界都是轴平行的,故此引入多变量决策树:不是为每个非叶节点寻找一个最优划分属性,而是试图建立一个合适的线性分类器。
一、概述
决策树是一种基本的分类与回归方法。回归决策树主要是指CART(classification and regression tree)算法,内部结点特征的取值为“是”和“否”, 为二叉树结构。
所谓回归,就是根据特征向量来决定对应的输出值。回归树就是将特征空间划分成若干单元,每一个划分单元有一个特定的输出。因为每个结点都是“是”和“否”的判断,所以划分的边界是平行于坐标轴的。对于测试数据,我们只要按照特征将其归到某个单元,便得到对应的输出值。
二、回归树建立
既然要划分,切分点怎么找?输出值又怎么确定?这两个问题也就是回归决策树的核心。
对特征空间的划分采用启发式方法,每次划分逐一考察当前集合中所有特征的所有取值,根据平方误差最小化准则选择其中最优的一个作为切分点。
[切分点选择:最小二乘法]; [输出值:单元内均值]
算法描述:
三、示例
下表为训练数据集,特征向量只有一维,根据此数据表建立回归决策树。
(1) 选择最优切分变量j与最优切分点s:
在本数据集中,只有一个特征变量,最优切分变量自然是x。接下来考虑9个切分点
{ 1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5 }(切分变量两个相邻取值区间)内任一点均可),根据式(1.2)计算每个待切分点的损失函数值:
四、Python实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn import linear_model
from sklearn.externals.six import StringIO
from sklearn import tree
import pydotplus
# Data set
x = np.array(list(range(1, 11))).reshape(-1, 1)
y = np.array([5.56, 5.70, 5.91, 6.40, 6.80, 7.05, 8.90, 8.70, 9.00, 9.05]).ravel()
# Fit regression model
model1 = tree.DecisionTreeRegressor(max_depth=1)
model2 = tree.DecisionTreeRegressor(max_depth=3)
model3 = linear_model.LinearRegression()
model1 = model1.fit(x, y)
model2 = model2.fit(x, y)
model3 = model3.fit(x, y)
# Predict
X_test = np.arange(0.0, 10.0, 0.01)[:, np.newaxis] # 注意这个方式,训练数据需要传入(number,1)维度
y_1 = model1.predict(X_test)
y_2 = model2.predict(X_test)
y_3 = model3.predict(X_test)
# 可视化1:决策树model2
dot_data = StringIO()
tree.export_graphviz(model2, out_file=dot_data, # 绘制决策树
filled=True, rounded=True,
special_characters=True)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
graph.write_pdf("tree.pdf")
# 可视化2: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<