线性回归在插入符号中的表现优于随机森林

机器算法验证 回归 机器学习 神经网络 随机森林
2022-03-27 01:31:59

我正在处理相当高维数据(光谱数据),我使用 PCA 对其进行预处理,然后应用所选的学习算法。当我使用线性回归时,使用 Caret 包,我得到一个R2=0.83然而,在我的 300 个 PCA 组件的测试集上,当我在同一集上使用随机森林时:

modelFit <- train(train$age~.,data=trainPC[,1:300],method = "rf")

我的表现更差,与R2在测试集上要低得多。RMSE 对于随机森林与线性回归也没有那么好。

为清楚起见 - 我正在使用 Caret 的内置交叉验证,并正在评估独立测试集的性能。

当我使用xgboost、神经网络等时,我得到了类似的结果。我知道不同的机器学习算法在不同的情况下可以表现得更好,但我仍然对线性回归似乎表现最好感到惊讶,这让我怀疑我正在接近事情不正确,或使用 Caret 包时出现基本错误。

我也尝试过使用 PLS(用于我的特定示例的主要特征选择方法)并得到一个R2=0.83. 文献表明神经网络/非线性方法应该优于我正在使用的线性方法,但目前,我无法重现这一点。

有人对此有任何建议/提示吗?我还附上了我正在使用的数据集(我正在尝试预测年龄) -数据链接

我还附上了我当前用于学习的 R 脚本 - 任何帮助将不胜感激!- R 脚本

2个回答

一定要检查如何R2正在评估中,以及它在不同算法之间是否一致。除此之外,我想到了一些想法:

  • 如果您的特征对协变量具有平滑的、近乎线性的依赖关系,那么线性回归将比随机森林更好地模拟依赖关系,随机森林基本上会逼近一条带有丑陋不规则阶跃函数的线性曲线。如果相关性是多元线性且平滑的,则v显着的协变量产生依赖性,随机森林的拟合性能可以预期会随着越来越大而变得越来越差v. RF 比单个决策树具有更大的线性建模能力,因为我们将树预测加在一起 ​​- 但是,用一系列阶跃函数来近似高维线性关系并不是很有效。我认为这是 RF 表现不佳的线性回归最有可能的理论解释。

  • ...也就是说,随着您向随机森林添加更多树,步进函数会变得更好。因此,您可能需要考虑大量增加树的数量——只要您愿意等待即可。也许看看插入符号是否允许您跟踪R2随着树木数量的增加?我还希望增强的树在这里可能会很好地工作,但是您可能必须适应大量的树并摆弄很多参数。但不能保证——如果这是一个真正的高维平滑关系,可能需要大量的树才能很好地近似它。

  • 对于像随机森林这样的高维学习器,使用 PCA 进行预处理并不理想。为了获得最佳结果,他们通常应该直接访问完整的数据集。如果原始数据集具有稀疏的主效应,那么这个很好的属性很容易被 PCA 破坏。这将使我的第一个项目符号的问题变得更糟,其中 RF 试图通过阶跃函数来近似高维线性关系。

  • 先进的机器学习算法因其泛化性能而受到青睐,而不是它们紧密拟合训练数据并产生高R2. 您正在执行一个有趣的诊断,这是值得做的,但请注意,此诊断并不是衡量最终性能的好方法。

  • 随机森林并不是高维数据唯一有用的算法。您还可以在 PCA 处理的数据或原始数据集上尝试弹性网络回归。弹性网络使您能够建模平滑关系,以及使用1回归系数惩罚。

检查插入符号的功能findLinearCombos并在您的数据上运行它。返回的对象是一个列表——第二个元素是一个索引向量,可以安全地从您的数据集中删除,因为它们是其他列的线性组合(现在我认为它完全有意义,因为您只有 500观察结果,因此您的模型完全被过度指定了)。

当您传入数据框时,生成的向量有一千个元素基本上,您可以直接删除第 501 到 1500 列。

从一开始就这样做,并尝试重新构建这些模型。


几个快速的旁注:

  • 如果包含“数据”参数,则仅在公式中按列名称引用列(即写age ~.而不是data$age ~.)。
  • 如果您打算进行PCA,那么您可能需要考虑通过函数中的preProcess参数进行设置train(您可以调整函数中的阈值trainControl)。(既然您已经在使用克拉,您也不妨让它处理您的预处理——它让您少担心一件事)。

顺便说一句,试着检查一下这段代码。

prepped <- preProcess(x=df[, -1], method=c('center', 'scale', 'pca'), 
                      thresh=0.9999)
pca <- predict(prepped, df[, -1])
pca$age <- df$age
fit <- ln(age ~ ., data=pca)

num.unique <- length(unique(df$age))

cols <- rainbow(num.unique)[factor(df$age)]

plot(fit, col=cols)