失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 机器学习实战6-sklearn训练决策树实现分类和回归

机器学习实战6-sklearn训练决策树实现分类和回归

时间:2022-07-02 17:08:31

相关推荐

机器学习实战6-sklearn训练决策树实现分类和回归

简介:

与SVM一样,决策树也是一种多功能的机器学习算法,它可以实现分类和回归任务,甚至是多输出任务。它们功能强大,能够拟合复杂的数据集。决策树同时也是随机森林(参见第7章)的基本组成部分,后者是现今最强大的机器学习算法之一。

首先,我们会讨论如何对决策树进行训练、可视化和预测;然后介绍Scikit-Learn的CART训练算法,讨论如何对决策树进

行正则化并将其用于回归任务;最后,我们会谈一谈决策树的局限性。

一个决策树实例:

1、构建一个决策树

看看它是如何做出预测的。下面的代码在鸢尾花数据集上训练了一个DecisionTreeClassifier:

(Scikit-Learn使用的是CART算法,该算法仅生成二叉树:非叶节点永远只有两个子节点(即问题答案仅有是或否)。但是,其他

算法,比如ID3生成的决策树,其节点可以拥有两个以上的子节点)

from sklearn.datasets import load_irisfrom sklearn.tree import DecisionTreeClassifieriris=load_iris()X=iris.data[:,2:]y=iris.targettree_clf=DecisionTreeClassifier(max_depth=2,random_state=42)tree_clf.fit(X,y)

输出一个树结构:

DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=2,max_features=None, max_leaf_nodes=None,min_impurity_decrease=0.0, min_impurity_split=None,min_samples_leaf=1, min_samples_split=2,min_weight_fraction_leaf=0.0, presort=False, random_state=42,splitter='best')

