尽管交叉验证结果非常成功,但与随机森林过度拟合

Overfitting with random forest though very successful cross validation results

我在数据科学方面有一定的经验。我有一个包含 9500 个观察值和 4500 多个特征的数据集,其中大部分特征高度相关。以下是我尝试过的简要说明:我删除了少于 6000 个非 NA 的列,并在至少有 6000 个非 NA 时用相应列的中值估算了 NA。至于相关性,我只保留了与其他相关性最多为 0.7 的特征。通过这样做,我将特征数量减少到大约 750 个。然后我在随机森林的二元分类任务中使用了这些特征。

我的数据集高度不平衡,其中 (0:1) 的比率为 (10:1)。因此,当我应用具有 10 倍 cv 的 RF 时,我观察到每个 cv 的结果都太好了(AUC 为 99%),这好得令人难以置信,而在我的测试集中,我得到了更糟糕的结果,例如 0.7。这是我的代码:

import h2o
from h2o.estimators import H2ORandomForestEstimator

h2o.init(port=23, nthreads=4)

train = fs_rf[fs_rf['Year'] <= '201705']
test = fs_rf[fs_rf['Year'] > '201705']
train = train.drop('Year',axis=1)
test = test.drop('Year',axis=1)
test.head()

train = h2o.H2OFrame(train)
train['BestWorst2'] = train['BestWorst2'].asfactor()

test = h2o.H2OFrame(test)
test['BestWorst2'] = test['BestWorst2'].asfactor()

training_columns = train.drop('BestWorst2',axis=1).col_names
response_column = 'BestWorst2'

model = H2ORandomForestEstimator(ntrees=100, max_depth=20, nfolds=10, balance_classes=True)

model.train(x=training_columns, y=response_column, training_frame=train)

performance = model.model_performance(test_data=test)

print(performance)

如何避免这种过拟合?我在网格搜索中尝试了许多不同的参数,但 none 改进了结果。

这不是我所说的"overfitting"。与测试指标相比,您看到非常好的交叉验证指标的原因是您有时间序列数据,因此您不能使用 k 折交叉验证来准确估计性能。

对时间序列数据集执行 k 折交叉验证会给你过于乐观的性能指标,因为你没有尊重数据中的时间序列组件。常规的 k 折交叉验证将从您的整个数据集中随机抽样以创建训练和验证集。本质上,您的验证策略是 "cheating",因为您的 CV 训练集中包含 "future" 数据(如果这有意义的话)。

我可以从你的代码看出你明白你需要使用 "past" 数据进行训练并预测 "future" 数据,但如果你想阅读更多关于这个主题的信息,我会推荐这个 article or this article.

一种解决方案是简单地查看测试集性能作为评估模型的方式。另一种选择是使用所谓的 "rolling" 或 "time-series" 交叉验证,但 H2O 目前不支持它(尽管它似乎很快就会添加)。如果您想跟踪进度,这里有一个 ticket