SS00006.algorithm——|Arithmetic&Machine.v06|——|Machine:监督学习算法.v05|

一、使用SK-LEARN实现决策树:参数CRITERION
### --- 使用SK-LEARN实现决策树

~~~     # 参数CRITERION
~~~     # criterion 这个参数是用来决定不纯度的计算方法。sklearn 提供了两种选择:
~~~     输入 “entropy”,使用信息熵(Entropy)
~~~     输入 “gini”,使用基尼系数(Gini Impurity)
~~~     比起基尼系数,信息熵对不纯度更加敏感,对不纯度的惩罚最强。
~~~     但是在实际使用中,信息熵和基尼系数的效果基本相同。

~~~     信息熵的计算比基尼系数缓慢一些,因为基尼系数的计算不涉及对数。
~~~     另外,因为信息熵对不纯度更加敏感,所以信息熵作为指标时,决策树的生长会更加 ”精细”,
~~~     因 此对于高纬数据或者噪声很多的数据,信息熵很容易过拟合,
~~~     基尼系数在这种情况下效果往往比较好。

~~~     当模型拟合程度不足时,即当模型在训练集和测试集上都表现不太好的时候,使用信息熵。
~~~     当然,这些不是绝对的。
参数criterion
如何影响模型?确定不纯度的计算方法,帮助找出最佳节点和最佳分支,
不纯度越低,决策树对训练集的拟合约好。
可能的输入有哪些?不填默认基尼系数,填写gini使用基尼系数,填写entropy使用信息增益
怎样选取参数?通常就使用基尼系数
数据维度很大,噪音很大时使用基尼系数
维度低,数据比较清晰的时候,信息熵和基尼系数没区别
当决策树的拟合程度不够的时候,使用信息熵
两个都试试,不好就换另外一个
二、初步建模
### --- 初步建模

# 导入需要的算法库和模块
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
plt.rcParams['font.sans-serif']=['Simhei']
plt.rcParams['axes.unicode_minus']=False
三、探索数据
### --- 探索数据

wine = load_wine()
wine.data.shape
wine.target
### --- 如果 wine 是一张表,应该长这样:

wine_pd=pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1).he
ad()
wine.feature_names.append("result")
wine_pd.columns=wine.feature_names
wine_pd
Xtrain, Xtest, Ytrain, ytest =
train_test_split(wine.data,wine.target,test_size=0.3,
random_state=420)
Xtrain.shape
Xtest.shape

~~~     # 输出参数
(124, 13)
(54, 13)
### --- 建立模型
clf = tree.DecisionTreeClassifier(criterion="gini")
clf = clf.fit(Xtrain, Ytrain)
clf.score(Xtest, ytest) #返回预测的准确度

~~~     # 输出参数
0.9444444444444444
四、画一棵树
### --- 画出一棵树

~~~     同时,我们可以利用 Graphviz 模块导出决策树模型,
~~~     第一次使用 Graphviz 之前需要对其进行安装, 
~~~     若是使用从 pip 进行的 Python 包管理,则可直接在命令⾏界⾯中利用下述指令进行安装:
pip install graphviz

import matplotlib.pyplot as plt
feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315 稀释葡萄酒','脯氨酸']
                
import graphviz
dot_data = tree.export_graphviz(clf,
out_file = None,
feature_names= feature_name,
class_names=["琴酒","雪莉","贝尔摩德"],
filled=True,
rounded=True)
graph = graphviz.Source(dot_data)
graph
### --- export_graphviz生成一个DOT格式的决策树:

~~~     feature_names:每个属性的名字
~~~     class_names:每个因变量类别的名字
~~~     label:是否显示不纯度信息的标签,默认为"all"表都显示,可以是"root"或"none"
~~~     filled:是否给每个结点的主分类绘制不同的颜色,默认为False
~~~     out_file:输出的dot文件的名字,默认为None表示不输出文件,可以是自定义名字如"tree.dot"
~~~     rounded:默认为Ture,表示对每个结点的边框加圆角,并使用Helvetica字体
### --- 更多参数说明查看

~~~     https://scikit-learn.org/stable/modules/generated/sklearn.tree.export_graphviz.html#sklearn.tree.export_graphviz
五、探索决策树属性
### --- 探索决策树属性

~~~     # clf.feature_importances_显示每个特征重要性
clf.feature_importances_
[*zip(feature_name,clf.feature_importances_)]
### --- clf.apply

~~~     # 返回每个预测样本的叶子索引
clf.apply(Xtrain)
### --- clf.tree_.node_count