tree.DecisionTreeClassifier(class_weight=None, #balanced & None 可选criterion='gini',#"gini"或者"entropy",前者代表基尼系数,后者代表信息增益。max_depth=None,#max_depth控制树的深度防止overfittingmax_features=None, #可使用多种类型值,默认是"None",划分时考虑所有的特征数;#"log2" 划分时最多考虑log2Nlog2N个特征;#"sqrt"或者"auto" 划分时最多考虑√N个特征。#整数,代表考虑的特征绝对数。#浮点数,代表考虑特征百分比,即考虑(百分比xN)取整后的特征数。#其中N为样本总特征数。max_leaf_nodes=None,#最大叶节点树min_impurity_split=1e-07, #限制决策树的增长,#如果某节点的不纯度(基尼系数,信息增益)小于这个阈值,则该节点不再生成子节点,即为叶子节点。 min_samples_leaf=1,min_samples_split=2,#min_samples_split或min_samples_leaf来控制叶节点上的样本数量;#两者之间的主要区别在于min_samples_leaf保证了叶片中最小的样本数量,而min_samples_split可以创建任意的小叶子。但min_samples_split在文献中更常见。min_weight_fraction_leaf=0.0,#限制叶子节点所有样本权重和的最小值。如果小于这个值,则会和兄弟节点一起被剪枝。# 默认是0,就是不考虑权重问题。#一般来说,如果我们有较多样本有缺失值,或者分类树样本的分布类别偏差很大,#就会引入样本权重,这时我们就要注意这个值了。presort=False,#布尔值,默认是False不排序。预排序,提高效率。#设置为true可以让划分点选择更加快,决策树建立的更加快。random_state=None, #随机生成器种子设置,默认设置为None,如此,则每次模型结果都会有所不同。splitter='best')#split"best"或者"random"。#前者在特征的所有划分点中找出最优的划分点。#后者是随机的在部分划分点中找局部最优的划分点。#默认的"best"适合样本量不大的时候,而如果样本数据量非常大,此时决策树构建推荐"random"。

参数详情:/qq_30815237/article/details/89218316

参数说明:

samples属性:统计它应用的训练实例数量。例如,有100个训练实例的花瓣长度大于2.45厘米(深度1,右),其中54个花瓣宽度小于1.75厘米(深度2,左)。

value属性:说明了该节点上每个类别的训练实例数量:例如,右下节点应用在0个Setosa鸢尾、1个Versicolor鸢尾和45个Virginica鸢尾实例上。

class属性:说明该节点的类别。

节点的gini属性:衡量其不纯度(impurity):如果应用的所有训练实例都属于同一个类别,那么节点就是“纯”的(gini=0)。例如,深度1左侧节点仅应用于Setosa鸢尾花训练实例,所以它就是纯的,并且gini值为0。

基尼不纯度:

其中:是第i个节点上,类别为k的训练实例占比。

例如,深度2左侧节点,基尼系数等于 1–(0/54)^2 –(49/54)^2 –(5/54)^2 ≈0.168。

决策树的特质之一就是它们需要的数据准备工作非常少。完全不需要进行特征缩放或集中。

如何做出预测?

以上图中的树为例,如果你找到了一朵鸢尾花,想要将其归类,那么从根节点(深度0,位于顶部)开始:这朵花的花瓣长度是否小于2.45厘米?如果是,则向下移动到根的左侧子节点(深度1,左)。本例中,这是一个叶节点(即没有任何子节点),所以它不再继续提出问题,你可以直接查看这个节点的预测类别,也就是说,决策树预测你的这朵花是Setosa鸢尾花(class=setosa)。

假设你又找到了一朵花,但是这次的花瓣长度大于2.45厘米。你必须移动到根节点的右侧子节点(深度1,右),该节点不是叶节点,所以它提出另一个问题:花瓣宽度是否小于1.75厘米?如果是,那这朵花最有可能是Versicolor鸢尾花(深度2,左);如果不是,那就可能是Virginica鸢尾花(深度2,右)。就是这么简单。

2、训练完成后,使用决策树对测试集数据进行分类:

决策树除了可以输出实例所属的类别k外,同样可以估算某个实例属于特定类别k的概率:首先,跟随决策树找到该实例的叶节点,然后返回该节点中类别k的训练实例占比。

例如,假设你发现一朵花,其花瓣长5厘米,宽1.5厘米。相应的叶节点为深度2左侧节点,因此决策树输出如下概率:Setosa鸢尾花,0%(0/54);Versicolor鸢尾花,90.7%(49/54);Virginica鸢尾花,9.3%(5/54)。当然,如果你要求它预测类别,那么它应该输出Versicolor鸢尾花(类别1),因为它的概率最高。

tree_clf.predict_proba([[5, 1.5]])out:array([[0. , 0.90740741, 0.09259259]])tree_clf.predict([[5, 1.5]])out:array([1])

下图显示了决策树的决策边界。加粗直线表示根节点(深度0)的决策边界:花瓣长度=2.45厘米。因为左侧区域是纯的(只有Setosa鸢尾花),所以它不可再分。但是右侧区域是不纯的,所以深度1右侧的节点在花瓣宽度=1.75厘米处(虚线所示)再次分裂。因为这里最大深度max_depth设置为2,所以决策树在此停止。但是如果你将max_depth设置为3,那么两个深度为2的节点将各自再产生一条决策边界(点线所示)。

说明:决策树是非常直观的,它们的决策也很容易解释,这类模型通常被称为白盒模型。与之相反的,我们稍后将会看到,随机

森林或是神经网络被认为是一种黑盒模型。它们能做出很棒的预测,你也可以轻松检查它们在做出预测时执行的计算,然而,通常很难解释清楚它们为什么做出这样的预测。

CART训练算法

1、成本函数

Scikit-Learn使用的是分类与回归树(Classification And Regression Tree,简称CART)算法来训练决策树。

首先,使用单个特征k和阈值(例如,花瓣长度≤2.45厘米)将训练集分成两个子集。k和阈值怎么选择?答案是产生出最纯子集(受其大小加权)的k和就是经算法搜索确定的(t,)。算法尝试最小化的成本函数为:

其中:是第i个节点上,类别为k的训练实例占比。

一旦成功将训练集一分为二,它将使用相同的逻辑,继续分裂子集,然后是子集的子集,依次循环递进。直到抵达最大深度(由max_depth控制),或是再也找不到能够降低不纯度的分裂,它才会停止。还有一些超参数可以用来控制附加的停止条件(min_samples_split、min_samples_leaf、min_weight_fraction_leaf及max_leaf_nodes)。

CART是一种贪婪算法:从顶层开始搜索最优分裂,然后每层重复这个过程。几层分裂之后,它并不会检视这个分裂

的不纯度是否为可能的最低值。贪婪算法通常会产生一个相当不错的解,但是不能保证是最优解。

而寻找最优树是一个已知的NP完全问题:需要的时间是O(exp(m)),所以即使是很小的训练集,也相当棘手。

2、计算复杂度

进行预测需要从根到叶遍历决策树。通常来说,决策树大致平衡,因此遍历决策树需要经历大约个节点。而每个节点只需要检查一个特征值,所以总体预测复杂度也只是,与特征数量无关。如此,即便是处理大型数据集,预测也很快。

但是,训练时在每一个节点,算法都需要在所有样本上比较所有特征(如果设置了max_features会少一些)。这导致训练的复杂度为。对于小型训练集(几千个实例以内),Scikit-Learn可以通过对数据预处理(设置presort=True)来加快训练,但是对于较大训练集而言,可能会减慢训练的速度。

3、基尼不纯度和信息熵

默认使用的是基尼不纯度来进行测量,但是,你可以将超参数criterion设置为"entropy"来选择信息熵作为不纯度的测量方式。熵是一种分子混乱程度的度量:如果分子保持静止和良序,则熵接近于零。在机器学习中,它也经常被用作一种不纯度的测量方式:如果数据集中仅包含一个类别的实例,其熵为零。下式显示了第i个节点的熵值的计算方式。

例如,上图中深度2左侧节点的熵值:

大多数情况下,二者并没有什么大的不同,产生的树都很相似。基尼不纯度的计算速度略微快一些,所以它是个不错的默认选择。它们的不同在于,基尼不纯度倾向于从树枝中分裂出最常见的类别,而信息熵则倾向于生产更平衡的树。

正则化超参数

决策树极少对训练数据做出假设(线性模型假设数据是线性)。如果不加以限制,树的结构将跟随训练集变化,严密拟合,并且很可能过度拟合。这种模型通常被称为非参数模型。相应的参数模型,比如线性模型,则有预先设定好的一部分参数,因此其自由度受限,从而降低了过度拟合的风险(但是增加了拟合不足的风险)。

为避免过度拟合,需要在训练过程中降低决策树的自由度。这个过程被称为正则化。正则化超参数的选择取决于你所使用的模型,但是通常来说,至少可以限制决策树的最大深度,由超参数max_depth控制(默认值为None,意味着无限制)。减小max_depth可使模型正则化,从而降低过度拟合的风险。

DecisionTreeClassifier类还有一些其他的参数,同样可以限制决策树的形状:min_samples_split(分裂前节点必须有的最小样本数),min_samples_leaf(叶节点必须有的最小样本数量),min_weight_fraction_leaf(跟min_samples_leaf一样,但表现为加权实例总数的占比),max_leaf_nodes(最大叶节点数量),以及max_features(分裂每个节点评估的最大特征数量)。增大超参数min_*或是减小max_*将使模型正则化。

还可以先不加约束地训练模型,然后再对不必要的节点进行剪枝(删除)。如果一个节点的子节点全部为叶节点,则该节点可被认为不必要。

下图显示了在卫星数据集(见第5章介绍)上训练的两个决策树。左图使用默认参数(即无约束)来训练决策树,右图的决策树应用min_samples_leaf=4进行训练。很明显,左图模型过度拟合,右图的泛化效果更佳。

决策树的限制

1、对训练集的旋转非常敏感

决策树很容易理解和解释,使用简单,功能全面并且十分强大。但是,它们确实也有一些限制。首先,你可能已经注意到,决策树的决策边界都与轴线垂直,这导致它们对训练集的旋转非常敏感。例如,下图显示了一个简单的线性可分离数据集:左图里,决策树可以很轻松分裂;而到了右边,数据集旋转45°后,决策边界产生了不必要的卷曲。虽然两个模型都看似完美拟合训练集,但是右侧模型很可能泛化不佳。解决这种问题的方法之一是使用PCA让训练数据定位在一个更好的方向上。

2、对野值点敏感

决策树的主要问题是它们对训练数据中的小变化非常敏感。我们以上面的决策树为例,如果你从鸢尾花数据集中移除花瓣最宽的Versicolor鸢尾花(花瓣长4.8厘米,宽1.8厘米),然后重新训练一个决策树,你可能得到下图所示的模型。这跟之前的决策树看起来截然不同。事实上,由于Scikit-Learn所使用的算法是随机的,即使是在相同的训练数据上,你也可能得到完全不同的模型(除非你对超参数random_state进行设置)。

#X有两列,下式查找一个样本点:属于y=1类;在该类中找到最大的Petal Width对应的样本点X[(X[:, 1]==X[:, 1][y==1].max()) & (y==1)] # widest Iris-Versicolor flowerout:array([[4.8, 1.8]])# 删除了一个野点,再进行训练not_widest_versicolor = (X[:, 1]!=1.8) | (y==2)X_tweaked = X[not_widest_versicolor]y_tweaked = y[not_widest_versicolor]tree_clf_tweaked = DecisionTreeClassifier(max_depth=2, random_state=40)tree_clf_tweaked.fit(X_tweaked, y_tweaked)

回归

决策树也可以执行回归任务。用DecisionTreeRegressor来构建一个回归树,在一个带噪声的二次数据集上进行训练

结果树如图所示

跟之前建立的分类树很相似。主要差别在于,每个节点上不再是预测一个类别而是预测一个值。这个预测值其实就是与这个叶节点关联的110个实例的平均目标值例如,如果你想要对一个x1 =0.6的新实例进行预测,那么从根节点开始遍历,最后到达预测value=0.1106的叶节点。在这110个实例上,预测产生的均方误差(MSE)等于0.0151。

下图左侧显示了该模型的预测,其中max_depth=2。如果设置max_depth=3,将得到如右图所示的预测。注意看,每个区域的预测值永远等于该区域内实例的目标平均值。算法分裂每个区域的方法,就是使最多的训练实例尽可能接近这个预测值。

与分类任务一样,决策树在处理回归任务时也很容易过度拟合。如果没有任何正则化(即使用默认超参数),你将得到如图左侧所示的预测结果,这显然对训练集严重过度拟合。只需要设置min_samples_leaf=10,就能得到一个看起来合理得多的模型,如右图所示。

回归算法成本函数

CART算法的工作原理跟前面介绍的大致相同,唯一不同在于,它分裂训练集的方式不是最小化不纯度,而是最小化MSE。下式显示了算法尝试最小化的成本函数

其中:

GitHub源码:/liuzheCSDN/Scikit-Learn/blob/master/6_DecisionTree.ipynb

如果觉得《机器学习实战6-sklearn训练决策树实现分类和回归》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。