文章目录
- 一、决策树
- 二、决策树学习算法
- 2.1 特征选择
- 2.1.1 熵
- 2.1.1.1 条件熵
- 2.1.2 信息增益
- 2.1.3 信息增益率
- 2.1.4 基尼指数
- 2.2 决策树生成
- 2.2.1 ID3
- 2.2.2 C4.5
- 2.2.3 CART(为二叉树)
- 2.3 决策树剪枝
- 2.3.1 max_depth
- 2.3.2 min_samples_leaf
- 2.3.3 min_samples_split
- 2.3.4 max_features
- 2.3.5 min_impurity_decrease
- 三、代码
- 3.1 决策树红酒数据集
- 3.2 决策树鸢尾花数据集
- 四、回归树
- 4.1 代码
一、决策树
决策树模型是运用于分类以及回归的一种树结构。决策树由节点和有向边组成,一般一棵决策树包含一个根节点、若干内部节点和若干叶节点。决策树的决策过程需要从决策树的根节点开始,待测数据与决策树中的特征节点进行比较,并按照比较结果选择选择下一比较分支,直到叶子节点作为最终的决策结果。
- 内部节点:对应于一个属性测试
- 叶节点:对应于决策结果
- 根节点包含样本全集;
- 每个节点包括的样本集合根据属性测试的结果被划分到子节点中;
- 根节点到每个叶节点的路径对应对应了一个判定测试路径;
决策树的结构还是比较好理解的,如果不明白,可以看一下图中的例子,这是一个简单判断这个键盘我喜不喜欢的决策树模型:
二、决策树学习算法
- 特征选择
- 决策树生成
- 决策树剪枝
2.1 特征选择
特征选择也即选择最优划分属性,从当前数据的特征中选择一个特征作为当前节点的划分标准。我们希望在不断划分的过程中,决策树的分支节点所包含的样本尽可能属于同一类,即节点的“纯度”越来越高。而选择最优划分特征的标准不同,也导致了决策树算法的不同。
为了找到最优的划分特征,我们需要先了解一些信息论的知识:
- 信息熵(information entropy)
- 信息增益(information gain)
- 信息增益率(information gain ratio)
- 基尼指数(Gini index)
2.1.1 熵
在信息论和概率统计中,熵(entropy)是表示随机变量不确定性的度量,设X是一个取有限值的离散随机变量,其概率分布为:
则随机变量X的熵定义为:(对数通常以2为底)
**熵越大,随机变量的不确定性越大。**为了能够更好地理解熵的意义,我们下面举一个例子来说明。
当随机变量只取两个值,如1,0时,即X的分布为:
则熵为:
H§的函数图像如下:
从图中我们不难看出p=0或者1时H§为0,即不确定性为0。当p=0.5时,不确定性最大。
2.1.1.1 条件熵
设有随机变量(X,Y)。条件熵H(Y|X)表示在已知随机变量X的条件下随机变量Y的不确定性。随机变量X给定的条件下随机变量Y的条件熵H(Y|X)定义为X给定条件下Y的条件概率分布的熵对X的数学期望:
这里,pi=P(X=xi),i=1,2,…,n
2.1.2 信息增益
简单讲:不确定性的减少,确定性的增加。
下图,个人认为D(D|A)应该为H(A|D):给定条件D,特征A的条件熵。
2.1.3 信息增益率
类似于归一化,归到同一量纲下。(配分函数/归一化函数)
下面这张图可以来理解信息增益与信息增益率:
2.1.4 基尼指数
取值范围在[0,1]。基尼指数越小,熵越大,越不确定。熵是越大越不确定。
基尼不纯度:指将来自集合中的某种结果随机应用在集合中,某一数据项的预期误差率。(决策树衡量信息量)
2.2 决策树生成
生成算法 | 划分标准 |
ID3 | 信息增益 |
C4.5 | 信息增益率 |
CART | 基尼指数 |
2.2.1 ID3
ID3ID3 算法的核心是在决策树各个节点上根据信息增益来选择进行划分的特征,然后递归地构建决策树。
具体方法:
1.从根节点开始,对节点计算所有可能的特征的信息增益,选择信息增益值最大的特征作为节点的划分特征;
2.由该特征的不同取值建立子节点;
3.再对子节点递归地调用以上方法,构建决策树;
4.到所有特征的信息增益都很小或者没有特征可以选择为止,得到最终的决策树。
ID3的局限:
1.没有剪枝
2.采用信息增益作为选择最优划分特征的标准,然而信息增益会偏向那些取值较多的特征(这也是C4.5采用信息增益率的原因)。(数据不均匀)
ID3算法举例:
2.2.2 C4.5
C4.5与ID3相似,但对ID3进行了改进,讲一下有哪些基于ID3的改进:
1.用信息增益率来选择划分特征,克服了用信息增益选择的不足
2.在构造树的过程中进行剪枝
3.可对连续值与缺失值进行处理
有一些事情做不到,因为熵的取值范围大于0。
2.2.3 CART(为二叉树)
CART(classification and regressiontree), 分类回归树算法,既可用于分类也可用于回归,在这一部分我们先主要将其分类树的生成。区别于ID3和C4.5,CART假设决策树是二叉树,内部节点特征的取值为“是”和“否”,左分支为取值为“是”的分支,右分支为取值为”否“的分支。这样的决策树等价于递归地二分每个特征,将输入空间(即特征空间)划分为有限个单元。CART的分类树用基尼指数来选择最优特征的最优划分点,
具体过程:
1.从根节点开始,对节点计算现有特征的基尼指数,对每一个特征,例如A,再对其每个可能的取值如a,根据样本点对A=a的结果的”是“与”否“划分为两个部分,利用下面这个公式进行计算
2.在所有可能的特征A以及该特征所有的可能取值a中,选择基尼指数最小的特征及其对应的取值作为最优特征和最优切分点。然后根据最优特征和最优切分点,将本节点的数据集二分,生成两个子节点。(例:ABC分A|BC算一次,AB|C算一次,取gini指数小的值切分;连续数据用离散化分割等份数据)
3.对两个字节点递归地调用上述步骤,直至节点中的样本个数小于阈值,或者样本集的基尼指数小于阈值,或者没有更多特征后停止;
4.生成CART分类树。
2.3 决策树剪枝
在不加限制的情况下,一棵决策树会生长到衡量不纯度的指标最优,或者没有更多的特征可用为止。这样的决策树往往会过拟合,这就是说,它会在训练集上表现很好,在测试集上却表现糟糕。我们收集的样本数据不可能和整体的状况完全一致,因此当一棵决策树对训练数据有了过于优秀的解释性,它找出的规则必然包含了训练样本中的噪声,并使它对未知数据的拟合程度不足。
为了让决策树有更好地泛华性,我们要对决策树进行剪枝。剪枝策略对决策树的影响巨大,正确的剪枝策略是优化决策树算法的核心。sklearn为我们提供了不同的剪枝策略:
2.3.1 max_depth
限制树的最大深度,超过设定深度的树枝全部剪掉
2.3.2 min_samples_leaf
一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分枝就不会发生,或者,分枝会朝着满足每个子节点都包含min_samples_leaf个样本的方向去发生。
2.3.3 min_samples_split
一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分枝,否则分枝就不会发生。
2.3.4 max_features
限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃。
2.3.5 min_impurity_decrease
限制信息增益的大小,信息增益小于设定数值的分枝不会发生。
三、代码
3.1 决策树红酒数据集
# 决策树红酒数据集.py
#
import numpy as np
from sklearn import tree, datasets, preprocessing
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import graphviz
np.random.RandomState(0)
# 加载数据
wine = datasets.load_wine()
# 划分训练集与测试集
x, y = wine.data, wine.target
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3,random_state=0)
# 数据预处理
scaler = preprocessing.StandardScaler().fit(x_train)
x_train = scaler.transform(x_train)
x_test = scaler.transform(x_test)
# 创建模型
clf = tree.DecisionTreeClassifier(criterion="gini",random_state=0,max_depth=3,min_samples_leaf=2)# 随机状态为0,表示种子确定了
# 模型拟合
clf.fit(x_train, y_train)
# 预测
y_pred = clf.predict(x_test)
# 评估
print(accuracy_score(y_test, y_pred))
# 查看特征权重
print(wine.feature_names)
print(clf.feature_importances_)
dot_data = tree.export_graphviz(clf, out_file=None,
feature_names=wine.feature_names,
class_names=wine.target_names,
filled=True, rounded=True,
special_characters=True)
graph = graphviz.Source(dot_data)
graph.render("wine")
参数解释:
(1)criterion:
为了要将表格转化为一棵树,决策树需要找出最佳节点和最佳的分枝方法,对分类树来说,衡量这个“最佳”的指标叫做“不纯度”。通常来说,不纯度越低,决策树对训练集的拟合越好。现在使用的决策树算法在分枝方法上的核心大多是围绕在对某个不纯度相关指标的最优化上。
不纯度基于节点来计算,树中的每个节点都会有一个不纯度,并且子节点的不纯度一定是低于父节点的,也就是说,在同一棵决策树上,叶子节点的不纯度一定是最低的。
Criterion这个参数正是用来决定不纯度的计算方法的。sklearn提供了两种选择:
1)输入”entropy“,使用信息熵(Entropy)
2)输入”gini“,使用基尼系数(Gini Impurity)
其中t代表给定的节点,i代表标签的任意分类,p(i|t)代表标签分类i在节点t上所占的比例。注意,当使用信息熵时,sklearn实际计算的是基于信息熵的信息增益(Information Gain),即父节点的信息熵和子节点的信息熵之差。
比起基尼系数,信息熵对不纯度更加敏感,对不纯度的惩罚最强。但是在实际使用中,信息熵和基尼系数的效果基本相同。信息熵的计算比基尼系数缓慢一些,因为基尼系数的计算不涉及对数。另外,因为信息熵对不纯度更加敏感,所以信息熵作为指标时,决策树的生长会更加“精细”,因此对于高维数据或者噪音很多的数据,信息熵很容易过拟合,基尼系数在这种情况下效果往往比较好。当然,这不是绝对的。
其实,无论决策树模型如何进化,在分枝上的本质都还是追求某个不纯度相关的指标的优化,而正如我们提到的,不纯度是基于节点来计算的,也就是说,决策树在建树时,是靠优化节点来追求一棵优化的树,但最优的节点能够保证最优的树吗?集成算法被用来解决这个问题:sklearn表示,既然一棵树不能保证最优,那就建更多的不同的树,然后从中取最好的。怎样从一组数据集中建不同的树?在每次分枝时,不从使用全部特征,而是随机选取一部分特征,从中选取不纯度相关指标最优的作为分枝用的节点。这样,每次生成的树也就不同了。
(2)random_state:
random_state用来设置分枝中的随机模式的参数,默认None,在高维度时随机性会表现更明显,低维度的数据(比如鸢尾花数据集),随机性几乎不会显现。输入任意整数,会一直长出同一棵树,让模型稳定下来。
(3)splitter:
splitter也是用来控制决策树中的随机选项的,有两种输入值,输入”best",决策树在分枝时虽然随机,但是还是会优先选择更重要的特征进行分枝(重要性可以通过属性feature_importances_查看),输入“random",决策树在分枝时会更加随机,树会因为含有更多的不必要信息而更深更大,并因这些不必要信息而降低对训练集的拟合。这也是防止过拟合的一种方式。当你预测到你的模型会过拟合,用这两个参数来帮助你降低树建成之后过拟合的可能性。当然,树一旦建成,我们依然是使用剪枝参数来防止过拟合。
3.2 决策树鸢尾花数据集
# 决策树.py
#
import numpy as np
from sklearn import tree, datasets, preprocessing
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import graphviz
np.random.RandomState(0)
# 加载数据
iris = datasets.load_iris()
# 划分训练集与测试集
x, y = iris.data, iris.target
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3)
# 数据预处理
scaler = preprocessing.StandardScaler().fit(x_train)
x_train = scaler.transform(x_train)
x_test = scaler.transform(x_test)
# 创建模型
clf = tree.DecisionTreeClassifier()
# 模型拟合
clf.fit(x_train, y_train)
# 预测
y_pred = clf.predict(x_test)
# 评估
print(accuracy_score(y_test, y_pred))
dot_data = tree.export_graphviz(clf, out_file=None,
feature_names=iris.feature_names,
class_names=iris.target_names,
filled=True, rounded=True,
special_characters=True)
graph = graphviz.Source(dot_data)
graph.render("iris")# 导出pdf文件
四、回归树
决策树能够做分类问题,但是到了CART发明的时候,既能做分类也能做回归。内部节点特征的取值是“是”和“否”,为二叉树结构。
决策树的生成就是递归地构建二叉决策树的过程,对回归树用平方误差最小化准则,对分类树用基尼指数最小化准则,进行特征选择,生成二叉树。
最小二乘回归树的生成方法如下:
回归树例子:
4.1 代码
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([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 = DecisionTreeRegressor(max_depth=1)
model2 = DecisionTreeRegressor(max_depth=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]
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()