详解决策树-分类树菜菜的sklearn课堂笔记

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了详解决策树-分类树菜菜的sklearn课堂笔记相关的知识,希望对你有一定的参考价值。

文章换行有问题,望谅解

关键概念:节点

  • 根节点:没有进边,有出边。包含最初的,针对特征的提问。
  • 中间节点:既有进边也有出边,进边只有一条,出边可以有很多条。都是针对特征的提问。
  • 叶子节点:有进边,没有出边,每个叶子节点都是一个类别标签。
  • 子节点和父节点:在两个相连的节点中,更接近根节点的是父节点,另一个是子节点。

DecisionTreeClassifier与红酒数据集

tree.DecisionTreeClassifier(
    ["criterion=gini", "splitter=best", max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, class_weight=None, presort=False],
)

建立一棵树

导入需要的算法库和模块

from sklearn import tree
from sklearn.datasets import load_wine # 里面有很多著名的数据集
from sklearn.model_selection import train_test_split

了解数据

wine = load_wine() # 内置的红酒数据集
print(type(wine)) # 类似于字典
---
<class sklearn.utils.Bunch>

wine.keys()
---
dict_keys([data, target, target_names, DESCR, feature_names])

print(wine.DESCR) # 数据集简介
# 太多了,这里不写了

wine.feature_names # 特征名,也就是X每个维度代表什么,一会有翻译
---
[alcohol, malic_acid, ash, alcalinity_of_ash, magnesium, total_phenols, flavanoids, nonflavanoid_phenols, proanthocyanins, color_intensity, hue, od280/od315_of_diluted_wines, proline]

wine.target_names # 目标名,也就是每一类Y的名字。这里有3类Y,y_i in (class_0, class_1, class_2)
---
array([class_0, class_1, class_2], dtype=<U7)

wine.data.shape # 这里说明了数据集X一共有178个数据,13个特征
---
(178, 13)

wine.target # 即整个Y集
---
# 就是178个0,1,2这里不写了

import pandas as pd
pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1) # 将X和Y连成一个DataFrame
---

分割训练集和数据集

Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data,wine.target,test_size=0.3)
# test_size=0.3意味着训练集占70%,测试集占30%
# 注意,这里是随机的

print(type(Xtrain))
---
<class numpy.ndarray>

Xtrain.shape,Xtest.shape,Ytrain.shape,Ytest.shape
---
((124, 13), (54, 13),(124,), (54,))

建立模型

clf = tree.DecisionTreeClassifier(criterion="entropy")
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest) #返回预测准确度accuracy

score # 每次可能不一样,在后面会解释为什么不一样
---
0.8888888888888888

画出一棵树

import graphviz # 画树所需的包
feature_name=[酒精,苹果酸,灰,灰的碱性,镁,总酚,类黄酮,非黄烷类酚类,花青素,颜色强度,色调,od280/od315稀释葡萄酒,脯氨酸] # 和上面的英文特征相对应
dot_data = tree.export_graphviz(clf
								,feature_names=feature_name
                                ,class_names=[琴酒,雪莉,贝尔摩德]
                                ,filled=True
                                ,rounded=True
)
graph = graphviz.Source(dot_data)
# feature_names:X特征名,即X不同维度的名称
# class_names:Y类名,即不同类别Y的名称
# filled:是否填充颜色,颜色深浅表示纯度,不同颜色表示不同类别
# rounded:使用圆框/方框显示
graph
# entropy:纯度
# samples:样本个数
# value:样本比例

很遗憾图片并不能显示中文

继续探索决策树

clf.feature_importances_ # 特征重要性
---
array([0.02512577, 0.        , 0.        , 0.        , 0.035285  , 0.        , 0.        , 0.        , 0.        , 0.09686628, 0.13368571, 0.24884153, 0.46019571])

list(zip(feature_name,clf.feature_importances_))
---
[(酒精, 0.02512577188063646),
 (苹果酸, 0.0),
 (灰, 0.0),
 (灰的碱性, 0.0),
 (镁, 0.0),
 (总酚, 0.0),
 (类黄酮, 0.0),
 (非黄烷类酚类, 0.0),
 (花青素, 0.03528500112337327),
 (颜色强度, 0.09686627661594578),
 (色调, 0.13368570769252183),
 (od280/od315稀释葡萄酒, 0.24884153360350494),
 (脯氨酸, 0.46019570908401763)]

重要参数

criterion分枝指标

为了通过表格生成一棵决策树,我们需要找到最佳的节点和最佳的分枝方法,对分类树来说,衡量这个最佳的指标可以使用基尼系数,输入"gini",这也是criterion默认的值;使用信息熵,输入"entropy" 二者的数学表示 $$ \\beginaligned Entropy(t)&=-\\sum\\limits_i=0^c-1p(i|t)\\log_2p(i|t)\\ Gini(t)&=1-\\sum\\limits_i=0^c-1p(i|t)^2 \\endaligned $$ $t$代表给定的节点,$i$代表标签的任一分类

基尼系数缺点:对不纯度相对不敏感。 信息熵缺点:涉及对数计算,速度相对慢一点;对不纯度更敏感,尤其对于高维数据或者噪声很多的数据,容易过拟合

通常使用基尼系数 数据维度很大,噪声很大的时候使用基尼系数 维度低,数据比较清晰的时候,信息熵和基尼系数没区别 当决策树拟合程度不够好的时候,使用信息熵

random_state随机生成参数

clf = tree.DecisionTreeClassifier(criterion="entropy"
                                  ,random_state=0
                                 )
# random_state:用来设置分枝中的随机模式的参数,输入任意非负正整数,会一直长处一棵树,让模型稳定下来。默认None,在高维度时随机性会表现更明显,低维度的数据随机性几乎不会显现。
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest)

