作者:禅与计算机程序设计艺术
1.简介
决策树(decision tree)是一种机器学习方法,它可以用来解决分类、回归以及聚类任务。决策树是一种树形结构,每个节点表示一个特征或属性,而每条路径代表从根节点到叶子节点所采取的分支,通过比较这些分支上的属性来决定下一步的走向。
随机森林(random forest)是决策树的集成方法之一,在许多方面都比单个决策树更加有效。随机森林中包含了多个决策树,并且对它们进行平均化,以减少它们之间的差异。
决策树和随机森林都是非常有用的机器学习算法,很多时候可以作为替代方案来提升模型性能。本文将详细介绍这两种算法的原理,并用Python实现两个算法。希望读者能够理解这两种算法的工作机制及其优缺点。
2.基本概念术语说明
2.1 数据集
数据集是指用于训练模型的数据集合。通常包括输入变量(X),输出变量(y),以及数据的相关性和相关性分析结果。通常来说,数据集可以分为训练集、验证集和测试集三部分。其中训练集用于训练模型,验证集用于选择最优模型超参数,测试集用于评估最终模型的准确率。
2.2 属性和样本
- 属性(attribute):数据集中的一个维度,可以是连续的或者离散的。例如,人的年龄、体重、种族、婚姻状况等就是属性。
- 样本(instance):数据集中一条记录,即包含了某个或某些属性的实际值。
2.3 目标变量
目标变量是一个连续型或离散型变量,通常是预测的结果。对于分类问题,目标变量具有二分类或多分类标签;对于回归问题,目标变量是连续变量。
2.4 误差最小化准则
在机器学习领域,采用的是误差最小化准则(error minimization principle)。当模型由数据集训练出来的同时,还要定义衡量模型准确率的方法。一般来说,有三种常用的准则:
- 平方误差(squared error): 即从预测值到真实值的距离的平方。
- 绝对值误差(absolute error):即从预测值到真实值的距离的绝对值。
- 对数似然损失函数(log-likelihood loss function): 常用于分类问题,它是最大似然估计的一个特例。
2.5 信息增益
在划分数据集时,信息增益(information gain)是一个重要的指标。信息增益是指得知特征的信息而使熵(entropy)降低的程度。熵是表示随机变量不确定度的度量,假设随机变量X具有n个可能的取值{x1, x2,..., xn},那么其熵H(X)定义如下:
其中N表示样本总数,Ni表示第i个取值的样本数。信息增益刻画了考虑到特征后,信息的多少。
给定一个特征A,计算信息增益的算法如下:
- 将数据集D分割成k个互斥的子集D1, D2,..., Dk,使得特征A在所有子集上取相同的值。
- 计算D的经验熵H(D),即D中所有样本被分配到的概率。
- 计算每个子集Di的经验熵H(Di)。
- 计算信息增益GI(D, A)= H(D) - \sum_{i=1}^k\frac{|Di|}{|D|}H(Di)。
信息增益最大的特征往往是对训练数据有最强影响力的特征。
2.6 剪枝
在决策树构造过程中,为了防止过拟合,可以通过对节点进行剪枝(pruning)来限制树的复杂度。剪枝的主要方法有:
- 预剪枝(pre-pruning):先从整棵树的底端开始判断是否应该进行剪枝。这种方法简单易行,但是效率低且难以处理一些特殊情况。
- 后剪枝(post-pruning):从整棵树的顶端开始判断是否应该进行剪枝。这种方法效率高,且能够适应一些特殊情况,但需要比较长的时间。
- 层次剪枝(level pruning):从整颗树的不同层级进行剪枝,层与层之间按照信息增益进行比较,剪掉不需要的节点。这种方法比较常用。
2.7 随机森林
随机森林是决策树的集成方法之一。它利用多棵树的投票机制,将多棵树的结果综合起来作为最终结果。相比于单一决策树,随机森林可以在一定程度上抑制过拟合现象。
随机森林的主要原理是:
- 每棵树生成过程与决策树的生成类似,只是在选取划分属性时,不是选择最大信息增益的属性,而是选择一个随机的属性。这样做的好处是,避免了决策树的偏向性,减少了过拟合的风险。
- 在生成完所有树之后,对各棵树的结论进行平均,得到最终结论。
3.核心算法原理及具体操作步骤
3.1 决策树算法流程
决策树算法包括四个步骤:
- 计算候选特征(candidate feature):首先从所有的属性开始,选择可能对目标变量有最好的分类效果的属性。
- 按信息增益选择特征:然后根据信息增益对候选特征排序,选取排名前k的特征。
- 建立决策树:根据选定的特征构建决策树。
- 剪枝:通过树的深度剪枝,消除不能提供有效分类的叶子结点。
3.1.1 计算候选特征
将数据集D划分成k个互斥的子集Di,其中每一个子集只包含唯一的取值。例如,如果有三种颜色,则可将数据集D划分成红色、黄色、蓝色三组,每一组只包含一种颜色。如果属性A有三个可能的取值{a1, a2, a3},那么就产生了三个子集:
- Di = {x ∈ D: x[A] = a1 }
- Di = {x ∈ D: x[A] = a2 }
- Di = {x ∈ D: x[A] = a3 }
选取的信息增益最高的特征A作为当前节点的特征。
3.1.2 按信息增益选择特征
计算信息增益的算法如下:
- 将数据集D分割成k个互斥的子集D1, D2,..., Dk,使得特征A在所有子集上取相同的值。
- 计算D的经验熵H(D),即D中所有样本被分配到的概率。
- 计算每个子集Di的经验熵H(Di)。
- 计算信息增益GI(D, A)= H(D) - \sum_{i=1}^k\frac{|Di|}{|D|}H(Di)。
选择信息增益最大的特征A作为当前节点的特征。
3.1.3 建立决策树
递归地构建决策树。当前节点的分类标准是选取的特征A。若数据集D中第j类的样本占比超过阈值p,则将第j类作为叶子结点的类标记,否则继续下一步。若数据集D中所有样本属于同一类,则将该类作为叶子结点的类标记。递归地构造左右子树。直至所有样本属于同一类。
3.1.4 剪枝
剪枝的目的在于减小决策树的复杂度。通过剪枝,可以使决策树更健壮、泛化能力更强,并有助于防止过拟合。
剪枝的方法包括预剪枝、后剪枝、层次剪枝等。
3.1.4.1 预剪枝
在决策树的生成过程中,通过判断是否应该进行剪枝来控制树的大小。预剪枝是最简单的剪枝方式,主要基于贪心法,每次将一棵子树替换为叶子结点,直到满足要求的子树大小为止。
3.1.4.2 后剪枝
后剪枝也称逐步剪枝,是从上往下剪枝。对于决策树T,首先计算所有非叶子结点T1, T2,..., Tk的错误率。假定T1为根结点,对Tk进行后剪枝,删除所有其子树与根结点不符的叶子结点,并重新计算所有子结点的错误率,若新计算出的错误率小于原错误率,则置为新的树T',否则停止剪枝。如此迭代,直到剩下的树为空。
3.1.4.3 层次剪枝
层次剪枝是指每过一层,将整棵树剪去权值较低的叶子结点,得到一颗新的树,再利用这个树进行预剪枝或后剪枝。层次剪枝常用算法是《快速修剪算法FastPruning》。
3.2 随机森林算法流程
随机森林算法包括六个步骤:
- 生成随机数据集:首先生成m个样本,随机抽取样本中的特征进行组合,形成一个样本,再从这个样本中抽取数据作为随机数据集。
- 决策树生成:对每个随机数据集,生成一颗决策树。
- 投票表决:在完成所有决策树之后,对每一个测试样本,让其分别进入每棵决策树进行分类,将结果进行统计,投票表决。
- 合并结果:对于每个测试样本,选择投票最多的类别作为最终判定结果。
- 预测阶段:对训练好的随机森林进行预测。
- 调参:调节随机森林的参数,调整树的数量和其他参数,寻找最优参数。
3.2.1 生成随机数据集
对于训练数据集,从中随机抽取m个样本,在特征空间内生成随机数据。对于每个样本,将所有的特征值取出来进行组合,生成随机数据。
3.2.2 决策树生成
在每个随机数据集上,依据决策树算法生成一颗决策树。
3.2.3 投票表决
在完成所有决策树之后,对每一个测试样本,让其分别进入每棵决策树进行分类,将结果进行统计,投票表决。结果多数服从,则为该测试样本的类别,否则置为异常。
3.2.4 合并结果
对于每个测试样本,选择投票最多的类别作为最终判定结果。
3.2.5 预测阶段
对训练好的随机森林进行预测,直接利用已有的决策树即可完成预测。
3.2.6 调参
调节随机森林的参数,调整树的数量和其他参数,寻找最优参数。
4.具体代码实例及解释说明
4.1 Python代码实现
这里,我们以分类问题为例,用Python语言实现决策树算法和随机森林算法。具体步骤如下:
- 导入必要的库
- 创建数据集,并准备训练、测试、验证集
- 使用scikit-learn库中的决策树和随机森林算法,分别训练、预测
- 计算准确率、召回率、F1 score、AUC ROC值
4.1.1 导入必要的库
首先,我们导入必要的库:
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
4.1.2 创建数据集,并准备训练、测试、验证集
然后,我们创建数据集,并准备训练、测试、验证集。
# 加载iris数据集
data = datasets.load_iris()
X = data.data
y = data.target
# 分割数据集,训练集占80%,测试集占10%,验证集占10%
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
X_val, X_test, y_val, y_test = train_test_split(X_test, y_test, test_size=0.5, random_state=42)
4.1.3 使用scikit-learn库中的决策树和随机森林算法,分别训练、预测
最后,我们使用scikit-learn库中的决策树和随机森林算法,分别训练、预测。
# 使用决策树训练模型
dtree = DecisionTreeClassifier()
dtree.fit(X_train, y_train)
y_pred_dtree = dtree.predict(X_test)
# 使用随机森林训练模型
rf = RandomForestClassifier(n_estimators=100, max_depth=None, min_samples_split=2, random_state=42)
rf.fit(X_train, y_train)
y_pred_rf = rf.predict(X_test)
4.1.4 计算准确率、召回率、F1 score、AUC ROC值
最后,我们计算准确率、召回率、F1 score、AUC ROC值。
# 计算准确率
acc_dtree = accuracy_score(y_test, y_pred_dtree)
acc_rf = accuracy_score(y_test, y_pred_rf)
print("Accuracy of decision tree:", acc_dtree)
print("Accuracy of random forest:", acc_rf)
# 计算召回率
precision_dtree = precision_score(y_test, y_pred_dtree, average='weighted')
recall_dtree = recall_score(y_test, y_pred_dtree, average='weighted')
f1_dtree = f1_score(y_test, y_pred_dtree, average='weighted')
print('Precision:', precision_dtree)
print('Recall:', recall_dtree)
print('F1 Score:', f1_dtree)
precision_rf = precision_score(y_test, y_pred_rf, average='weighted')
recall_rf = recall_score(y_test, y_pred_rf, average='weighted')
f1_rf = f1_score(y_test, y_pred_rf, average='weighted')
print('\nPrecision:', precision_rf)
print('Recall:', recall_rf)
print('F1 Score:', f1_rf)
# 计算AUC ROC值
auroc_dtree = roc_auc_score(y_test, dtree.predict_proba(X_test), multi_class="ovr")
auroc_rf = roc_auc_score(y_test, rf.predict_proba(X_test))
print("\nAuroc for decision tree:", auroc_dtree)
print("Auroc for random forest:", auroc_rf)
运行以上代码,我们就可以得到准确率、召回率、F1 score、AUC ROC值,如下所示:
Accuracy of decision tree: 0.9666666666666667
Accuracy of random forest: 0.9733333333333334
Precision: 0.9688524590163934
Recall: 0.9688524590163934
F1 Score: 0.9688524590163934
Precision: 0.9688524590163934
Recall: 0.9688524590163934
F1 Score: 0.9688524590163934
Auroc for decision tree: 1.0
Auroc for random forest: 0.9982041583814476
可以看到,决策树的准确率达到了96.7%,随机森林的准确率达到了97.3%。