决策树是一种机器学习的方法。决策树的生成算法有ID3(信息增益), C4.5(信息增益率)和CART(Gini系数)等。决策树是一种树形结构,其中每个内部节点表示一个属性上的判断,每个分支代表一个判断结果的输出,最后每个叶节点代表一种分类结果。
构造树的基本想法是随着树深度的增加,节点的熵迅速地降低。熵降低地速度越快越好,这样我们有望得到一颗高度最矮地决策树。
描述样本纯度,熵和Gini系数越大,表示样本纯度越小,即样本中每一类出现的概率越小。
熵值的变化。希望构建决策树的过程中,信息增益越大越好。但如果在确定一个根节点之后,有很多子样本,每个子样本非常纯,那么就会出现熵约等于1的情况,但这种情况不是我们希望看到的,所以此方法需要改进。
预剪枝:在构建决策树的过程时,提前停止
后剪枝:决策树构建好后,然后才开始裁剪
评价决策树结构的好坏,类似于损失函数。其中Nt为当前叶子节点样本个数,H(t)则表示当前叶子节点的熵值或Gini值。
叶子节点个数太多,也会影响决策树结构好坏,加入了剪枝以后,评价函数变为:
from sklearn import tree
from sklearn.datasets import load_iris
from sklearn import model_selection
import matplotlib.pyplot as plt
import graphviz
# 加载鸢尾花数据集,X为数据集,y为标签
dataSet = load_iris()
X = dataSet.data
y = dataSet.target
# 特证名称
feature_names = dataSet.feature_names
# 类名
target_names = dataSet.target_names
# 划分数据集
X_train, X_test, Y_train, Y_test = model_selection.train_test_split(X, y)
# 实例化模型对象
# 1.criterion这个参数正是用来决定不纯度的计算方法的
# 输入"entropy",使用信息熵;输入“gini”,使用基尼系数
# 对于高维数据或者噪音很多的数据,信息熵很容易过拟合,基尼系数在这种情况下效果往往会更好
# 2.random_state用来设置分支中的随机模式的参数,默认为None,在高维度时随机性会表示的更加明显
# 3.splitter也是用来控制决策树中的随机选项的
# 输入“best”,决策树在分支时虽然随机,但是还是会优先选择更加重要的特征进行分支;
# 输入"random",决策树会在分支时更加随机,树会因为含有更多的不必信息而更深更大,可能会导致过拟合问题
# 4.剪枝操作
# (1)max_depth:限制树的最大深度,超过设定深度的树枝全部剪掉
# (2)min_samples_leaf:一个节点在分支后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分支就不会发生
# (3)min_samples_split:一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分支,否则分支就不会发生
# (4)max_features:限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃,和max_depth相似
# (5)min_impurity_decreases:限制信息增益的大小,信息增益小于设定数值的分枝不会发生。
clf = tree.DecisionTreeClassifier(criterion='entropy')
# 通过模型接口训练模型
clf = clf.fit(X_train, Y_train)
# 模型预测
predict_y = clf.predict(X_test)
print("对测试集样本的预测结果:\n", predict_y)
predict_y1 = clf.predict_proba(X_test)
print("预测样本为某个标签的概率:\n", predict_y1)
# 通过测试集对模型评分(0-1)
Test_score = clf.score(X_test, Y_test)
print("模型在测试集上进行评分:\n", Test_score)
# 使用grapviz绘制决策树
clf_dot = tree.export_graphviz(clf,
out_file=None,
feature_names=feature_names,
class_names=target_names,
filled=True,
rounded=True)
graph = graphviz.Source(clf_dot,
filename="iris_decisionTree",
format="png")
graph.view()
print("\n特征重要程度为:")
info = [*zip(feature_names, clf.feature_importances_)]
for cell in info:
print(cell)
# 确认最优的剪枝参数,横坐标是超参数,纵坐标是模型度量,这里是Test_score
test = []
for i in range(10):
clf = tree.DecisionTreeClassifier(max_depth=i + 1
, criterion="entropy"
, random_state=30
, splitter="random"
)
clf = clf.fit(X_train, Y_train)
score = clf.score(X_test, Y_test)
test.append(score)
plt.plot(range(1, 11), test, color="red", label="max_depth")
plt.legend()
plt.show()