- 模块 sklearn.tree
共有5类不包括集成算法
tree.DecisionTreeClassifier | 分类树 |
---|---|
tree.DecisionTreeRegression | 回归树 |
tree.export_graphviz | 将生成的决策树导出为DOT格式,画图专用 |
tree.ExtraTreeClassifier | 高随机版本分类树 |
tree.ExtraTreeRegression | 高随机版本回归树 |
使用步骤只有三步
- 实例化,建立评估模型对象(实例化需要使用到参数)
- 通过模型接口训练模型
- 通过模型接口提取需要的信息
简单的代码也只有三行
from sklearn import tree
clf = tree.DecisionTreeClassifier()
clf = clf.fit(X_train, Y_train)
result = clf.score(X_test, Y_test) # 这是评估指标(Accuracy)
参数:
class sklearn.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)
重要的参数:
-
criterion
决策树需要找出最佳节点和最佳的分枝方法,对分类树来说,衡量这个“最佳”的指标叫做“不纯度”。不纯度越低,决策树对训练集的拟合越好。现在使用的决策树算法在分枝方法上的核心大多是围绕在对某个不纯度相关指标的最优化上。
不纯度基于节点来计算,树中的每个节点都会有一个不纯度,并且子节点的不纯度一定是低于父节点的,也就是
说,在同一棵决策树上,叶子节点的不纯度一定是最低的。
Criterion这个参数正是用来决定不纯度的计算方法的。sklearn提供了两种选择:
1)输入”entropy“,使用信息熵(Entropy)
2)输入”gini“,使用基尼系数(Gini Impurity)
区别:
-
信息熵对不纯度更加敏感,对不纯度的惩罚最强,决策树的生长会更加“精细”。在实际使用中,信息熵和基尼系数的效果基本相同。
-
对于高维数据或者噪音很多的数据,信息熵很容易过拟合,基尼系数在这种情况下效果往往比较好。
-
信息熵的计算比基尼系数缓慢一些(涉及对数原因)。
-
参数 | criterion |
---|---|
如何影响模型 | 确定不纯度的计算方法,帮忙找出最佳节点和最佳分枝,不纯度越低,决策树对训练集拟合越好 |
可能的输入有哪些 | 的拟合越好不填默认基尼系数,填写gini使用基尼系数,填写entropy使用信息增益 |
怎么选取参数 | 通常就使用基尼系数 数据维度很大,噪音很大时使用基尼系数 维度低,数据比较清晰的时候,信息熵和基尼系数没区别 当决策树的拟合程度不够的时候,使用信息熵 两个都试试,不好就换另外一个 |
基本流程:
- 计算全部特征的不纯的指标
- 选取不纯度指标最优的特征来分支
- 在第一个特征的分支下,计算不纯度指标
- 重复第 2 步骤,直到结束…
-
random_state & splitter
- random_state=任意整数 分枝中的随机模式的参数,默认None,在高维度时随机性会表现更明显. 使其长出同一棵树,让模型稳定。
- splitter 也是用来控制决策树中的随机选项的,有两种输入值,输入”best",决策树在分枝时虽然随机,但是还是会优先选择更重要的特征进行分枝(重要性可以通过属性feature_importances_查看),输入“random",决策树在分枝时会更加随机,因为含有更多的不必要信息而更深更大,并因这些不必要信息而降低对训练集的拟合。这也是防止过拟合的一种方式。
-
剪枝参数,让决策树更有泛化性,减小过拟合
-
剪枝策略
max_depth
限制树的最大深度,超过设定深度的树枝全部剪掉
最广泛的剪枝参数,高维度低样本量时非常有效。决策树多生长一层,对样本量的需求会增加一倍,所以限制树深度能够有效地限制过拟合。在集成算法中也非常实用。实际使用时,建议从===3开始尝试==,看看拟合的效果再决定是否增加设定深度
min_samples_leaf & min_samples_split
min_samples_leaf限定,一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分枝就不会发生,或者,分枝会朝着满足每个子节点都包含min_samples_leaf个样本的方向去发生
一般搭配max_depth使用,在回归树中有神奇的效果,可以让模型变得更加平滑。这个参数的数量设置得太小会引起过拟合,设置得太大就会阻止模型学习数据。一般来说,建议从**=5开始使用**。
如果叶节点中含有的样本量变化很大,建议输入浮点数作为样本量的百分比来使用。同时,这个参数可以保证每个叶子的最小尺寸,可以在回归问题中避免低方差,过拟合的叶子节点出现。对于**类别不多的分类问题,=1通常就是最佳选择。**
min_samples_split限定,一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分枝,否则分枝就不会发生。
通常来讲是使用max_depth和min_中的二选一,不够在进行下面参数使用
max_features & min_impurity_decrease
一般max_depth使用,用作树的”精修“
max_features 限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃。
max_features是用来限制高维度数据的过拟合的剪枝参数,但其方法比较暴力,是直接限制可以使用的特征数量
而强行使决策树停下的参数,在不知道决策树中的各个特征的重要性的情况下,强行设定这个参数可能会导致模型学习不足。
min_impurity_decrease 限制信息增益的大小,信息增益小于设定数值的分枝不会发生。
-
-
如何确定最优剪枝参数:
使用超参数曲线
超参数的学习曲线,是一条以超参数的取值为横坐标,模型的度量指标为纵坐标的曲
线,用来衡量不同超参数取值下模型的表现的线。在建好的决策树里,模型度量指标就是score。
建立树
导入算法库和模块
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
探索数据
wine = load_wine() # 载入数据
wine # 发现是字典形式
wine.data # 特征
wine.target # 是三分类问题
import pandas as pd
pd.concat([pd.DataFrame(wine.data), pd.DataFrame(wine.target)], axis=1) # 连起来
Out[247]:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 0 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 14.23 | 1.71 | 2.43 | 15.6 | 127.0 | 2.80 | 3.06 | 0.28 | 2.29 | 5.64 | 1.04 | 3.92 | 1065.0 | 0 |
1 | 13.20 | 1.78 | 2.14 | 11.2 | 100.0 | 2.65 | 2.76 | 0.26 | 1.28 | 4.38 | 1.05 | 3.40 | 1050.0 | 0 |
2 | 13.16 | 2.36 | 2.67 | 18.6 | 101.0 | 2.80 | 3.24 | 0.30 | 2.81 | 5.68 | 1.03 | 3.17 | 1185.0 | 0 |
3 | 14.37 | 1.95 | 2.50 | 16.8 | 113.0 | 3.85 | 3.49 | 0.24 | 2.18 | 7.80 | 0.86 | 3.45 | 1480.0 | 0 |
4 | 13.24 | 2.59 | 2.87 | 21.0 | 118.0 | 2.80 | 2.69 | 0.39 | 1.82 | 4.32 | 1.04 | 2.93 | 735.0 | 0 |
… | … | … | … | … | … | … | … | … | … | … | … | … | … | … |
173 | 13.71 | 5.65 | 2.45 | 20.5 | 95.0 | 1.68 | 0.61 | 0.52 | 1.06 | 7.70 | 0.64 | 1.74 | 740.0 | 2 |
174 | 13.40 | 3.91 | 2.48 | 23.0 | 102.0 | 1.80 | 0.75 | 0.43 | 1.41 | 7.30 | 0.70 | 1.56 | 750.0 | 2 |
175 | 13.27 | 4.28 | 2.26 | 20.0 | 120.0 | 1.59 | 0.69 | 0.43 | 1.35 | 10.20 | 0.59 | 1.56 | 835.0 | 2 |
176 | 13.17 | 2.59 | 2.37 | 20.0 | 120.0 | 1.65 | 0.68 | 0.53 | 1.46 | 9.30 | 0.60 | 1.62 | 840.0 | 2 |
177 | 14.13 | 4.10 | 2.74 | 24.5 | 96.0 | 2.05 | 0.76 | 0.56 | 1.35 | 9.20 | 0.61 | 1.60 | 560.0 | 2 |
178 rows × 14 columns
wine.feature_names
['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
array(['class_0', 'class_1', 'class_2'], dtype='<U7')
Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data, wine.target, test_size=0.3) # 划分训练集和测试集
Xtrain.shape
wine.data.shape
开始建模
clf = tree.DecisionTreeClassifier(criterion="entropy",random_state=6,splitter="random")
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest)
score
feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类',
'花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸']
import graphviz
"""
这里利用来画图的,
第一个参数是训练好的模型,
第二个参数是对应要设置的特征名字,没有的话只会出现x[i]的情况,
第三个参数是颜色填充,
第四是边框的形状。
"""
dot_data = tree.export_graphviz(
clf,
feature_names=feature_name,
class_names=["第一种","第二种","第三种"],
filled=True,
rounded=True
)
graph = graphviz.Source(dot_data)
graph
OUTPUT:
clf.feature_importances_ # 查看特征重要性
array([0.06242934, 0. , 0. , 0. , 0.01514244,
0. , 0.05408415, 0. , 0. , 0.06432747,
0.3444244 , 0.20385196, 0.25574024])
[*zip(feature_name,clf.feature_importances_)] # 给予名字
[('酒精', 0.06242933526728492),
('苹果酸', 0.0),
('灰', 0.0),
('灰的碱性', 0.0),
('镁', 0.015142440931242472),
('总酚', 0.0),
('类黄酮', 0.05408415344978855),
('非黄烷类酚类', 0.0),
('花青素', 0.0),
('颜色强度', 0.06432747109750046),
('色调', 0.3444243986322976),
('od280/od315稀释葡萄酒', 0.20385195893470848),
('脯氨酸', 0.25574024168717757)]
clf = tree.DecisionTreeClassifier(criterion="entropy"
,random_state=300
,splitter="random"
,max_depth=5
# ,min_samples_leaf=10
,min_samples_split=10
)
clf = clf.fit(Xtrain, Ytrain)
dot_data = tree.export_graphviz(clf
,feature_names= feature_name
,class_names=["琴酒","雪莉","贝尔摩德"]
,filled=True
,rounded=True
)
graph = graphviz.Source(dot_data)
clf.score(Xtest, Ytest)
import matplotlib.pyplot as plt
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)
test.append(score)
plt.plot(range(1,11),test,color="red",label="max_depth")
plt.legend()
plt.show()
注:该学习笔记记录自网络视频,如有侵权,请联系删除。并且表示深深的歉意!