Scikit-learn决策树算法库总结与简单实践

mac2025-07-11  5

       上两篇我们探讨了决策树ID3算法,C4.5算法以及CART算法。CART算法在ID3,C4.5的基础上进行了不少优化,也是Scikit-learn决策树库使用的算法,是我们必须要掌握的算法之一。本篇我们基于上篇的算法原理,来探讨下Scikit-learn决策树算法库的一些常用参数,以及决策树的可视化,最后我们使用DecisionTreeClassifier做一个简单的分类实践。

1)Scikit-learn决策树算法库概述

       Scikit-learn决策树算法库既可以做分类,又可以做回归。分类库类对应DecisionTreeClassifier,回归库类对应DecisionTreeRegressor,两者的绝大多数参数都相同,下面按照参数重要性进行一一介绍。

2)DecisionTreeClassifier常用参数

        Scikit-learn DecisionTreeClassifier类官方API: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=‘deprecated’, ccp_alpha=0.0)[source]

criterion,不确定性的计算方式,默认“gini”         可以输入“gini”和“entropy”,“gini”对应CART算法的基尼系数, “entropy”对应信息增益。在实际使用中,信息熵和基尼系数的效果基本相同,但信息熵涉及对数计算,模型会慢一些。实际使用时,大多保持默认“gini”设置。

splitter,特征划分方式,默认“best”         该参数为特征划分的方式,“best”表示在特征所有划分中选择最优的划分点;“random”表示在随机划分中选择最优的划分点。实际使用时,大多保持默认“best”设置。

max_depth,树的最大深度,默认“None”         该参数用来限制树过拟合的剪枝参数,超过指定深度的树枝全部被剪掉。当为“None”是,决策树将将会自由生长。决策树首要调整的剪枝参数,实际使用时,在没有经验的情况下,可以参考从3开始调整。

min_samples_leaf,叶节点最小样本个数,默认1        该参数用来限制树过拟合的剪枝参数。如果叶节点样本数目小于该参数的值,叶节点将会被剪枝。实际使用时,小样本保持默认1设置,大样本(10万)时,需要设置该参数,可以参考从5开始调整。

min_samples_split,节点划分所需的最小样本个数,默认2        该参数用来限制树过拟合的剪枝参数。如果节点样本数小于该参数,节点将会不会再被划分。实际使用时,小样本保持默认设置,大样本(10万)时,可以参考从5开始调整。

ccp_alpha,最小剪枝系数,默认为0        该参数用来限制树过拟合的剪枝参数。对应上一篇决策树原理中的 α \alpha α,模型将会选择小于输入值最大 α \alpha α。ccp_alpha=0时,决策树不剪枝;ccp_alpha越大,越多的节点被剪枝。Scikit learn 0.22版本新增参数。

max_features,分枝时考虑的特征个数,默认为“None”        该参数用来限制树过拟合的剪枝参数。max_features限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃。输入为“None”时,使用所有的特征进行特征选择。否则设定指定数量的特征,如平方根个特征(sqrt),对数个特征(log2)。设定指定数量的特征可能会导致模型学习不足。

class_weight,类别权重参数,默认为“None”        当样本存在不平衡的情况下,需要设置该参数。 这里可以自己指定各个样本的权重,或者用‘balanced’,如果使用‘balanced’ ,则算法会自己计算权重,样本量少的类别所对应的样本权重会高。

min_weight_fraction_leaf,叶子节点最小的样本权重和,默认为0。        当设置了class_weight参数,样本量就不再是单纯地记录数目,而是受输入的权重影响了,因此这时候剪枝,就需要搭配min_ weight_fraction_leaf这个基于权重的剪枝参数来使用。

random_state,随机种子,默认为“None”        当输入为int型数值时,随机数生成器使用的输入值作为种子;输入为None时,则随机数生成器是所使用np.random产生的随机数作为种子。

3)DecisionTreeRegressor常用参数

       sklearn.tree.DecisionTreeRegressor(criterion=‘mse’, 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, presort=‘deprecated’, ccp_alpha=0.0)[source]

       DecisionTreeRegressor中的参数绝大多数参数和DecisionTreeClassifier相同,只有特征选择的方式不同。

criterion,不确定性的计算方式,默认“mse”        可以输入"mse"或者"mae",mse是均方差,mae是和均值之差的绝对值之和。实际使用时,使用默认的"mse"。

4)决策树结果可视化

       scikit-learn中决策树的可视化使用Graphviz,Graphviz是一款开源图形可视化软件包。首先我们到官网下载对应版本的Graphviz进行安装,设置环境变量,将graphviz的bin目录加到PATH,比如我的graphviz的bin目录为:D:\Program Files (x86)\decisionTreeVersion_Graphviz\bin。然后,通过pip安装可视化所需要的graphviz,pydotplus包。        注意:如果完成环境变量的设置,Python还提醒没有将graphviz的bin目录加到PATH,可使用代码指定环境目录:

import os os.environ["PATH"] += os.pathsep +"D:/Program Files (x86)/decisionTreeVersion_Graphviz/bin/"

       决策树的可视化输出有三种方式,我们放在案例中进行介绍。

5)决策树算法库使用经验总结

在高维数据下,我们需要指定 r a n d o m _ s t a t e random\_state random_state,否则每次调参时,随机种子不一样,建立的决策树也不一样,调参没有意义。如果你的数据集非常大,你已经预测到需要要剪枝,那提前设定一些剪枝参数来减少模型的复杂度,缩短模型运行的时间。使用决策树模型的属性feature_importances_查看特征重要性,以及特征选择。使用grid_search和交叉验证对剪枝参数进行选择。

