sklearn之决策树参数详解

机器学习之决策树(sklearn库函数详解)

  • 1 sklearn.tree
  • 2 四种树模型的介绍
    • 一 tree.DecisionTreeClassifier
      • ⅰ 分支节点选择的参数
        • ① criterion
        • ② splitter
      • ⅱ 树生成的参数
        • ① max_depth
        • ② min_samples_split
        • ③ min_samples_leaf
        • ④ min_weight_fraction_leaf
        • ⑤ max_features
        • ⑥ random_state
        • ⑦ max_leaf_nodes
        • ⑧ min_impurity_decrease
        • ⑨ class_weight
      • ⅲ 树的剪枝
        • ① ccp_alphanon-negative
      • ⅳ 模型的属性与方法
        • ① 模型属性
        • ② 模型方法
    • 二 与其他三种模型不同
      • ⅰ DecisionTreeRegressor 的选择标准
      • ⅱ 额外树默认参数的改变
  • 3 完结撒花

如果你觉得这篇文章对你有帮助,记得点赞收藏哦。在这片文章中我将详细介绍sklearn.tree模型怎么使用,我查阅了很多资料,源码,国内外论坛,甚至查看了论文,解答了一些函数调用的疑惑,文章接着往下看,保证是干货。
(ps:这篇文章适合对决策树理论已经有详细了解的人阅读)可以查看我先前的文章理解理论知识:
机器学习之决策树(原理篇)

1 sklearn.tree

如果你有查看sklearn的官方文档,你就知道一共有4个简单的决策树模型,并且都被封装在了sklearn.tree中。它们分别是:

tree.DecisionTreeClassifier 分类树
tree.DecisionTreeRegressor 回归树
tree.ExtraTreeClassifier 额外的分类树(极其随机的分类树)
tree.ExtraTreeRegressor 额外的回归树(极其随机的回归树)
sklearn之决策树参数详解_第1张图片

4种算法都可以选择性的使用信息熵或基尼系数作为分类标准,但信息熵并不影响它们是基于CART算法设计并改进的的。

2 四种树模型的介绍

我这里其实只需要全面介绍一种最经典的tree.DecisionTreeClassifier,其它三个就在它的改进上介绍进行,而且4者源代码几乎所有部分都是相同的。我将会以决策树构建的三要素,节点的选择,决策树的生成以及剪枝展开介绍。

一 tree.DecisionTreeClassifier

ⅰ 分支节点选择的参数

其实节点的选择有两个重要的参数,分别是

1 criterion:{“gini”, “entropy”}, default=”gini”
2 splitter:{“best”, “random”}, default=”best”

① criterion

很容易理解,这个参数代表你想选择的是信息熵或者基尼指数,决策树默认的是基尼指数。
你可能会问这两个参数选哪一个比较好,我可以告诉你绝大多数情况下默认gini系数就对了,没必要去动。原因是首先很多情况下它们两的实际效果差异几乎没啥区别。

但有些点要注意,一是信息熵对错误的分类相比基尼系数更加严格,更容易差生过拟合。二是信息熵由于公式中带对数计算,而基尼系数是平方,导致前者生成的树计算时间更长,在特征很多的时候表较明显。一般你要处理特征特别多的数据,也是基尼指数更好的,更快。默认就行,改变这个参数几乎不会对模型效果有啥影响。如果你想建造两棵不一样的决策树,倒是可以两个都试一下。

② splitter

这个参数有必要好好讲讲。因为目前网上,不说绝对,有90%的说法是错误的,我也是查阅了很多资料才搞明白。
这个参数默认是 splitter = ‘‘best’‘,它还有一个选项是random

如果你选择默认的best。那么对于离散特征 A A A,假设有三个分类 A 1 A_1 A1 A 2 A_2 A2 A 3 A_3 A3与连续特征 B B B来判断那个特征该是分支节点,并且分裂点具体是哪个。(看到这里,你必须清楚CART算法的原理才能继续下去)。我们知道CART算法是严格生成二叉树的,CART是如何判断特征 A A A还是 B B B作为分支节点的呢,CART算法会先对连续特征 B B B,与 A A A进行信息增益比或基尼系数的计算,得到两者的数值。