~~~     # 树的节点个数。
clf.tree_.node_count
~~~     # 输出参数
13
### --- clf.tree_.feature

~~~     # 每个节点对应的属性索引值,-2 表示叶节点:
clf.tree_.feature
~~~     # 输出参数
array([ 9, 12, -2, -2, 6, 10, -2, -2, 12, 0, -2, -2, -2], dtype=int64)
六、防止过拟合
### --- 防止过拟合

~~~     在不加限制的情况下,一棵决策树会生长到衡量不纯度的指标最优,或者没有更多的特征可用为止。
~~~     这样的决策树往往会过拟合,这就是说,它会在训练集上表现很好,在测试集上却表现糟糕。
~~~     我们收集的样本数据不可能和整体的状况完全一致,
~~~     因此当一棵决策树对训练数据有了过于优秀的解释性,
~~~     它找出的规则必然包含了训练样本中的噪声,并使它对未知数据的拟合程度不足。
~~~     # 我们的树对训练集的拟合程度如何?
score_train = clf.score(Xtrain, Ytrain)
score_train

~~~     为了让决策树有更好的泛化性,我们要对决策树进行剪枝。剪枝策略对决策树的影响巨大,
~~~     正确的剪枝策略是优化决策树算法的核心。
random_state & splitter
### --- random_state

~~~     如果我们改动 random_state,画出来的每一棵树都不一样。它为什么会不稳定呢?
~~~     如果使用其他数据集,它还会不稳定吗?
    
~~~     我们之前提到过,无论决策树模型如何进化,
~~~     在分支上的本质都还是追求某个不纯度相关的指标的优化,而正如我们提到的,
~~~     不纯度是基于节点来计算的,也就是说,决策树在建树时,
~~~     是靠优化节点来追求一棵优化的树,但最优的节点能够保证最优的树吗?
~~~     集成算法被用来解决这个问题:sklearn 表示,既然一棵树不能保证最优,
~~~     那就建更多的不同的树,然后从中取最好的。怎样从一组数据集中建不同的树?
~~~     在每次分支时,不使用全部特征,而是随机选取一部分特征,
~~~     从中选取不纯度相关指标最优的作为分支用的节点。这样,每次生成的树也就不同了。

~~~     random_state 用来设置分支中的随机模式的参数,默认 None,在高维度时随机性会表现更明显,
~~~     低维度的数据(比如鸢尾花数据集),随机性几乎不会显现。输入任意整数,
~~~     会一直长出同一棵树,让模型稳定下来。
### --- splitter

~~~     # splitter 也是用来控制决策树中的随机选项的,有两种输入值:
~~~     # 输入”best",决策树在分支时虽然随机,
~~~     但是还是会优先选择更重要的特征进行分支(重要性可以通过属性 feature_importances_查看);
~~~     # 输入“random",决策树在分支时会更加随机,树会因为含有更多的不必要信息而更深更大,
~~~     并因这些不必要信息而降低对训练集的拟合。这也是防止过拟合的一种方式。
~~~     当你预测到你的模型会过拟合,用这两个参数来帮助你降低树建成之后过拟合的可能性。
~~~     当然,树一旦建成,我们依然是使用剪枝参数来防止过拟合。

clf = tree.DecisionTreeClassifier(criterion="entropy"
,random_state=30
,splitter="random"
)
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, ytest)
score
plt.rcParams['font.sans-serif']=['Simhei']
plt.rcParams['axes.unicode_minus']=False
### --- 剪枝参数:

~~~     # max_depth
~~~     max_depth 限制树的最大深度,超过设定深度的树枝全部剪掉,
~~~     一般用作树的”精修“这是用得最广泛的剪枝参数,在高维度低样本量时非常有效。
~~~     决策树多生长一层,对样本量的需求会增加一倍,所以限制树深度能够有效地限制过拟合。
~~~     在集成算法中也非常实用。实际使用时,建议从=3 开始尝试,看看拟合的效果再决定是否增加设定深度。

~~~     # min_samples_leaf
~~~     一个节点在分支后的每个子节点都必须包含至少 min_samples_leaf 个训练样本,
~~~     否则分支就不会发生, 或者,分支会朝着满足每个子节点都包min_samples_leaf 个样本的方向去发生。
~~~     一般搭配 max_depth 使用,在回归树中有神奇的效果,可以让模型变得更加平滑。
~~~     这个参数的数量设置得太小会引起过拟合,设置得太大就会阻止模型学习数据。
~~~     一般来说,建议从=5 开始使用。
~~~     如果叶节点中含有的样本量变化很大,建议输入浮点数作为样本量的百分比来使用。
~~~     同时,这个参数可以保证每个叶子的最小尺寸,避免低方差,过拟合的叶子节点出现。
~~~     # min_samples_split
~~~     一个节点必须要包含至少 min_samples_split 个训练样本,这个节点才允许被分支,
~~~     否则分支就不会发生。

