Day 9 :随机森林调参与时间序列交叉验证

Day 9 :随机森林调参与时间序列交叉验证

📋 目录

  1. 随机森林核心超参数详解
  2. 超参数对模型的影响
  3. 调参策略与顺序
  4. 时间序列交叉验证
  5. 网格搜索与随机搜索
  6. 学习曲线与验证曲线
  7. 过拟合诊断

第一部分:随机森林核心超参数详解(1.5小时理论)

1.1 超参数分类

类别 参数 作用 影响
模型复杂度 n_estimators 树的数量 越多越稳定
树结构 max_depth 最大深度 控制过拟合
分裂条件 min_samples_split 分裂最小样本数 正则化
叶节点 min_samples_leaf 叶节点最小样本数 平滑预测
特征选择 max_features 特征子集大小 增加多样性
采样 bootstrap 是否自助采样 通常为True

1.2 n_estimators(树的数量)

定义:随机森林中决策树的数量。

原理:

  • 每棵树独立训练,通过投票/平均得到最终结果
  • 根据大数定律,树越多,方差越小

数学性质 :
Error=Bias2+Variance+Noise \text{Error} = \text{Bias}^2 + \text{Variance} + \text{Noise} Error=Bias2+Variance+Noise

增加 n_estimators 主要降低方差,不影响偏差。

参数影响:

n_estimators 训练时间 预测时间 内存 性能
太少(<50) 快 快 小 不稳定
适中(100-200) 中等 中等 中等 良好
太多(>500) 慢 慢 大 边际收益递减

选择策略:

python 复制代码
# 观察OOB误差随n_estimators的变化
oob_scores = []
for n in range(10, 301, 10):
    rf = RandomForestClassifier(n_estimators=n, oob_score=True)
    rf.fit(X_train, y_train)
    oob_scores.append(rf.oob_score_)
# 选择OOB误差收敛时的n_estimators

1.3 max_depth(最大深度)

定义:每棵树的最大深度。

原理:

  • 深度越大,树越复杂,越容易过拟合
  • 限制深度是最直接的正则化方法

参数影响:

max_depth 模型复杂度 过拟合风险 训练时间
小(3-5) 低 低 快
中(10-20) 中 中 中等
大(None) 高 高 慢

选择策略:

python 复制代码
# 观察不同深度下的训练/测试误差
depths = range(3, 31, 3)
train_scores, test_scores = [], []
for depth in depths:
    rf = RandomForestClassifier(max_depth=depth)
    rf.fit(X_train, y_train)
    train_scores.append(rf.score(X_train, y_train))
    test_scores.append(rf.score(X_test, y_test))
# 选择测试误差最低的深度

1.4 min_samples_split(分裂最小样本数)

定义:内部节点再划分所需的最小样本数。

原理:

  • 值越大,树越难分裂,模型越简单
  • 防止模型学习局部噪声

参数影响:

min_samples_split 分裂次数 树大小 过拟合风险
小(2) 多 大 高
中(5-20) 中 中 中
大(>50) 少 小 低

选择策略:

python 复制代码
# 从小值开始,逐步增加
min_samples_split_values = [2, 5, 10, 20, 50, 100]

1.5 min_samples_leaf(叶节点最小样本数)

定义:叶节点所需的最小样本数。

原理:

  • 与min_samples_split类似,但作用于叶节点
  • 确保每个叶节点有足够样本,避免过拟合

与min_samples_split的区别:

参数 作用节点 对树的影响
min_samples_split 内部节点 限制分裂
min_samples_leaf 叶节点 限制叶节点大小

1.6 max_features(特征子集大小)

定义:每次分裂时随机选择的特征数量。

原理:

  • 增加树的多样性
  • 防止强特征主导所有树

常用设置:

任务 推荐值 说明
分类 sqrt(n_features) 默认值
回归 n_features/3 默认值
特征少 None 使用所有特征
高维数据 log2(n_features) 增加随机性

第二部分:超参数对模型的影响

2.1 单个参数的影响分析