6)简单实践

       下面我们使用决策树算法,对鸢尾花数据进行分类,学习决策树的可视化方式。完整代码已经上传到我的Github。        首先导入需要使用的Python包:

import numpy as np import pandas as pd import matplotlib.pyplot as plt import matplotlib as mpl from sklearn import tree from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score import pydotplus import os

       设置Python一些环境:

#设置Graphviz环境变量 os.environ["PATH"] += os.pathsep +"D:/Program Files (x86)/decisionTreeVersion_Graphviz/bin/" #中文可视化 mpl.rcParams['font.sans-serif'] = ['simHei'] mpl.rcParams['axes.unicode_minus'] = False

       读取鸢尾花数据。

iris_feature_E = 'sepal length', 'sepal width', 'petal length', 'petal width' iris_feature = '花萼长度', '花萼宽度', '花瓣长度', '花瓣宽度' iris_class = 'Iris-setosa', 'Iris-versicolor', 'Iris-virginica' path = '..\\iris.data' # 数据文件路径 data = pd.read_csv(path, header=None)

       使用鸢尾花的花萼长与花萼宽进行模型构建,方便后面做可视化效果展示。

x = data.iloc[:,:4] y = pd.Categorical(data[4]).codes x = x.iloc[:, :2] x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=1) model = DecisionTreeClassifier() model.fit(x_train, y_train) y_test_hat = model.predict(x_test) # 测试数据 print('accuracy_score:', accuracy_score(y_test, y_test_hat))

       下面我们介绍决策树的可视化,决策树的可视化方法有三种。第一种和第二种方法都是生成.dot文件,利用graphviz打开或者通过系统命令转成PNG进行查看。系统命令为:

dot -Tpng iris.dot -o iris.png

       第一种决策树可视化方法和效果如下:

with open('iris1.dot', 'w') as f: tree.export_graphviz(model, out_file=f)

       第二种决策树的可视化方法和第一种效果一样:

tree.export_graphviz(model, out_file='iris2.dot')

       我们可以看出上面两种方法生成的决策树没有对应的字段名称,不太利于解读,因此我们实际应用中使用第三种方法:

dot_data = tree.export_graphviz(model, out_file=None, feature_names=iris_feature_E[0:2], class_names=iris_class, filled=True, rounded=True, special_characters=True) graph = pydotplus.graph_from_dot_data(dot_data) graph.write_pdf('iris.pdf') f = open('iris.png', 'wb') f.write(graph.create_png()) f.close()

       第三种可视化效果如下:        我们可视化决策树的分类效果,从决策树分类效果中可以看出,决策树完全根据训练数据进行生长。

# 画图 N, M = 50, 50 # 横纵各采样多少个值 x1_min, x2_min = x.min() x1_max, x2_max = x.max() t1 = np.linspace(x1_min, x1_max, N) t2 = np.linspace(x2_min, x2_max, M) x1, x2 = np.meshgrid(t1, t2) # 生成网格采样点 x_show = np.stack((x1.flat, x2.flat), axis=1) # 测试点 cm_light = mpl.colors.ListedColormap(['#A0FFA0', '#FFA0A0', '#A0A0FF']) cm_dark = mpl.colors.ListedColormap(['g', 'r', 'b']) y_show_hat = model.predict(x_show) # 预测值 y_show_hat = y_show_hat.reshape(x1.shape) # 使之与输入的形状相同 plt.figure(facecolor='w') plt.pcolormesh(x1, x2, y_show_hat, cmap=cm_light) # 预测值的显示 plt.scatter(x_test[0], x_test[1], c=y_test.ravel(), edgecolors='k', s=100, zorder=10, cmap=cm_dark, marker='*') # 测试数据 plt.scatter(x[0], x[1], c=y.ravel(), edgecolors='k', s=20, cmap=cm_dark) # 全部数据 plt.xlabel(iris_feature[0], fontsize=13) plt.ylabel(iris_feature[1], fontsize=13) plt.xlim(x1_min, x1_max) plt.ylim(x2_min, x2_max) plt.grid(b=True, ls=':', color='#606060') plt.title('鸢尾花数据的决策树分类', fontsize=15) plt.show() # 训练集上的预测结果 y_test = y_test.reshape(-1) print(y_test_hat) print(y_test) result = (y_test_hat == y_test) # True则预测正确,False则预测错误 acc = np.mean(result) print('准确度: %.2f%%' % (100 * acc))

       下面看下树的深度和过拟合之间的关系。

# 过拟合:错误率 depth = np.arange(1, 15) err_list = [] for d in depth: clf = DecisionTreeClassifier( max_depth=d) clf.fit(x_train, y_train) y_test_hat = clf.predict(x_test) # 测试数据 result = (y_test_hat == y_test) # True则预测正确,False则预测错误 err = 1 - np.mean(result) err_list.append(err) print(d, ' 错误率: %.2f%%' % (100 * err)) plt.figure(facecolor='w') plt.plot(depth, err_list, 'ro-', markeredgecolor='k', lw=2) plt.xlabel('决策树深度', fontsize=13) plt.ylabel('错误率', fontsize=13) plt.title('决策树深度与过拟合', fontsize=15) plt.grid(b=True, ls=':', color='#606060') plt.show()

       到此,我们终于完成了决策树算法系列的探讨。希望大家有所思,有所悟。

(欢迎大家在评论区探讨交流,也欢迎大家转载,转载请注明出处) 上篇:决策树(Decision Tree)算法原理总结(二) 下篇:集成学习方法之Bagging,Boosting,Stacking

最新回复(0)