机器学习——随机森林
一、简介
随机森林(Random Forest)是一种强大的集成学习算法,由Leo Breiman和Adele Cutler于2001年在论文"Random Forests"中首次提出。该算法通过构建多个决策树进行预测,并采用投票或平均的方式来综合各个决策树的结果,从而提高模型的准确性和泛化能力。
作为机器学习领域最常用的算法之一,随机森林具有以下显著特点:
- 采用bootstrap抽样方法构建多棵决策树
- 在每棵树的节点分裂时,随机选择部分特征进行最优分割
- 通过"多数表决"(分类)或"平均输出"(回归)的方式整合多个决策树的结果
这种集成方法有效克服了单一决策树容易过拟合的缺点,同时保持了决策树模型解释性强的优势。
二、基本原理
随机森林是一种基于决策树的集成学习方法,它通过构建多棵决策树并将它们组合起来进行预测。其核心思想源于"群体智慧"的概念——多个弱分类器(决策树)的集体决策往往比单个强分类器更准确可靠。
了解随机森林算法,首先需要理解其理论基础——集成学习(Ensemble Learning)。集成学习是一种通过构建并结合多个基学习器(Base Learner)来完成学习任务的机器学习方法。其核心思想是通过组合多个弱学习器来获得比单一学习器更优越的泛化性能。

集成学习主要分为两大类方法:
-
Bagging(Bootstrap Aggregating):通过自助采样法(bootstrap sampling)生成多个训练子集,并行训练多个基学习器,最后通过投票或平均的方式结合预测结果。随机森林就是Bagging方法的典型代表。
-
Boosting:通过迭代的方式串行训练基学习器,每个基学习器都试图修正前一个学习器的错误,最后通过加权投票的方式结合预测。AdaBoost和GBDT是Boosting的代表算法。
随机森林作为Bagging方法的扩展,在构建决策树时还引入了随机特征选择:
- 每棵决策树在节点分裂时,只考虑随机选取的一部分特征(而非全部特征)
- 这种双重随机性(数据随机+特征随机)有效提升了模型的多样性,降低了过拟合风险
随机森林的工作流程包含以下关键步骤:
-
自助采样(Bootstrap Sampling):从原始训练集中有放回地随机抽取n个样本,形成新的训练子集。这个过程会重复进行,为每棵树生成不同的训练数据。
-
随机特征选择:在构建每棵决策树时,不是考虑所有特征,而是从特征集合中随机选取一个子集(通常取特征总数的平方根),然后从中选择最优分裂特征。
-
完全生长决策树:每棵树都独立地生长到最大深度,不进行剪枝。这种"高方差低偏差"的策略正是通过后续的集成来平衡的。
-
投票/平均机制:
- 分类任务:采用多数投票法
- 回归任务:取所有树的预测平均值