如果我们发现离散特征 A A A的基尼系数更小或者信息增益比更大,说明特征 A A A更适合,此时决策树会将三个类别细分为{ A 1 A_1 A1},{ A 2 A_2 A2, A 3 A_3 A3},或{ A 2 A_2 A2},{ A 1 A_1 A1, A 3 A_3 A3},{ A 3 A_3 A3},{ A 2 A_2 A2, A 1 A_1 A1},然后分别计算三者之间的基尼系数,最后选择基尼系数最小的一个组合作为二叉树生成的依据。

如果我们发现连续特征 B B B的基尼系数更小或者信息增益比更大,说明特征 B B B更适合,此时决策树就把当初特征 B B B中连续值之间的最优分割点(对于 B B B来说得到的基尼系数最小)作为生成二叉树的依据。

—————————————————————————————————————————

如果你选择的是random,同样对于离散特征 A A A,连续特征 B B B,决策树在计算信息增益前会先对两个特征内部做分割点的随机操作,然后再计算基尼指数。并不是很多博客中模棱两可的说,只是随机选取一部分特征,具体过程也不告诉你。实际上对于randombest,所有特征都会被计算(它们真的没搞明白就乱写,批评看完源码,不要误导别人)

对于 A A A,比如这三个组合{ A 1 A_1 A1},{ A 2 A_2 A2, A 3 A_3 A3},或{ A 2 A_2 A2},{ A 1 A_1 A1, A 3 A_3 A3},{ A 3 A_3 A3},{ A 2 A_2 A2, A 1 A_1 A1}。他只会随机的选择三者中的一个,然后计算这个组合的基尼系数代表特征 A A A的基尼系数。

对于 B B B,因为他是连续特征嘛,假设数据中有m个值,序列为{ b 1 , b 2 , b 3 , . . . . b m {b_1,b_2,b_3,....b_m} b1,b2,b3,....bm},此时他会把其中最小值,最大值拿出来。然后只会在最小值最大值之间随机的选择一个值所作特征 B B B的分割值,然后用这个来计算特征 B B B的基尼指数并代表 B B B。最后用这两个代表的基尼系数来进行比较谁做为分割点

—————————————————————————————————————————

说完了这个过程你应该理解splitter参数的作用,确实是体现了随机性,并且这个随机性你会觉得有点无厘头,如果都是连续特征,这怎么能生成合理的决策树呢。实际上是可以的,只不过生成的树很离谱,虽然它分类正确,你可以自己写代码试试。并且如果你的随机种子不一样,它每次都会生成完全不一样的树。这算是一种瞎猫碰上死耗子的算法,但它也是有一定的合理性,尽管他是随机的分,但越重要的特征,得到的基尼系数更小的可能性是越大的。

(如果说best是点到点的直线,那么random就是点到点的n多条离谱的曲线,但它依然能到达目的地)

这个random参数被设计的初衷其实也是为了随机生成许多不一样但有效的树,保证树的多样性。别的博客说它可以用来解决过拟合,其实在我看来并不适合,因为在原理上体现是用极大的随机性来重新生成可能正确的树,是误打误撞。这个splitter实际分类任务设置时默认best就行,毕竟random生成的树实在是过于离谱。如果你想对一个数据集有很多种不同的树模型,又不太关注合理性,可以选择random

如果你想有更多了解,在这篇06年的论文中有介绍。
[1]. P. Geurts, D. Ernst., and L. Wehenkel, “Extremely randomized trees”, Machine Learning, 63(1), 3-42, 2006.

ⅱ 树生成的参数

现在来介绍控制树生长的参数,一共有9个,虽然看起来很多,但实际每个都很容易理解,只需简单介绍就行。分别为:

