scikit-learn, 又写作sklearn, 是一个开源的基于python语言的机器学习工具包. 它通过numpy, Scipy和 Matplotlib等python数值计算的库实现的算法应用, 并且涵盖了几乎所有主流机器学习算法.
在工程应用中, 用python手写代码来从头实现一个算法的可能性非常低, 这样不仅耗时耗力, 还不一定能够写出构架清晰, 稳定性强的模型. 更多情况下, 是分析采集到的数据, 根据数据特征选择适合的算法, 在工具包中调用算法, 调整算法的参数, 获取需要的信息, 从而实现算法效率和效果之间的平衡. 而sklearn, 正是这样一个可以帮助我们高效实现算法应用的工具包.
官方网站: scikit-learn: machine learning in Python — scikit-learn 0.24.2 documentation
sklearn中决策树的类都在“tree”这个模块之下. 这个模块总共包含五个类:
tree.DecisionTreeClassifier | 分类树 |
tree.DecisionTreeRegressor | 回归树 |
tree.export_graphviz | 将生成的决策树导出位DOT格式, 画图专用 |
tree.ExtraTreeClassifier | 高随机版本的分类树 |
tree.ExtraTreeRegressor | 高随机版本的回归树 |
sklearn的基本建模流程:
1.实例化, 建立评估对象
2.通过模型接口训练模型
3.通过模型接口提取需要的信息
分类树所对应代码:
import sklearn import tree
clf = tree.DecisionTreeClassifier()
clf = clf.fit(X_train, Y_train)
result = clf.score(X_test, Y_test)
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 =Flase)
Criterion这个参数正是用来决定不纯度的计算方法的。
sklearn提供了两种选择:
1)输入“entropy”, 使用信息熵(Entropy)
2)输入“gini”,使用基尼系数(Gini Impurity)
注意, 当使用信息熵时, sklearn实际计算的是基于信息熵的信息增益(Information Gain), 即父节点的信息熵和子节点的信息熵之差. 比起基尼系数, 信息熵对不纯度更加敏感, 对不纯度的惩罚最强. 但是在实际使用中,信息熵和基尼系数的效果基本相同. 信息熵的计算比基尼系数缓慢一些, 因为基尼系数的计算不涉及对数. 另外, 因为信息熵对不纯度更加敏感, 所以信息熵作为指标时, 决策树的生长会更加“精细”, 因此对于高维数据或者噪音很多的数据, 信息熵很容易过拟合, 基尼系数在这种情况下效果往往比较好. 当模型拟合程度不足的时候, 即当模型在训练集和测试集上都表 现不太好的时候, 使用信息熵. 当然, 这些不是绝对的.
random_state用来设置分枝中的随机模式的参数, 默认None, 在高维度时随机性会表现更明显,低维度的数据 (比如鸢尾花数据集), 随机性几乎不会显现. 输入任意整数, 会一直长出同一棵树, 让模型稳定下来. splitter也是用来控制决策树中的随机选项的, 有两种输入值, 输入”best", 决策树在分枝时虽然随机, 但是还是会优先选择更重要的特征进行分枝(重要性可以通过属性feature_importances_查看), 输入“random”, 决策树在 分枝时会更加随机, 树会因为含有更多的不必要信息而更深更大,并因这些不必要信息而降低对训练集的拟合. 这也是防止过拟合的一种方式. 当你预测到你的模型会过拟合, 用这两个参数来帮助你降低树建成之后过拟合的可能性. 当然, 树一旦建成,我们依然是使用剪枝参数来防止过拟合.
不加限制的情况下, 一棵决策树会生长到衡量不纯度的指标最优, 或者没有更多的特征可用为止. 这样的决策树往往会过拟合, 这就是说, 它会在训练集上表现很好, 在测试集上却表现糟糕. 我们收集的样本数据不可能和整体的状况完全一致, 因此当一棵决策树对训练数据有了过于优秀的解释性, 它找出的规则必然包含了训练样本中的噪声, 并使它对未知数据的拟合程度不足.
为了让决策树有更好的泛化性, 我们要对决策树进行剪枝. 剪枝策略对决策树的影响巨大, 正确的剪枝策略是优化决策树算法的核心. sklearn为我们提供了不同的剪枝策略:
1) max_depth
限制树的最大深度, 超过设定深度的树枝全部剪掉.
这是用得最广泛的剪枝参数, 在高维度低样本量时非常有效. 决策树多生长一层, 对样本量的需求会增加一倍, 所以限制树深度能够有效地限制过拟合. 在集成算法中也非常实用. 实际使用时, 建议从=3开始尝试, 看看拟合的效果再决定是否增加设定深度.
2)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个训练样本, 这个节点才允许被分枝, 否则分枝就不会发生.
3) max_features & min_impurity_decrease
max_features限制分枝时考虑的特征个数, 超过限制个数的特征都会被舍弃. 和max_depth异曲同工, max_features是用来限制高维度数据的过拟合的剪枝参数, 但其方法比较暴力, 是直接限制可以使用的特征数量而强行使决策树停下的参数, 在不知道决策树中的各个特征的重要性的情况下, 强行设定这个参数可能会导致模型学习不足. 如果希望通过降维的方式防止过拟合, 建议使用PCA, ICA或者特征选择模块中的降维算法.
下面用红酒数据集画一颗决策树:
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
import pandas as pd
import graphviz
wine = load_wine()
# print(wine.target)
# pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)
Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data, wine.target, test_size=0.3)
clf = tree.DecisionTreeClassifier(criterion="entropy"
# ,random_state=30
, splitter="random"
, max_depth=3
# ,min_samples_leaf=10
# ,min_samples_split=10
)
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest) # 返回预测的准确度
feature_name = ['酒精', '苹果酸', '灰', '灰的碱性', '镁', '总酚', '类黄酮',
'非黄烷类酚类', '花青素', '颜色强度', '色调', '稀释葡萄酒', '脯氨酸']
target_name = ['琴酒', '雪莉', '贝尔摩德']
dot_data = tree.export_graphviz(clf
, out_file=None
, feature_names=feature_name
, class_names=target_name
, filled=True
, rounded=True
)
graph = graphviz.Source(dot_data.replace('helvetica', '"Microsoft YaHei"'), encoding='utf-8')
graph.view("tree")
结果如下图所示:
原作者: B站up主菜菜