决策树有以下优点:
- 可解释性和便于理解
- 决策树不支持缺失值,而且基本上不需要数据预处理
- 使用树的成本与用于训练树的数据数量乘对数关系
- 能够同时处理数字变量和字符串变量(分类变量)
- 即使其假设在某种程度上违反了产生数据的真实模型,也有很好的表现性
决策树的缺点: - 决策树很敏感很容易过拟合,所以剪枝非常有必要。
- 决策树可能不稳定,数据的微笑变化会训练出不同的决策树。
- 决策树的预测是不平滑的。
- 在数据集中某一种类的样本过多,就会生成带有偏见的决策树。
分类
下面的数据集统一使用鸢尾花数据
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
from sklearn.metrics import mean_squared_error, r2_score
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 划分数据集, 将0.3的数据为test数据集,随机化为10
iris = datasets.load_iris()
train_x,test_x,train_y,test_y = train_test_split(iris.data, iris.target, test_size=0.3, random_state=10)
print(f"训练数据的情况:\n 特征数据:{train_x.shape}, 结果:{train_y.shape}")
训练数据的情况:
特征数据:(105, 4), 结果:(105,)
下面使用决策树对鸢尾花数据进行分类训练,然后计算测试数据的各种指标。最后再可视化该决策树
from sklearn import tree
# 决策树训练
clf = tree.DecisionTreeClassifier()
clf = clf.fit(train_x, train_y)
# 决策树预测
pred_y = np.argmax(clf.predict_proba(test_x), axis=1)
def metrics_function(pred_y, test_y):
# 准确率
print(f"准确率:{accuracy_score(test_y, pred_y)}")
# 精确率
print(f"精确率:{precision_score(test_y, pred_y, average='macro')}")
# 召回率
print(f"召回率:{recall_score(test_y, pred_y, average='macro')}")
# F1度量
print(f"F1度量:{f1_score(test_y, pred_y, average='macro')}")
# 指标输出
metrics_function(pred_y, test_y)
# 绘制决策树
tree.plot_tree(clf)
准确率:0.9777777777777777
精确率:0.9814814814814815
召回率:0.9761904761904763
F1度量:0.9781305114638448
回归
下面使用决策树对波斯顿房价进行预测。
boston = datasets.load_boston()
print(f"特征数据:{boston.data.shape}\n房价:{boston.target.shape}")
训练数据:(506, 13)
测试数据:(506,)
train_x, test_x, train_y, test_y = train_test_split(boston.data, boston.target, test_size=0.3, random_state=10)
print(f"训练数据: {train_x.shape}")
print(f"测试数据:{test_x.shape}")
训练数据: (354, 13)
测试数据:(152, 13)
clf = tree.DecisionTreeRegressor()
clf = clf.fit(train_x, train_y)
pred_y = clf.predict(test_x)
def metrics_regression_founction(test_y, pred_y):
# 标准误差
print(f"标准误差:{mean_squared_error(test_y, pred_y)}")
# R-squared
print(f"R-squared: {r2_score(test_y, pred_y)}")
metrics_regression_founction(test_y, pred_y)
标准误差:18.367105263157892
R-squared: 0.8118769549269786
多输出问题
多输出问题是一个有多个输出的监督性问题。当输出之间没有相关性,则可以每个输出创建一个模型。如果输出之间是有相互关系的则需要建立一个能够输出多个输出的单一模型。
决策树在解决多输出问题的任务需要做如下修改:
- 在叶子节点中存储n个输出值
- 使用的划分选择策略,需要计算所有n个输出平均值减少。
在下面的例子中,将使用决策树来解决多输出问题。
决策树被用来同时观测一个圆圈的噪声x和噪声y的观测值,只给出了一个特征值。基本上需要使用决策树对一个属性的样本回归出两个预测值。
# 创建数据
rng = np.random.RandomState(1)
x = np.sort(200*rng.rand(100, 1)-100, axis=0)
y = np.array([np.pi*np.sin(x).ravel(), np.pi*np.cos(x).ravel()]).T
# 在不加入噪声之前绘制一下
plt.scatter(y[:, 0], y[:, 1])
plt.show()
# 现在加入噪声
y[::5, :]+=0.5 -rng.rand(20, 2)
plt.scatter(y[:, 0], y[:, 1])
plt.show()
# 训练模型
clf = tree.DecisionTreeRegressor()
clf = clf.fit(x, y)
# 预测数据
pred_y = clf.predict(x)
# 对回归结果进行绘制
plt.figure()
# 原始数据
plt.scatter(y[:, 0], y[:, 1], edgecolors="black", label= "data")
# 预测数据
plt.scatter(pred_y[:, 0], pred_y[:, 1], edgecolors="red", label="predict")
plt.xlim([-4, 4])
plt.ylim([-4, 4])
plt.show()
上面的结果是预测值和真实值重叠了。应该是过拟合了。下面将决策树的最大层限制到8试试。
# 训练模型
clf = tree.DecisionTreeRegressor(max_depth=8)
clf = clf.fit(x, y)
# 预测数据
pred_y = clf.predict(x)
# 对回归结果进行绘制
plt.figure()
# 原始数据
plt.scatter(y[:, 0], y[:, 1], edgecolors="black", label= "data")
# 预测数据
plt.scatter(pred_y[:, 0], pred_y[:, 1], edgecolors="red", label="predict")
plt.xlim([-4, 4])
plt.ylim([-4, 4])
plt.show()
从上面的结果可以看出预测值和真实值是存在偏差的。