~~~     # max_features
~~~     max_features 限制分支时考虑的特征个数,超过限制个数的特征都会被舍弃。 
~~~     和 max_depth 异曲同工, max_features 是用来限制高维度数据的过拟合的剪枝参数,
~~~     但其方法比较暴力,是直接限制可以使用的特征数量而强行使决策树停下的参数,
~~~     在不知道决策树中的各个特征的重要性的情况下,强行设定这个参数可能会导致模型学习不足。
~~~     如果希望通过降维的方式防止过拟合,建议使用 PCA,ICA 或者特征选择模块中的降维算法。
~~~     # min_impurity_decrease
~~~     min_impurity_decrease 限制信息增益的大小,信息增益小于设定数值的分支不会发生。
~~~     这是在 0.19 版本中更新的功能,在 0.19 版本之前时使用 min_impurity_split。

~~~     # 确认最优的剪枝参数
~~~     那具体怎么来确定每个参数填写什么值呢?这时候,我们就要使用确定超参数的曲线来进行判断了,
~~~     继续使用我们已经训练好的决策树模型 clf。
~~~     超参数的学习曲线,是一条以超参数的取值为横坐标,模型的度量指标为纵坐标的曲线,
~~~     它是用来衡量不同超参数取值下模型的表现的线。
~~~     在我们建好的决策树里,我们的模型度量指标就是 score。
test = []
for i in range(10):
clf = tree.DecisionTreeClassifier(max_depth=i+1
,criterion="entropy"
,random_state=30
,splitter="random")
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest) # 记录下不同 max_depth 下模型在测试集分数
test.append(score)
plt.plot(range(1,11),test,color="red",label="学习曲线")
plt.ylabel("socre")
plt.xlabel("max_depth")
plt.legend()
plt.show();
### --- 思考:

~~~     - 剪枝参数一定能够提升模型在测试集上的表现吗? - 调参没有绝对的答案,一切都是看数据本身。
~~~     - 这么多参数,一个个画学习曲线? - 在泰坦尼克号的案例中,我们会解答这个问题。

~~~     无论如何,剪枝参数的默认值会让树无尽地生长,这些树在某些数据集上可能非常巨大,
~~~     对内存的消耗也非常巨大。

~~~     所以如果你手中的数据集非常巨大,你已经预测到无论如何你都是要剪枝的,
~~~     那提前设定这些参数来控制树的复杂性和大小会比较好。
七、总结
### --- 总结

~~~     属性是在模型训练之后,能够调用查看的模型的各种性质 。
~~~     对决策树来说,最重要的是feature_importances_,能够查看各个特征对模型的重要性。

~~~     sklearn 中许多算法的接口都是相似的,比如说我们之前已经用到的 fit 和 score,
~~~     几乎对每个算法都可以使用。除了这两个接口之外,决策树最常用的接口还有 apply 和 predict。
~~~     apply 中输入测试集返回每个测试样本所在的叶子节点的索引。
~~~     predict 输入测试集返回每个测试样本的标签。返回的内容一目了然并且非常容易,
~~~     大家感兴趣可以自己下去试试看。

~~~     在这里不得不提的是,所有接口中要求输入 Xtrain 和 Xtest 的部分,
~~~     输入的特征矩阵必须至少是一个二维矩阵。 sklearn 不接受任何一维矩阵作为特征矩阵被输入。
~~~     如果你的数据的确只有一个特征,那必须用 reshape(-1,1)来给矩阵增维。
~~~     # 我们已经学完了分类树 DecisionTreeClassifier 和用决策树绘图(export_graphviz)的所有基础。
~~~     # 我们讲解了决策树的基本流程,分类树的八个参数,一个属性,四个接口,以及绘图所用的代码:
~~~     八个参数:Criterion;
~~~     两个随机性相关的参数(random_state,splitter);
~~~     五个剪枝参数 (max_depth, min_samples_split , min_samples_leaf , max_feature ,min_impurity_decrease) ;
~~~     一个属性:feature_importances_ ;
~~~     四个接口:fit,score,apply,predict .
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yanqi_vip

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值