《机器学习实战——基于Scikit-Learn和TensorFlow》
这是一本非常好的机器学习和深度学习入门书,既有基本理论讲解,也有实战代码示例。
我将认真阅读此书,并为每一章内容做一个知识笔记。
我会摘录一些原书中的关键语句和代码,若有错误请为我指出。
第六章 决策树
决策树可以实现分类和回归任务,甚至是多输出任务。
1 决策树训练和可视化
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
iris = load_iris()
X = iris.data[:, 2:] # petal length and width
y = iris.target
tree_clf = DecisionTreeClassifier(max_depth=2, random_state=42)
tree_clf.fit(X, y)
from sklearn.tree import export_graphviz
export_graphviz(
tree_clf,
out_file=image_path("iris_tree.dot"),
feature_names=iris.feature_names[2:],
class_names=iris.target_names,
rounded=True,
filled=True
)
from matplotlib.colors import ListedColormap
def plot_decision_boundary(clf, X, y, axes=[0, 7.5, 0, 3], iris=True, legend=False, plot_training=True):
x1s = np.linspace(axes[0], axes[1], 100)
x2s = np.linspace(axes[2], axes[3], 100)
x1, x2 = np.meshgrid(x1s, x2s)
X_new = np.c_[x1.ravel(), x2.ravel()]
y_pred = clf.predict(X_new).reshape(x1.shape)
custom_cmap = ListedColormap(['#fafab0','#9898ff','#a0faa0'])
plt.contourf(x1, x2, y_pred, alpha=0.3, cmap=custom_cmap)
if not iris:
custom_cmap2 = ListedColormap(['#7d7d58','#4c4c7f','#507d50'])
plt.contour(x1, x2, y_pred, cmap=custom_cmap2, alpha=0.8)
if plot_training:
plt.plot(X[:, 0][y==0], X[:, 1][y==0], "yo", label="Iris-Setosa")
plt.plot(X[:, 0][y==1], X[:, 1][y==1], "bs", label="Iris-Versicolor")
plt.plot(X[:, 0][y==2], X[:, 1][y==2], "g^", label="Iris-Virginica")
plt.axis(axes)
if iris:
plt.xlabel("Petal length", fontsize=14)
plt.ylabel("Petal width", fontsize=14)
else:
plt.xlabel(r"$x_1$", fontsize=18)
plt.ylabel(r"$x_2$", fontsize=18, rotation=0)
if legend:
plt.legend(loc="lower right", fontsize=14)
plt.figure(figsize=(8, 4))
plot_decision_boundary(tree_clf, X, y)
plt.plot([2.45, 2.45], [0, 3], "k-", linewidth=2)
plt.plot([2.45, 7.5], [1.75, 1.75], "k--", linewidth=2)
plt.plot([4.95, 4.95], [0, 1.75], "k:", linewidth=2)
plt.plot([4.85, 4.85], [1.75, 3], "k:", linewidth=2)
plt.text(1.40, 1.0, "Depth=0", fontsize=15)
plt.text(3.2, 1.80, "Depth=1", fontsize=13)
plt.text(4.05, 0.5, "(Depth=2)", fontsize=11)
save_fig("decision_tree_decision_boundaries_plot")
plt.show()
2 做出预测
决策树的特质之一就是它们需要的数据准备工作非常少。
特别是。完全不需要进行特征缩放或集中。
基尼不纯度计算。
白盒模型:直观易解释,决策树。
黑盒模型:难以解释,随机森林,神经网络。
3 估算类别概率
找到某实例的叶节点,该节点中某类别的实例占比就是输入该类别的概率。
4 CART训练算法
scikit-learn使用的是 分类与回归树 。
首先,使用单个特征k和阈值t_k将训练集分成两个子集。
CART分类成本函数:
J
(
k
,
t
k
)
=
m
l
e
f
t
m
G
l
e
f
t
+
m
r
i
g
h
t
m
G
r
i
g
h
t
J(k,t_k)=\frac{m_{left}}{m}G_{left}+\frac{m_{right}}{m}G_{right}
J(k,tk)=mmleftGleft+mmrightGright
G_left和G_eight衡量左右子树的不纯度。
不断一分为二,直到抵达最大深度,或是再也找不到能够降低不纯度的分裂才会停止。
CART是一种贪婪算法。
5 计算复杂度
决策树大致平衡,通过从根节点到叶节点进行预测需要经历约O(log_2(m))个节点。
预测复杂度和特征数量无关,即便是大型数据集预测也很快。
但是在训练时,由于训练每一个节点都需要在样本上比较所有特征,导致复杂度为O(nmlog(m))。
对于小型训练集,scikitl-learn可以通过对数据预处理来加快训练,但是对于较大训练集而言,可能会减慢训练的速度。
6 基尼不纯度还是信息熵
默认使用基尼不纯度进行测量,但是可以将超参数criterion设置为entropy来选择 信息熵 作为不纯度的测量方式。
如果数据集中仅包含一个类别的实例,则熵为零。
计算公式略。
7 正则化超参数
决策树极少地对训练数据做出假设,如果不加以限制,树的结构将跟随训练集变化,严密拟合,并且很可能过度拟合。
这种模型是 非参数模型 ,训练之前没有确定参数的数量,导致模型结构自由而紧密地贴近数据。
参数模型 则预先定好部分参数,自由度受限,降低了过度拟合的风险。
在scikit-learn中,使用超参数max_depth可以使模型正则化,降低过度拟合的风险。同样还有其他超参数。
或可以先通过不加限制地训练模型,再对不必要的节点进行剪枝。
from sklearn.datasets import make_moons
Xm, ym = make_moons(n_samples=100, noise=0.25, random_state=53)
deep_tree_clf1 = DecisionTreeClassifier(random_state=42)
deep_tree_clf2 = DecisionTreeClassifier(min_samples_leaf=4, random_state=42)
deep_tree_clf1.fit(Xm, ym)
deep_tree_clf2.fit(Xm, ym)
plt.figure(figsize=(11, 4))
plt.subplot(121)
plot_decision_boundary(deep_tree_clf1, Xm, ym, axes=[-1.5, 2.5, -1, 1.5], iris=False)
plt.title("No restrictions", fontsize=16)
plt.subplot(122)
plot_decision_boundary(deep_tree_clf2, Xm, ym, axes=[-1.5, 2.5, -1, 1.5], iris=False)
plt.title("min_samples_leaf = {}".format(deep_tree_clf2.min_samples_leaf), fontsize=14)
save_fig("min_samples_leaf_plot")
plt.show()
8 回归
可用DecisionTreeRegressor来构建一个回归树。
# Quadratic training set + noise
np.random.seed(42)
m = 200
X = np.random.rand(m, 1)
y = 4 * (X - 0.5) ** 2
y = y + np.random.randn(m, 1) / 10
from sklearn.tree import DecisionTreeRegressor
tree_reg = DecisionTreeRegressor(max_depth=2, random_state=42)
tree_reg.fit(X, y)
预测值等于该区域内实例的目标平均值。
回归问题也容易过度拟合,需要正则化。
9 不稳定性
决策树的缺点之一:青睐正交的决策边界,使得对于训练集的旋转非常敏感。
可使用PCA来让训练数据定位在一个更好的方向上。
决策树对于训练数据中的小变化非常敏感。
随机森林可限制这种不稳定性。