1 max_depth: int, default=None
2 min_samples_split: int or float, default=2
3 min_samples_leaf: int or float, default=1
4 min_weight_fraction_leaf: float, default=0.0
5 max_features: int, float or {auto, “sqrt”, “log2”}, default=None
6 random_state: int, RandomState instance or None, default=None
7 max_leaf_nodes: int, default=None
8 min_impurity_decrease: float, default=0.0
9 class_weight: dict, list of dict or “balanced”, default=None

① max_depth

就是树的最大深度,默认为None,就是不限制树的最大深度。这个参数第一次生成树的时候不使用,如果你已经构建了一颗树,并大致知道树的深度。在生成一颗新的树的时候就可以设置max_depth的值来减轻过拟合。

② min_samples_split

同样很容易理解,就是一个节点能够分割的最小样本数,默认为2,也是来防止过拟合的。一般数据非常多的情况下可以设置5-10或者自己觉得合适的,来停止树的生长,起到减轻过拟合的效果。可以设置浮点数,此时算是比例表示ceil(min_samples_split * n_samples)ceil()就是四舍五入的意思。

③ min_samples_leaf

默认为1,这个表明一个分支节点生成的两个叶子节点中的样本数量必须大于min_samples_leaf=1。当数据非常多的时候可以设置为5或者你喜欢的,来停止树的生长,起到减轻过拟合的效果。当你设置为浮点数的时候表明比例表示,与上面的相同,很容易理解。

④ min_weight_fraction_leaf

默认值为0,这个参数也是很多博客没有解释清楚的,甚至是错误的,包括sklearn官方文档也没做解释的很清楚,有点搞。在查阅githubsklearn开发者解释后我才明白什么意思。其实这个是配合min_samples_leaf使用的,公式为:

min_samples_leaf = max(min_samples_leaf, int(ceil(self.min_weight_fraction_leaf * n_samples)))

看到这个公式你就很容易明白我们只能在 min_samples_leafmin_weight_fraction_leaf 两个之中得到样本占比最大的那一个,实际情况我们只需要使用min_samples_leaf,因为两者的本质含义其实是一样的,而且保不准后者会出现什么特殊情况。

⑤ max_features

这个也相当容易理解,默认是n_features。作用是限制每次分支节点选择计算所使用的最大特征数。但要注意如果在其中没找到满足条件的特征,他就会跳出这个max_features这个范围,遍历剩下的特征n_features - max_features。如果剩下的也不满足的,该节点就不分裂,停止生长。要说明一下,在每个节点的max_features中的特征都是在所有特征中随机选取的,受我们常说的随机种子影响,也就是参数random_state.
这个参数也可以起到防止过拟合的效果,根据模型特征数自定。下面给出一张图你就能理解怎么使用。
sklearn之决策树参数详解_第2张图片

其中的无与没有就是None,浮动是浮点数float,自动是auto

⑥ random_state

这个参数,很有意思。如果你了解随机数生成的原理以及随机种子random_seed,我告诉你实际上random_seed就是random_state,只是名字不同,你基本上就理解了。这个参数是用来控制所有随机过程的,包括参数splitter以及max_features。默认设置为None,意思是每次都是随机的,如果你设置为int 1或者5,代表固定的。很多第一次用决策树算法的小白,会发现自己同一个数据集得到的决策树不同,会很疑惑,而且他们只使用了两行代码

clf=sklearn.tree.DecisionTreeClassifier()
clf.fit(X,Y)

尽管默认的splitter=''best''max_features=n_features。其实是因为在某些节点计算所有的特征的基尼指数,偶尔会出现最小基尼指数相同的特征,那么此时算法就根据random_state随机种子来随机决定其中一个作为分裂节点,特征越多,线性相关性越大,这种情况出现的概率也就越大,最后生成的树就不一样了。这也是为什么我们如果希望别人复现我们的代码,我们需要特定设置一个random_state=常数,来使得我们的随机过程是固定的,这样他们生成的模型会跟我们的相同。

