【问题标题】:PCA for dimensionality reduction before Random ForestPCA 用于随机森林之前的降维
【发布时间】:2015-11-07 23:03:14
【问题描述】:

我正在研究具有大约 4500 个变量的二元类随机森林。其中许多变量是高度相关的,其中一些只是原始变量的分位数。我不太确定应用 PCA 进行降维是否明智。这会提高模型性能吗?

我希望能够知道哪些变量对我的模型更重要,但如果我使用 PCA,我只能知道哪些 PC 更重要。

非常感谢。

【问题讨论】:

标签: pca random-forest dimensionality-reduction


【解决方案1】:

我的经验是,RF 之前的 PCA 并不是一个很大的优势,如果有的话。主成分回归(PCR)是例如什么时候,PCA 有助于在 OLS 线性回归之前对训练特征进行正则化,这对于稀疏数据集是非常需要的。由于 RF 本身已经在不假设线性的情况下执行了良好/公平的正则化,因此它不一定是优势。也就是说,我发现自己在两周前为 R 编写了一个 PCA-RF 包装器。该代码包括一个由 100 个特征组成的数据集的模拟数据集,该数据集仅包含 5 个真正的线性分量。在这种情况下,使用 PCA 进行预过滤实际上是一个小优势 该代码是一个无缝实现,因此每个 RF 参数都可以简单地传递给 RF。加载向量保存在 model_fit 中以供预测期间使用。

@我希望能够知道哪些变量对我的模型更重要,但如果我使用 PCA,我只能知道哪些 PC 更重要。

简单的方法是在没有 PCA 的情况下运行并获得可变重要性,并期望找到与 PCA-RF 类似的东西。

繁琐的方法是使用您自己的可变重要性代码将 PCA-RF 包装在一个新的 bagging 方案中。可以在 50-100 行左右完成。

PCA-RF 的源代码建议:

#wrap PCA around randomForest, forward any other arguments to randomForest
#define as new S3 model class
train_PCA_RF = function(x,y,ncomp=5,...) {
  f.args=as.list(match.call()[-1])
  pca_obj = princomp(x)
  rf_obj = do.call(randomForest,c(alist(x=pca_obj$scores[,1:ncomp]),f.args[-1]))
  out=mget(ls())
  class(out) = "PCA_RF"
  return(out)    
}

#print method
print.PCA_RF = function(object) print(object$rf_obj)

#predict method
predict.PCA_RF = function(object,Xtest=NULL,...) {
  print("predicting PCA_RF")
  f.args=as.list(match.call()[-1])
  if(is.null(f.args$Xtest)) stop("cannot predict without newdata parameter")
  sXtest = predict(object$pca_obj,Xtest) #scale Xtest as Xtrain was scaled before
  return(do.call(predict,c(alist(object = object$rf_obj, #class(x)="randomForest" invokes method predict.randomForest
                                 newdata = sXtest),      #newdata input, see help(predict.randomForest)
                                 f.args[-1:-2])))  #any other parameters are passed to predict.randomForest

}

#testTrain predict #
make.component.data = function(
  inter.component.variance = .9,
  n.real.components = 5,
  nVar.per.component = 20,
  nObs=600,
  noise.factor=.2,
  hidden.function = function(x) apply(x,1,mean),
  plot_PCA =T
){
  Sigma=matrix(inter.component.variance,
               ncol=nVar.per.component,
               nrow=nVar.per.component)
  diag(Sigma)  = 1
  x = do.call(cbind,replicate(n = n.real.components,
                              expr = {mvrnorm(n=nObs,
                                              mu=rep(0,nVar.per.component),
                                              Sigma=Sigma)},
                              simplify = FALSE)
            )
  if(plot_PCA) plot(prcomp(x,center=T,.scale=T))
  y = hidden.function(x)
  ynoised = y + rnorm(nObs,sd=sd(y)) * noise.factor
  out = list(x=x,y=ynoised)
  pars = ls()[!ls() %in% c("x","y","Sigma")]
  attr(out,"pars") = mget(pars) #attach all pars as attributes
  return(out)
}

运行代码示例:

#start script------------------------------
#source above from separate script
#test
library(MASS)
library(randomForest)

Data = make.component.data(nObs=600)#plots PC variance
train = list(x=Data$x[  1:300,],y=Data$y[1:300])
test = list(x=Data$x[301:600,],y=Data$y[301:600])

rf = randomForest (train$x, train$y,ntree =50) #regular RF
rf2 = train_PCA_RF(train$x, train$y,ntree= 50,ncomp=12)

rf
rf2


pred_rf = predict(rf  ,test$x)
pred_rf2 = predict(rf2,test$x)

cat("rf, R^2:",cor(test$y,pred_rf  )^2,"PCA_RF, R^2", cor(test$y,pred_rf2)^2)

cor(test$y,predict(rf ,test$x))^2
cor(test$y,predict(rf2,test$x))^2

pairs(list(trueY = test$y,
           native_rf = pred_rf,
           PCA_RF = pred_rf2)
)

【讨论】:

  • 上面的代码不会运行 > is.data.frame(y) 中的错误:找不到对象'pred_rf' 你忘记包含对象pred_rf和pred_rf2的来源了吗?
  • 通过将 cat() 向下移动几行,直到分配了变量 pred_rf 和 pred_rf2 来修复错误
  • 谢谢。你介意看看这个问题stackoverflow.com/questions/69727955/…
【解决方案2】:

您可以在这里查看以获得更好的想法。 link 表示将 PCA 用于较小的数据集!!在使用 Genomes 时,我的一些同事出于同样的目的使用了随机森林。他们有大约 30000 个变量和大量 RAM。

我发现的另一件事是随机森林use up a lot of Memory,你有 4500 个变量。那么,您是否可以将 PCA 应用于单个树。

【讨论】:

    猜你喜欢
    • 2019-07-20
    • 2015-09-16
    • 2020-08-16
    • 2017-05-03
    • 2015-09-16
    • 2017-03-15
    • 1970-01-01
    • 2018-05-18
    • 2015-07-30
    相关资源
    最近更新 更多