python 复制代码
# 参数影响矩阵
# 
#          欠拟合 ←──────────────→ 过拟合
# 
# n_estimators:   小 ←→ 大
# max_depth:      小 ←→ 大
# min_samples_split: 大 ←→ 小
# min_samples_leaf:  大 ←→ 小
# max_features:   小 ←→ 大

2.2 参数交互作用

参数组合 效果
max_depth小 + min_samples_split大 强正则化,可能欠拟合
max_depth大 + min_samples_split小 弱正则化,可能过拟合
n_estimators大 + max_depth小 稳定且不易过拟合

2.3 偏差-方差权衡

text 复制代码
高偏差(欠拟合)          最优              高方差(过拟合)
     ←─────────────────────────────────────────→
     
增加 max_depth ────────────────────────────────→
增加 n_estimators ────────────────────────────→
增加 min_samples_split ←───────────────────────
增加 min_samples_leaf ←───────────────────────

第三部分:调参策略与顺序

3.1 推荐调参顺序

text 复制代码
第1步: 固定其他参数,确定 n_estimators
       └── 观察OOB误差收敛点

第2步: 调整 max_depth
       └── 找到最佳深度范围

第3步: 调整 min_samples_split 和 min_samples_leaf
       └── 进一步正则化

第4步: 调整 max_features
       └── 微调特征随机性

第5步: 联合调优
       └── 使用网格搜索/随机搜索

3.2 粗调 vs 精调

阶段 参数范围 步长 目的
粗调 大范围 大 找到最优区域
精调 小范围 小 找到最优值

3.3 调参注意事项

  1. 避免数据泄露:只用训练集调参
  2. 使用交叉验证:评估泛化能力
  3. 记录实验:保存每次调参结果
  4. 关注边际收益:性能提升不明显时停止

第四部分:时间序列交叉验证

4.1 为什么不能用普通K折?

普通K折的问题:

  • 随机打乱数据,破坏时间顺序
  • 用未来数据训练,过去数据验证(前视偏差)
python 复制代码
# 错误做法 ❌
from sklearn.model_selection import KFold
kf = KFold(n_splits=5, shuffle=True)  # 随机打乱

4.2 TimeSeriesSplit原理

工作方式:

text 复制代码
Fold 1: Train [0:100]  | Test [100:120]
Fold 2: Train [0:120]  | Test [120:140]
Fold 3: Train [0:140]  | Test [140:160]
Fold 4: Train [0:160]  | Test [160:180]
Fold 5: Train [0:180]  | Test [180:200]

特点:

  • 训练集始终在测试集之前
  • 测试集不重叠
  • 训练集大小递增
python 复制代码
# 正确做法 ✅
from sklearn.model_selection import TimeSeriesSplit
tscv = TimeSeriesSplit(n_splits=5)

4.3 TimeSeriesSplit参数

参数 说明 默认值
n_splits 分割次数 5
max_train_size 最大训练集大小 None
test_size 测试集大小 None
gap 训练集和测试集之间的间隔 0

4.4 带间隔的TimeSeriesSplit

python 复制代码
# 防止数据泄露,设置间隔
tscv = TimeSeriesSplit(n_splits=5, gap=5)  # 训练集和测试集间隔5天

# 示意:
# Fold 1: Train [0:100]  | Gap [100:105] | Test [105:125]

4.5 时间序列交叉验证的变体

变体 描述 适用场景
滚动窗口 固定窗口大小 非平稳数据
扩展窗口 窗口不断增大 数据量小
带间隔 防止短期依赖 高频数据

第五部分:网格搜索与随机搜索

5.1 GridSearchCV(网格搜索)

原理:遍历所有参数组合,找到最佳参数。

python 复制代码
from sklearn.model_selection import GridSearchCV

param_grid = {
    'max_depth': [10, 20, 30],
    'min_samples_split': [2, 5, 10]
}
# 总共 3×3 = 9 种组合

grid_search = GridSearchCV(rf, param_grid, cv=5)
grid_search.fit(X_train, y_train)

优点 :保证找到最优组合
缺点:计算量大(组合爆炸)

5.2 RandomizedSearchCV(随机搜索)

