引言

朴决策树的原理可以参考我的另一篇

采用红酒的数据进行建模,并绘制分类图

tree.DecisionTreeClassifier 分类决策树

函数原型:

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

参数解释:

criterion:特征选择标准

‘gini’ or ‘entropy’ (default=”gini”),前者是基尼系数,后者是信息熵。两种算法差异不大对准确率无影响,信息墒云孙效率低一点,因为它有对数运算.一般说使用默认的基尼系数”gini”就可以了,即CART算法。除非你更喜欢类似ID3, C4.5的最优特征选择方法。

splitter:特征划分标准

‘best’ or ‘random’ (default=”best”) 前者在特征的所有划分点中找出最优的划分点。后者是随机的在部分划分点中找局部最优的划分点。 默认的”best”适合样本量不大的时候,而如果样本数据量非常大,此时决策树构建推荐”random” 。

max_depth:决策树最大深度

int or None, optional (default=None) 一般来说,数据少或者特征少的时候可以不管这个值。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。常用的可以取值10-100之间。常用来解决过拟合

min_impurity_decrease:节点划分最小不纯度

float, optional (default=0.) 这个值限制了决策树的增长,如果某节点的不纯度(基尼系数,信息增益,均方差,绝对差)小于这个阈值,则该节点不再生成子节点。 sklearn 0.19.1版本之前叫 min_impurity_split

min_samples_split:内部节点再划分所需最小样本数

int, float, optional (default=2) 如果是 int,则取传入值本身作为最小样本数; 如果是 float,则去 ceil(min_samples_split * 样本数量) 的值作为最小样本数,即向上取整。

min_samples_leaf:叶子节点最少样本数

如果是 int,则取传入值本身作为最小样本数; 如果是 float,则去 ceil(min_samples_leaf * 样本数量) 的值作为最小样本数,即向上取整。 这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。

max_leaf_nodes:最大叶子节点数

int or None, optional (default=None) 通过限制最大叶子节点数,可以防止过拟合,默认是”None”,即不限制最大的叶子节点数。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征分成多的话,可以加以限制,具体的值可以通过交叉验证得到。

min_impurity_split:信息增益的阀值

决策树在创建分支时,信息增益必须大于这个阀值,否则不分裂

min_weight_fraction_leaf:叶子节点最小的样本权重和

float, optional (default=0.) 这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。 默认是0,就是不考虑权重问题。一般来说,如果我们有较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要注意这个值了。

class_weight:类别权重

dict, list of dicts, “balanced” or None, default=None 指定样本各类别的的权重,主要是为了防止训练集某些类别的样本过多,导致训练的决策树过于偏向这些类别。这里可以自己指定各个样本的权重,或者用“balanced”,如果使用“balanced”,则算法会自己计算权重,样本量少的类别所对应的样本权重会高。当然,如果你的样本类别分布没有明显的偏倚,则可以不管这个参数,选择默认的”None” 不适用于回归树 sklearn.tree.DecisionTreeRegressor

返回类型:

Return evenly spaced numbers over a specified interval.
(在start和stop之间返回均匀间隔的数据)
Returns num evenly spaced samples, calculated over the interval [start, stop].
(返回的是 [start, stop]之间的均匀分布)
The endpoint of the interval can optionally be excluded.
Changed in version 1.16.0: Non-scalar start and stop are now supported.

(可以选择是否排除间隔的终点)

一、限定最大深度

max_depth = 1
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.model_selection import train_test_split #切分训练集和测试集
from sklearn import tree, datasets
wine = datasets.load_wine()
#只选取前两个特征
X = wine.data[:, :2]
y = wine.target
#拆分训练集和数据集
X_train, X_test, y_train, y_test = train_test_split(X, y)
#设定决策树的深度为 1
clf = tree.DecisionTreeClassifier(max_depth=1)
clf.fit(X_train, y_train)
#绘制图形
#定义图像中分区的颜色和散点的颜色
cmap_light= ListedColormap(['#FFAAAA', '#AAFFAA', '#AAAAFF'])
cmap_bold = ListedColormap(['#FF0000', '#00FF00', '#0000FF'])
#分别用样本的两个特征值创建图像和横轴和纵轴
x_min, x_max = X[:,0].min()-1, X[:,0].max()+1
y_min, y_max = X[:,1].min()-1, X[:,1].max()+1
#用不同的背景色表示不同的类
xx, yy = np.meshgrid(np.arange(x_min, x_max, .02),
np.arange(y_min, y_max, .02))
z = clf.predict(np.c_[(xx.ravel(), yy.ravel())]).reshape(xx.shape)
plt.figure()
plt.pcolormesh(xx, yy, z, cmap=cmap_light)
#用散点把样本标出来
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=cmap_bold, edgecolors='k', s=20)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.title('Classifier: DecisionTrss(max_depth = 1)')
plt.show()

可以看出,最大深度等于1时,分类器只分了两类,效果不好。

6.1DecisionTree(max_depth=1).png

二、限定最大深度 max_depth = 3

#设定决策树的深度为 3

clf = tree.DecisionTreeClassifier(max_depth=3)

可以看出,最大深度等于3时,分类器只分了三类,仍有部分数据分类错误。

6.1DecisionTree(max_depth=3).png

三、限定最大深度 max_depth = 5

#设定决策树的深度为 5

clf = tree.DecisionTreeClassifier(max_depth=5)

可以看出,最大深度等于5时,分类器表现进一步提升。

6.1DecisionTree(max_depth=5).png

四、graphviz 库来展示决策树每一层的判断过程

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.model_selection import train_test_split #切分训练集和测试集
from sklearn import tree, datasets
import graphviz
from sklearn.tree import export_graphviz #导入决策树中输出graphviz的接口
from sklearn.externals.six import StringIO
import pydot
wine = datasets.load_wine()
#只选取前两个特征
X = wine.data[:, :2]
y = wine.target
#拆分训练集和数据集
X_train, X_test, y_train, y_test = train_test_split(X, y)
#设定决策树的深度为 3
clf = tree.DecisionTreeClassifier(max_depth=3)
clf.fit(X_train, y_train)
dot_data = StringIO()
dot_data = export_graphviz(clf, out_file=None, class_names=wine.target_names,
feature_names=wine.feature_names[:2], impurity=False, filled=True)
graph = graphviz.Source(dot_data) # doctest: +SKIP
#在同级目录下生成tree.pdf文件
graph.render("tree") # 保存成pdf
decisionTree.png

五、决策树的优势和不足

优势:

1.很容易将模型可视化。

2.由于决策树算法对每个特征进行单独处理,因此并不需要对数据进行转换,几乎不需要对数据进行预处理

不足:

即便采用预剪枝,但还是不可避免的出现过拟合

PS.关于graphviz 库的一些坑

之前以为在Anaconda 中 pip install graphviz 就可以了。结果发现太天真了,这个操作只是安装了graphviz的pyhon调用接口,使用的话还需要下载graphviz的安装文件。graphviz是一个软件!!但是找了网上的一些资料,怎么搞都搞不起来,下载也慢,最后看到一篇博客

《graphviz包安装》

conda install -c conda-forge graphviz xorg-libxrender xorg-libxpm

pip install graphviz