第一部分:决策树的缺点
(1)训练的复杂度过高
这个详细的源代码可见机器学习实现决策树Decision Tree-CSDN博客
这里面有详细的进行决策树的代码,每个节点的处理过程分为两层for循环和内部的一层计算熵的函数。
(2)比较容易过拟合
这个和knn非常相似,都属于非参数的学习方式,比较容易出现过拟合现象。
第二部分:剪枝的目的(降低复杂度+解决过拟合)和手段
(1)存在过拟合的代码(以鸢尾花数据集为例,使用决策树分类算法)
①导包
#第一部分:导包
import numpy as np
import matplotlib.pyplot as plt
②加载数据集
#第二部分:加载数据集
from sklearn.datasets import load_iris
iris = load_iris()
x=iris.data[:,0:2]#选择前两个特征
y=iris.target
plt.scatter(x[:,0],x[:,1],c=y)
plt.show()
③使用决策树进行分类
#第三部分:使用决策树进行分类
from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier()
clf = clf.fit(x,y)
④使用决策边界来绘制样本点分类散布情况
#第四部分:使用决策边界来绘制样本点分类散布情况
def decision_boundary_plot(X, y, clf):
axis_x1_min, axis_x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
axis_x2_min, axis_x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
x1, x2 = np.meshgrid(np.arange(axis_x1_min, axis_x1_max, 0.01),
np.arange(axis_x2_min, axis_x2_max, 0.01))
z = clf.predict(np.c_[x1.ravel(), x2.ravel()])
z = z.reshape(x1.shape)
from matplotlib.colors import ListedColormap
custom_cmap = ListedColormap(['#F5B9EF', '#BBFFBB', '#F9F9CB'])
plt.contourf(x1, x2, z, cmap=custom_cmap)
plt.scatter(X[:, 0], X[:, 1], c=y)
plt.show()
decision_boundary_plot(x,y,clf)
从这个图中就可以看出来,图形分布交错混乱,也就是过拟合的表现。
⑤可视化分类结构图
#第五部分:可视化分类结构图
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt
# 绘制决策树
plt.figure(figsize=(10, 6)) # 设置图像大小
plot_tree(clf, filled=True) # `filled=True` 会为不同的类别填充颜色
plt.show()
可以看到,真正的树总共有13层,过拟合!
⑥完整pycharm代码
#第一部分:导包
import numpy as np
import matplotlib.pyplot as plt
#第二部分:加载数据集
from sklearn.datasets import load_iris
iris = load_iris()
x=iris.data[:,0:2]#选择前两个特征
y=iris.target
plt.scatter(x[:,0],x[:,1],c=y)
plt.show()
#第三部分:使用决策树进行分类
from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier()
clf = clf.fit(x,y)
#第四部分:使用决策边界来绘制样本点分类散布情况
def decision_boundary_plot(X, y, clf):
axis_x1_min, axis_x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
axis_x2_min, axis_x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
x1, x2 = np.meshgrid(np.arange(axis_x1_min, axis_x1_max, 0.01),
np.arange(axis_x2_min, axis_x2_max, 0.01))
z = clf.predict(np.c_[x1.ravel(), x2.ravel()])
z = z.reshape(x1.shape)
from matplotlib.colors import ListedColormap
custom_cmap = ListedColormap(['#F5B9EF', '#BBFFBB', '#F9F9CB'])
plt.contourf(x1, x2, z, cmap=custom_cmap)
plt.scatter(X[:, 0], X[:, 1], c=y)
plt.show()
decision_boundary_plot(x,y,clf)
#第五部分:可视化分类结构图
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt
# 绘制决策树
plt.figure(figsize=(10, 6)) # 设置图像大小
plot_tree(clf, filled=True) # `filled=True` 会为不同的类别填充颜色
plt.show()
(2)剪枝方式1:限制深度(结点层数)
(3)剪枝方式2:限制广度(叶子结点个数)
我们将第三部分代码的clf = DecisionTreeClassifier()内添加四个参数:max_depth和min_samples_split和min_samples_leaf和max_leaf_nodes和min_weight_fraction_leaf
变成了:
clf = DecisionTreeClassifier(max_depth=3,min_samples_split=20,min_samples_leaf=5,max_leaf_nodes=5,min_weight_fraction_leaf=0.03)
代表的含义就是:
①最多就只能有3层
②同时当每一个分类的样本总数少于20的时候就不再进行往下划分了;
③最小样本数不能低于5个,如果低于5个了就要向上合并,让它的上一级成为叶子结点.
④最多只能有5个叶子结点
⑤指定叶子结点中的最小权重(在没有设置样本权重的时候,所有样本的权重是相同的)
就好比总共有100个样本,每个样本权重0.01,我规定每个叶子结点中权重最少要0.05,也就是说,这个叶子结点中最起码要有5个点,少于5个点就不能分,其实跟③中差不多。
完整代码:
#第一部分:导包
import numpy as np
import matplotlib.pyplot as plt
#第二部分:加载数据集
from sklearn.datasets import load_iris
iris = load_iris()
x=iris.data[:,0:2]#选择前两个特征
y=iris.target
plt.scatter(x[:,0],x[:,1],c=y)
plt.show()
#第三部分:使用决策树进行分类
from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier()
clf = DecisionTreeClassifier(max_depth=3,min_samples_split=20,min_samples_leaf=5,max_leaf_nodes=5,min_weight_fraction_leaf=0.03)
clf = clf.fit(x,y)
#第四部分:使用决策边界来绘制样本点分类散布情况
def decision_boundary_plot(X, y, clf):
axis_x1_min, axis_x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
axis_x2_min, axis_x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
x1, x2 = np.meshgrid(np.arange(axis_x1_min, axis_x1_max, 0.01),
np.arange(axis_x2_min, axis_x2_max, 0.01))
z = clf.predict(np.c_[x1.ravel(), x2.ravel()])
z = z.reshape(x1.shape)
from matplotlib.colors import ListedColormap
custom_cmap = ListedColormap(['#F5B9EF', '#BBFFBB', '#F9F9CB'])
plt.contourf(x1, x2, z, cmap=custom_cmap)
plt.scatter(X[:, 0], X[:, 1], c=y)
plt.show()
decision_boundary_plot(x,y,clf)
#第五部分:可视化分类结构图
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt
# 绘制决策树
plt.figure(figsize=(10, 6)) # 设置图像大小
plot_tree(clf, filled=True) # `filled=True` 会为不同的类别填充颜色
plt.show()
可以发现,最终的效果比之前要好了不少。
但是如果我们这个里面的参数过于极端,也会出现过拟合现象,比如只设置最多1层,每层1000个点,相当于直接让二叉树失效了。
注:我们可以手动设置这5个参数,当然也可以使用网格搜索的方式来找到最优超参数!
第三部分:附加提示
(1)方向问题
从上述我们通过“使用决策边界来绘制样本点分类散布情况”,就可以看出,决策树只能用于“水平方向上样本点的分类,如果这个分类正确应该是斜着的分类线,那么决策树就会产生很大的误差!”
(2)不够稳定
随便改变某一个数可能会让改变前和改变后的图像出现较大的变化!