原理:随机采样参数组合,而非遍历。

python 复制代码
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import randint

param_dist = {
    'max_depth': randint(10, 50),
    'min_samples_split': randint(2, 20)
}
# 可以指定n_iter控制搜索次数

random_search = RandomizedSearchCV(rf, param_dist, n_iter=20, cv=5)

优点 :效率高,适合大参数空间
缺点:可能错过最优组合

5.3 搜索策略选择

场景 推荐方法
参数少(<10种组合) GridSearchCV
参数多(>50种组合) RandomizedSearchCV
参数连续分布 RandomizedSearchCV
追求最优 GridSearchCV + 分步搜索

5.4 分步搜索策略

python 复制代码
# 第1步:粗调,大范围
param_grid1 = {'max_depth': [5, 10, 20, 30, None]}

# 第2步:精调,小范围
param_grid2 = {'max_depth': [10, 12, 14, 16, 18, 20]}

# 第3步:联合调优
param_grid3 = {
    'max_depth': [12, 14, 16],
    'min_samples_split': [2, 4, 6, 8]
}

第六部分:学习曲线与验证曲线

6.1 学习曲线(Learning Curve)

定义:展示模型性能随训练集大小的变化。

作用:

  • 判断欠拟合/过拟合
  • 判断增加数据的收益

解读:

text 复制代码
训练误差高,验证误差高 → 欠拟合
训练误差低,验证误差高 → 过拟合
两者都低且接近 → 良好拟合

6.2 验证曲线(Validation Curve)

定义:展示模型性能随单个参数的变化。

作用:

  • 找到参数的最佳范围
  • 观察参数对过拟合的影响
python 复制代码
from sklearn.model_selection import validation_curve

train_scores, test_scores = validation_curve(
    rf, X_train, y_train,
    param_name='max_depth',
    param_range=[3, 5, 10, 15, 20, 30],
    cv=5
)

6.3 学习曲线 vs 验证曲线

曲线类型 X轴 目的
学习曲线 训练集大小 判断数据需求
验证曲线 参数值 判断参数影响

第七部分:过拟合诊断

7.1 诊断方法

方法 指标 过拟合信号
训练vs测试误差 准确率差 训练>>测试
OOB评分 OOB vs 测试 OOB低于测试
学习曲线 误差差距 差距随数据增大
验证曲线 参数影响 复杂度过高

7.2 过拟合应对策略

  1. 增加正则化 :
    • 减小max_depth
    • 增大min_samples_split
    • 增大min_samples_leaf
  2. 增加数据 :
    • 收集更多历史数据
    • 数据增强
  3. 减少特征 :
    • 特征选择
    • 降维(PCA)
  4. 降低模型复杂度 :
    • 减少n_estimators(边际效应)
    • 减小max_features
相关推荐
ZhengEnCi6 小时前
Agent 架构怎么选:从单 Agent 到多 Agent 编排的选型决策指南
算法·架构
秋天的怀念_David6 小时前
第二十二夜 · 数字迷雾
java·程序人生·算法
Zzj_tju7 小时前
准确率不变,概率质量也不变吗?
人工智能·深度学习·机器学习·语言模型
Pniubi7 小时前
力扣283移动零(双指针法)
算法·leetcode·职场和发展
hhb_6187 小时前
大模型落地三重优化实战
人工智能·算法·机器学习
云和数据.ChenGuang7 小时前
光哥说Python RAG 系统需要哪些评估指标:从检索到生成的全链路评测指南
网络·人工智能·python·算法·langchain
Zzj_tju8 小时前
长期记忆让智能体更可靠,还是让错误持续累积?
人工智能·机器学习·语言模型·自然语言处理
在所不辞兄9 小时前
【零基础学智能仿真-67】力学知识库与检索增强
人工智能·深度学习·神经网络·机器学习·智能仿真
2601_970703839 小时前
工业除湿机租赁:把一份租金合同拆开看
大数据·数据结构·算法·数据库架构·推荐算法
心中有你02149 小时前
Java实现Dijkstra最短路径算法(邻接表 + 优先队列)
java·数据库·算法