score # 依旧有可能不一样
---
0.9074074074074074

即使我们固定了random_state=0或者其他数字,由于训练集和数据集的划分是随机的。当我们重启jupyter的时候,数据集将不同。因此,即使固定random_state,树仍有可能是不同的

splitter随机生成参数

clf = tree.DecisionTreeClassifier(criterion="entropy"
                                  ,random_state=0
                                  ,splitter=random
                                 )
# splitter:控制决策树分枝的方式
# 默认"best",即选择更重要的特征进行分枝(上面有提到"在每次分枝时,不从使用全部特征,而是随机选取一部分特征",因此这里只是对这一部分随机选取的特征选择feature_importances_最大的进行分枝)
# 输入"random",在分支的时候会更加随机,注意这里的随机可以认为是最佳随机,即给与一定的随机性,但仍然受到feature_importances_影响,不是随机选一个。
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest)

score
---
0.9259259259259259

当我们预测到模型有可能过拟合,可以考虑调节splitter来降低过拟合的可能性。 实际上,当书建成以后,我们也可以通过剪枝来防止过拟合

max_depth剪枝参数

限制树的最大深度,超过设定深度的树枝会被全部剪掉 对于一棵决策树,每多生长一层,对样本的需求量就会增加一倍,所以限制树的深度能够有效的限制过拟合 默认五None。如果为None,决策树会持续生长直到虽有叶节点不纯度为0,或者直到每个叶节点所含的样本量都小于参数min_samples_split中输入的数字

实际使用时,建议从=3开始尝试,看看拟合的效果决定是否增加设定深度

min_sample_leaf & min_samples_split剪枝参数

min_samples_leaf限定,一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分枝就不会发生,或者,分枝会朝着满足每个子节点都包含min_samples_leaf个样本的方向去发生 如果输入整数,则认为输入的数字是叶节点存在所需的最小样本量;如果输入浮点数,则认为输入的浮点数是比例,即叶节点存在所需的最小样本量为输入模型的样本量$\\times$浮点数

min_samples_split就是对于中间结点而言的,同min_sample_leaf

这个参数设置的太小会引起过拟合,设置的太大会阻止模型学习数据,一般来说,建议从=5开始使用

max_features剪枝参数

分枝时考虑的最大特征个数,超过限制个数的特征会被舍弃 不建议使用该参数,因为其舍弃特征并不考虑特征的重要性。如果数据维度过多可以考虑PCA等方式降维来防止过拟合 默认None

min_impurity_decrease剪枝参数

限制不纯度降低的最小大小,不纯度下降小于设定数值,分枝不会发生

带权重的不纯度下降可以表示为 $$ \\fracN_tN\\times 所在中间结点不纯度- \\fracN_tRN\\times 右侧子树不纯度- \\fracN_tlN\\times 左侧子树不纯度 $$

默认=0,接收浮点数

class_weight & min_weight_fraction_leaf目标权重参数

常用于样本不平衡的数据集中。 样本不平衡是指在一组数据集中,标签的一类天生占有很大的比例。比如说,在银行要判断“一个办了信用卡的人是否会违约”,就是是vs否(1%:99%)的比例。这种分类状况下,即便模型什么也不做,全把结果预测成“否”,正确率也能有99%。

确认最优剪枝参数

一般我们可以结合matplotlib来绘制超参数学习曲线来进行判断 超参数学习曲线,是一条以超参数的取值为横坐标,模型的度量指标为纵坐标的曲线,它是用来衡量不同超参数取值下模型的表现的线 在我们建好的决策树里,我们的模型度量指标就是score

import matplotlib.pyplot as plt

test = []
for i in range(10):
    clf = tree.DecisionTreeClassifier(max_depth=i+1
                                     ,criterion="entropy"
                                     ,random_state=0
                                     ,splitter="best"
                                     )
    clf = clf.fit(Xtrain,Ytrain)
    score = clf.score(Xtest,Ytest)
    test.append(score)

plt.plot(range(1,11),test,color="red",label="max_depth")
plt.legend()
plt.show()

重要接口和属性

之前提到过

  • feature_importances_,查看各个特征推模型的重要性
  • fit用于生成决策树
  • score用于评估决策树准确性
clf.apply(Xtest)# 返回每个测试样本所在叶结点的索引
---
array([10,  7,  7, 10,  4, 10, 10,  7,  4, 10,  5,  5, 10,  7,  7,  4, 10, 5,  7,  5,  7,  7,  9,  5,  7,  9, 10, 10,  4, 10, 10,  4,  4,  7, 7,  4, 10,  4,  5,  4, 10,  7, 10,  7, 10, 10,  7,  7,  4, 10,  5, 10,  7,  5], dtype=int64)

clf.predict(Xtest)# 返回每个测试样本的分类/回归结果
---
array([0, 1, 1, 0, 2, 0, 0, 1, 2, 0, 1, 1, 0, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 2, 0, 0, 2, 2, 1, 1, 2, 0, 2, 1, 2, 0, 1, 0, 1, 0, 0, 1, 1, 2, 0, 1, 0, 1, 1])

以上是关于详解决策树-分类树菜菜的sklearn课堂笔记的主要内容,如果未能解决你的问题,请参考以下文章

详解决策树-交叉验证菜菜的sklearn课堂笔记

详解支持向量机-支持向量机分类器原理菜菜的sklearn课堂笔记

菜菜的sklearn课堂笔记支持向量机-线性SVM用于分类的原理

详解数据预处理和特征工程-特征选择-Embedded嵌入法菜菜的sklearn课堂笔记

sklearn1.分类决策树

详解随机森林-概述菜菜的sklearn课堂笔记