系列文章目录
浅入决策树的分类和回归
深入决策树的分类和回归
sklearn中的决策树
前言
在学习重要的基础算法的时候,我往往会偷懒忽视掉很多问题,就会陷入到,我觉得我会了,我知道是怎么个原理,就是一句代码拿来用就好,但真的要去讲解说明的时候,我却不知道从何说起,最后的conclusion就是实则我不是很清楚原理也讲不清原理。
在这里主要浅析决策树中的分类和回归原理,让我们不仅仅知道决策树是什么,还知道为什么和怎么做!
面对决策树,我问了自己三个问题:
决策树和人构建的决策树是否一样?
决策树如何做分类?
决策树如何做回归?
先看如下一段话:
“一方面决策树可以由人类手动制作 ,这种情况就不存在机器学习,另一方面,也可以选择让机器自动制作决策树模型,在这个时候,它就属于机器学习。制作出来的决策树模型会通过各个分支来理解yes/no的关系。”
——《深度学习的商业应用》 [日]日经大数据
这段话有三个点:
①由人类手动制作的决策树
②让机器自动制作决策树
③通过各个分支来理解yes/no的关系
下文将对上述我自己的三个疑问来叙述:
一 决策树机制—通过条件分支描述数据
先看看我们人类怎么对一堆东西进行分类
现在假设:
对四种动物进行分类(熊、鹰、企鹅、海豚)
我的目标:
提出尽可能少的if/else问题得到正确答案!
Ok,假设我提出:
①“动物有没有羽毛?”
我就把企鹅和鹰分到有羽毛的那组;
海豚和熊分到没有羽毛的那组;
我就得到了两个子节点,此时没有得到唯一的分类结果
②“会不会飞?”和“有没有鳍?”
会飞-鹰、不会飞-企鹅;
有鳍-海豚、没鳍-熊
ok,完成了分类。
这整个过程都是根据我的认知来构建的一个决策树模型。
因此,也就明了所谓“决策树”就是通过类似于“若满足A,则得到B”,“若满足B,则得到C”这样的逻辑表达式。
前面我的分类,这种逻辑表达式是人为生成的,机器学习的决策树就在于:由机器自动生成这样的逻辑表达式。
机器学习的魅力在于:
利用监督学习从数据中学习模型,无需我人为构建,它能从监督学习中看见我们人类看不见的并且寻找到最优分割点。
同样,为了构建这一决策树,决策树算法将搜索所有可能的测试:
就是为了找对目标变量(如上面分类这个目标)来讲信息量最大的那一个!
那回到我第一个问题:
1.机器学习决策树和人构建的决策树是否一样?
答:是一样的,就是这些分支条件,现在通过机器学习不要我们自己去设定了,他能从数据中通过监督学习看见我们看不见的并且找到最优的分割点。
二 机器学习的决策树分类
1. 决策树的二分类举例
决策树分类的核心就是:不断递归生成二元决策树,竭力去找最优分割点
比如说这样一个分2类的数据集,我们要对其进行划分
接下来,通过监督学习,加深树的深度,当深度为1的时候:
数据集将在x[1]≤0.0596处垂直进行划分,如上图黑线所示。通过测试x[1]是否≤0.0596对数据集进行划分,可以看到这一次划分还算可以:
左节点里包含属于类别A的2个点,数据类别B的32个点;
右节点里包含属于类别A的48个点,B类别的18个点。 两侧都还包含了对方类别的点。
Ok,那也就意味着,在已经被划分了的区域,需要重复寻找最佳测试来构建出更准确的模型。
继续,递归过程生成一棵二元决策树,其中每一个节点都包含一个测试,也相当于分层划分。,这个例子中只有两个特征x[0],x[1],因此划分区域的边界线始终与坐标轴平行。
不断递归下去!
当树中的某个叶节点所包含数据点的目标值都相同,那么这个叶节点就是纯的。
上面,当树的深度是9的时候,是最终的划分。
2. 决策树的多分类举例
其实决策树的多分类问题和二分类问题本质上差不多,为了方便理解,使用load_iris数据集举例说明
load_iris数据集介绍
· load_iris数据集总共150个样本,其中etosay、versicolor、irginca类样本各50个
· 维度数据4个,对应上图的红色区域,第5维度表示类别的标签
对该数据集使用决策树进行分类有如下:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier, plot_tree
# Parameters
n_classes = 3
plot_colors = "ryb"
plot_step = 0.02
# Load data
iris = load_iris()
for pairidx, pair in enumerate([[0, 1], [0, 2], [0, 3],
[1, 2], [1, 3], [2, 3]]):
# We only take the two corresponding features
X = iris.data[:, pair]
y = iris.target
# Train
clf = DecisionTreeClassifier().fit(X, y)
# Plot the decision boundary
plt.subplot(2, 3, pairidx + 1)
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, plot_step),
np.arange(y_min, y_max, plot_step))
plt.tight_layout(h_pad=0.5, w_pad=0.5, pad=2.5)
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
cs = plt.contourf(xx, yy, Z, cmap=plt.cm.RdYlBu)
plt.xlabel(iris.feature_names[pair[0]])
plt.ylabel(iris.feature_names[pair[1]])
# Plot the training points
for i, color in zip(range(n_classes), plot_colors):
idx = np.where(y == i)
plt.scatter(X[idx, 0], X[idx, 1], c=color, label=iris.target_names[i],
cmap=plt.cm.RdYlBu, edgecolor='black', s=15)
plt.suptitle("Decision surface of a decision tree using paired features")
plt.legend(loc='lower right', borderpad=0, handletextpad=0)
plt.axis("tight")
plt.figure()
clf = DecisionTreeClassifier().fit(iris.data, iris.target)
plot_tree(clf, filled=True)
plt.show()
对于决策树分类的机制就如下:
首先通过训练数据集训练出了决策树,训练过程中,决策树很暴力的去寻找每一个最优分割点,全力搜寻,能看出我们看不出的分割点, 最后训练出决策树的结构和结点,然后待预测样本只需要根据所训练出的决策树走到决策树的某个叶子结点,输出该结点早就计算好的分类类别或者某个类别的概率即可!【根据训练样本分配到每个叶子结点的数量计算出了每个叶子结点对应的所属类别的概率】等到我们输入测试集的时候就能自上而下得到其分类结果。
二、决策树回归
决策树也可以用到回归任务,使用的方法也一样:
基于每个结点的测试对树进行遍历,最终找到新数据所属的叶节点,这一结点的输出即为此叶节点中所有训练点的平均值。
现在看回归决策树,训练数据如下,特征向量只有一维即x:
x | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
y | 5.56 | 5.7 | 5.91 | 6.4 | 6.8 | 7.05 | 8.9 | 8.7 | 9 | 9.05 |
如何做到回归?
同样也是二叉树,为了说明原理,我假设我自己就是机器学习算法的黑盒子——暴力寻最优分割点的那个玩意,我选择最优切分变量【切分变量两个相邻取值区间内任意一点均可】
此时考虑:
{1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5}:
通过计算每个待切分的损失函数值:
a.计算子区域输出值
当s=1.5时,两个子区域R1={1},R2={2,3,4,5,6,7,8,9,10}
c1=5.56
同理,得到其它各切点的子区域输出值,列表如下:
s | 1.5 | 2.5 | 3.5 | 4.5 | 5.5 | 6.5 | 7.5 | 8.5 | 9.5 |
c1 | 5.56 | 5.63 | 5.72 | 5.89 | 6.07 | 6.24 | 6.62 | 6.88 | 7.11 |
c2 | 7.5 | 7.73 | 7.99 | 8.25 | 8.54 | 8.91 | 8.92 | 9.03 | 9.05 |
b.计算损失函数值。找到最优切分点
当S=1.5时
同理,计算得到其它切分点的损失函数值,列表如下:
s | 1.5 | 2.5 | 3.5 | 4.5 | 5.5 | 6.5 | 7.5 | 8.5 | 9.5 |
L(s) | 15.72 | 12.07 | 8.36 | 5.78 | 3.91 | 1.93 | 8.01 | 11.73 | 15.74 |
正如这次,选择1.5作为切分点,之后计算出的损失函数L(6.5)时最小的,所以我找到第一个切分点:6.5
现在我就有两个区间
R1:{1,2,3,4,5,6}
R2:{7,8,9}
对R1取切分点:{1.5,2.5,3.5, 4.5, 5.5}
s | 1.5 | 2.5 | 3.5 | 4.5 | 5.5 |
c1 | 5.56 | 5.63 | 5.72 | 5.89 | 6.07 |
c2 | 6.37 | 6.54 | 6.75 | 6.93 | 7.05 |
损失函数为
s | 1.5 | 2.5 | 3.5 | 4.5 | 5.5 |
L(s) | 1.3087 | 0.754 | 0.2771 | 0.4368 | 1.0644 |
ok,我得到第二个划分点3.5
假设树的深度为2,两次划分之后就停止了,就得到如下决策树:
最终的到的结果是:
当x<=3.5时, y为5.72
当3.5<=x<=6.5时,y为5.72
当6.5<=x时, y为5.72
原来,决策树做回归是这么一个道理,也是将这堆数据不断的分类,分类,分类…ok,够深了,最后不分了,我取平均值就好了,取这个所有被分到同一个最末叶子结点的所有值的平均值就好啦。
那关于第三个问题:3.决策树如何做回归?
答案就是上述了。
总结
对于决策树实际上就是在一堆数据间分类,分类,分类—ok,最终完成每一类的划分。
但是决策树又是怎么选取结点的?
决策树的深度会一直增加?这不会造成过拟合?
对于这些将在下一篇进行详细讲解
参考1参考2