⑦ max_leaf_nodes

这个意思是生成的整棵树的叶子节点的数量,默认为None,也就是无。它也可以用来减轻过拟合,一般是你知道整棵树的叶节点大概有多少后,然后自定一个认为合适的。

⑧ min_impurity_decrease

先看英文直译,最小不纯度的减少,只要每次不纯度的减少大于或等于你设定的值,就允许分裂,默认设置为0.0。我们在计算决策树的时候,每个节点我们都可以计算不纯度,而这个不纯度其实是标签的信息熵或者基尼系数 (是标签!),一般标签的混乱程度越小,就是不纯度越小,表明标签多为同一种类别,实际反应的就是信息熵与基尼系数小。下面给出一张图,你应该能理解
sklearn之决策树参数详解_第3张图片

这张图第一个不纯度,也就是基尼指数是0.653,后面的两个节点的不纯度分别为0.6110,也就是它的子节点不纯度之和为0.611,减少的不纯度为0.655-0.611=0.044。如果我们设置min_impurity_decrease=0.045,由于减小的不纯度0.044小于需求的0.045,节点不会分裂,最后上面的这棵树就只有根节点了。这个参数适当的设置也可能减小过拟合

⑨ class_weight

直译:类权重,就是类别之间的权重。比如一个二分类问题,类别一占10%,类别二站90%,我们训练一个模型,这个模型不管什么情况只输出类别二,正确率也有90%,其实这是相当不合理的。这时我们需要一个权重来平衡样本,比如对样本少类别的的基尼系数在原本的基础上乘以0.9,而样本多的乘以0.1。虽然这种加权重的方法很不错,但样本极其不平衡的时候,也无济于事,因为决策树再怎么也学不到少样本类别的规律,数据不够太硬伤。一般都是在类别参差不齐的时候使用效果比较好。默认参数是None,建议每次构建决策树的时候都改成balanced(自动平衡),比较实用,略微防止过拟合。balanced的公式给一下:
n s a m p l e s n c l a s s e s ∗ n p . b i c o u n t ( y ) \cfrac{n_{samples}}{n_{classes}*np.bicount(y)} nclassesnp.bicount(y)nsamples

np.bicount(y) 是统计所有标签中每个类别的样本出现的次数
可以从这个公式中看出,样本数量越小的标签得到的权重越大

我们也可以自己设置权重例如三分类问题[1.1,1.2,0.8],但一般都是用balanced,效果也不错。另外对于多输出问题,这里的输出是指我们一个样本经过决策树可以得到多个输出,我们目前遇到的几乎都是一输出。多输出问题一般不适合用决策树,出现的情况也很小,有个了解就行,比如决策树人脸预测,给一张人脸的上半部分像素点,预测下半部分,由于下半部分有很多像素点,所以是多输出,其实效果很差,给张sklearn的图给你们看看就行。

sklearn之决策树参数详解_第4张图片

ⅲ 树的剪枝

① ccp_alphanon-negative

ccp_alphanon-negative float, default=0.0

ccp(Cost-Complexity Pruning)的意思就是代价复杂度剪枝。如果你知道CART算法剪枝原理,就明白具体剪枝过程与alpha怎么设置。但有一点需要说明sklearn中的alpha需要我们自己设置,而传统的CCP算法是不需要,它能计算每个节点的alpha,然后选出最小的进行剪枝迭代。

在sklearn官方文档中说明的是默认为0.0表示不剪枝,并且它没有写自动迭代的算法,只写了用 α \alpha α(也许以后会完善)。所以我们只能手动调节alpha,一般调参技巧是从0开始,一点一点增大,0.0010.1,具体根据经验选个合适的。(而且他们的 α \alpha α只能使用一次,生成一棵最优子树)
如果你有通天能耐,是个超级大牛,可以去github上完善这一部分的代码,不过光是决策树这部分,就已经有几万行代码了。。。。