这种方法的优势体现在多个方面:
- 通过随机性引入多样性,降低过拟合风险
- 天然支持并行计算(每棵树可独立构建)
- 能自动处理高维数据,对特征缩放不敏感
- 提供特征重要性评估
三、随机森林的特点与优势
3.1 主要优势
-
高准确性:通过集成多棵树降低方差,通常比单棵决策树表现更好
-
抗过拟合:双重随机性(数据+特征)有效防止过拟合
-
处理高维数据:能自动处理数千个输入变量,无需特征降维
-
鲁棒性强:
-
对缺失数据不敏感
-
能处理不平衡数据
-
对异常值有较好容忍度
-
-
特征重要性评估:可计算各特征对预测的贡献度
-
并行计算:各树独立训练,适合并行化加速
3.2 局限性
-
计算资源消耗大:大量决策树需要更多内存和计算时间
-
模型解释性差:相比单棵决策树更难直观理解
-
回归预测受限:预测值不会超出训练数据范围
-
参数调优复杂:需调整树数量、深度等多个超参数
四、随机森林的参数
# sklearn.ensemble.RandomForestClassifier 参数详解
## 随机森林特有参数
### `n_estimators` [默认100]
- **定义**:森林中决策树的数目
- **版本变化**:
- scikit-learn 0.22 版本前默认值为10
- 0.22+ 版本改为100
- **建议值**:
- 小数据集(特征<50):50-200
- 中等数据集:200-300
- 大数据集(特征>100):可增至500+
- 实际应用中通常100-500足够
- **性能影响**:
- 值越大模型越稳定,但训练时间越长
- 超过一定数量后准确率提升有限### `max_features` [默认'sqrt']
- **功能**:每棵树分裂时考虑的特征数量
- **详细取值**:
- **整数**:直接指定特征数量(如10)
- **浮点数**(0.0-1.0):总特征数×该比例
- 例如0.3表示考虑30%特征
- **'sqrt'**:取特征总数的平方根(分类任务推荐)
- **'log2'**:取以2为底的对数值
- **None/1.0**:使用全部特征(等同于决策树)
- **实践建议**:
- 分类任务:sqrt或log2
- 回归任务:通常用1.0或0.5-0.8### `bootstrap` [默认True]
- **作用**:控制采样方式
- True:使用有放回抽样(bootstrap抽样)
- False:使用原始完整数据集
- **相关参数**:
- 当True时可配合使用`oob_score`
- `max_samples`可控制采样数量### `oob_score` [默认False]
- **功能**:使用袋外样本(out-of-bag)进行模型评估
- **要求**:必须设置`bootstrap=True`
- **优势**:
- 无需额外验证集
- 提供无偏估计
- **输出**:
- 通过`oob_score_`属性获取分数
- 适用于分类准确率/回归R²评分## 决策树共享参数
### `criterion` [默认'gini']
- **可选值**:
- 'gini':基尼不纯度
- 'entropy':信息增益
- **比较**:
| 指标 | 计算速度 | 对不平衡数据 | 分割倾向 |
|------|---------|------------|----------|
| 基尼 | 更快 | 更稳健 | 偏向多值特征 |
| 熵 | 稍慢 | 敏感 | 更平衡 |
- **实践选择**:
- 大多数情况下差异不大
- 计算资源有限时推荐gini### `max_depth` [默认None]
- **控制树复杂度**:
- None:完全生长直到满足停止条件
- 整数:限制最大深度
- **调优建议**:
- 从None开始,观察是否过拟合
- 常用值:3-15
- 深度越大模型越复杂### `min_samples_split` [默认2]
- **定义**:节点可分裂的最小样本数
- **格式**:
- 整数:绝对数量
- 浮点数:占总样本比例
- **示例**:
- min_samples_split=5:节点至少5个样本才分裂
- min_samples_split=0.1:至少10%样本### `min_samples_leaf` [默认1]
- **作用**:叶节点最小样本数
- **推荐值**:
- 分类:2-5
- 回归:3-10
- **防止过拟合**:
- 增大该值可使模型更保守
- 尤其适用于噪声数据## 辅助参数
### `n_jobs` [默认None]
- **并行控制**:
- None/1:单核运行
- -1:使用所有可用核
- >1:指定核数
- **注意**:
- 树构建过程可完全并行
- 内存充足时推荐设为-1### `random_state` [默认None]
- **用途**:
- 控制随机种子
- 确保结果可复现
- **建议**:
- 实验阶段设为固定值(如42)
- 生产环境可不设### `class_weight` [默认None]
- **处理类别不平衡**:
- None:各类权重相同
- 'balanced':自动调整权重
- 字典:手动指定{class_label: weight}
- **示例**:
```python
class_weight={0:1, 1:3} # 类别1的权重是类别0的3倍
五、实例
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
'''
集成学习
'''
def polt_matrix(x,y):#x:真实标签,y:测试标签(绘制混淆矩阵)
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
cm = confusion_matrix(x,y)
plt.matshow(cm,cmap=plt.cm.Blues)
plt.colorbar()
for i in range(len(cm)):
for j in range(len(cm)):
plt.annotate(cm[i][j], xy=(j,i), horizontalalignment='center', verticalalignment='center')
plt.ylabel('True label')
plt.xlabel('Predicted label')
return plt
data = pd.read_csv('spambase.csv')
x=data.iloc[:,:-1]
y=data.iloc[:,-1]
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = \
train_test_split(x, y, test_size=0.2, random_state=100)
rf = RandomForestClassifier(
n_estimators=200,# 决策树的个数
max_features=0.8,# 80%的特征,每个决策树学习到的特征数量
random_state=42,
)
rf.fit(x_train,y_train)
y_spred = rf.predict(x_train)
from sklearn import metrics
print(metrics.classification_report(y_train, y_spred,digits=9))
polt_matrix(y_train,y_spred).show()
#输出测试集测试报告
y_pred = rf.predict(x_test)
print(metrics.classification_report(y_test, y_pred,digits=9))
polt_matrix(y_test,y_pred).show()
im =pd.DataFrame(rf.feature_importances_,columns=['importance'])
clos = data.columns
clos_1 = clos.values
clos_2 = clos_1.tolist()
clos = clos_2[0:-1]
im['clos'] = clos
#根据重要性排序
im=im.sort_values(by='importance', ascending=False)[:30]
from pylab import mpl
from matplotlib import pyplot as plt
mpl.rcParams['font.sans-serif'] = ['Microsoft YaHei']
mpl.rcParams['axes.unicode_minus'] = False
m = range(len(im))
#重要性柱状图
plt.yticks(m,im['clos'])
plt.barh(im['clos'],im['importance'])
plt.title = '排名'
plt.xlabel = '特征'
plt.ylabel = '占比'
plt.show()

更多推荐
所有评论(0)