我放一下sklearn官方如何使用 α \alpha α的代码。他们是手动使用 α \alpha α用for循环来检验的。(交叉验证的操作也要自己写代码实现!)

clfs = []
for ccp_alpha in ccp_alphas:
    clf = DecisionTreeClassifier(random_state=0, ccp_alpha=ccp_alpha)
    clf.fit(X_train, y_train)
    clfs.append(clf)
print(
    "Number of nodes in the last tree is: {} with ccp_alpha: {}".format(
        clfs[-1].tree_.node_count, ccp_alphas[-1]
    )
)

ⅳ 模型的属性与方法

① 模型属性

当模型训练完成后,我们想查看模型的属性。这里只简单的做个表格总结一下,一共有9个,具体详细方细节可以去sklearn官方网站上查看。毕竟这个真的是只要会用就能理解。

序号 属性 输出 介绍
1 classes_ ndarray of shape (n_classes,) or list of ndarray 得到所有不同标签的列表
2 feature_importances_ ndarray of shape (n_features,) 得到特征重要性的矩阵
3 max_features_ int 最大特征的推断值,其实就是模型构建时的那个max_features_
4 n_classes_ int or list of int 数据集有多少个类别,单输出问题整数,多输出问题列表
5 n_features_ int 整个数据有多少特征,在未来的1.2版本中会移除
6 n_features_in_ int 也是整个数据有多少个特征
7 feature_names_in_ ndarray of shape (n_features_in_,) 特征的名字,如果你的特征有字符型的昵称,就展现出来,其他的都不展示
8 n_outputs_ int 单输出问题固定输出1,多输出看有多少个
9 tree_ Tree instance 树对象,单独也有一些树的属性,如tree_.impurity[i]表明节点i的不纯度,建议前往官方文档获取更其他属性

② 模型方法

这个也是会用就能理解,能记住,了解细节去sklearn官网查看,这里放张图就行。
sklearn之决策树参数详解_第5张图片

二 与其他三种模型不同

ⅰ DecisionTreeRegressor 的选择标准

这个就介绍跟tree.DecisionTreeClassifier不同的点吧,搞懂了分类树,这个回归树就很容易理解。

criterion{“squared_error”, “friedman_mse”, “absolute_error”, “poisson”}, default=”squared_error”

对于回归树就只有这一点不一样,就是特征选择标准,默认的也是“squared_error”,其他的参数,方法,属性都一样。前提是你知道CART回归树的具体生成过程,看一下也就明白了。

ⅱ 额外树默认参数的改变

tree.ExtraTreeClassifiertree.ExtraTreeRegressor仅仅只是在分类树与回归树的基础上改变了splittermax_features的默认值。前者默认改成了random,后者默认改为了sqrt(n_features)。原本这两个参数的默认值分别是bestNone。其他都一样,源码也是相同的。

看到这里其实也就明白了额外树,改变默认参数,能够生成极其随机的树,这就是它的功能。如果你理解我上面写的splittermax_features参数功能,这里看一眼就能理解了。

3 完结撒花

理解上面的所有内容,你就能自如的调用sklearn决策树包做实验了。而不是像某些小白,只会掉包,却不理解原理与参数背后的意义。其实有些东西比如特征重要性怎么算法,这个在其他树模型例如随机森林,xgboost,还有回归模型中计算方法也是不一样,以后再慢慢讲解。还有包括树模型画图使用到的graphviz库,暂时也不介绍,可以自行上网查阅,方法也是十分简单的。

另外附上sklearn.tree 树模型的官方网站[2]https://scikit-learn.org/stable/modules/tree.html.

[1] P. Geurts, D. Ernst., and L. Wehenkel, “Extremely randomized trees”, Machine Learning, 63(1), 3-42, 2006.
[2] https://scikit-learn.org/stable/modules/tree.html

你可能感兴趣的:(决策树,sklearn,机器学习,python)