使用 glmnet 进行变量选择(插入符号包)

机器算法验证 r 回归 网络
2022-03-21 06:40:41

这是进行变量/预测器/虚拟选择的合法方式吗?

(我的目标是使用选定的变量进行预测)

fit <- train(train.values ~ .,data=train.data, method='glmnet') # train.data includes all variables

#getting the coefficients of the final model
coefficients <- coef(fit$finalModel, fit$bestTune$lambda)

#create a list of the selected coefficients
variables <- names(coefficients[which(Coefficients != 0),])

由于在这个平台上阅读了很多东西,我知道stepAIC()对于变量选择来说这并不是一个很好的选择。完成变量选择后,我将使用这些变量进行 glmnet 预测以及线性模型。

2个回答

我读过学术论文,引用了使用 Lasso 进行变量选择的有效性,并亲自将其付诸实践。

以下代码块识别数据集中的特征。

require(glmnet)
##returns variables from lasso variable selection, use alpha=0 for ridge
ezlasso=function(df,yvar,folds=10,trace=F,alpha=1){
  x<-model.matrix(as.formula(paste(yvar,"~.")),data=df)
  x=x[,-1] ##remove intercept

  glmnet1<-glmnet::cv.glmnet(x=x,y=df[,yvar],type.measure='mse',nfolds=folds,alpha=alpha)

  co<-coef(glmnet1,s = "lambda.1se")
  inds<-which(co!=0)
  variables<-row.names(co)[inds]
  variables<-variables[!(variables %in% '(Intercept)')];
  return( c(yvar,variables));
}

(我不能 100% 相信这段代码,因为我确信它是从某个地方改编的——最有可能在这里:Using LASSO from lars (or glmnet) package in R for variable selection

在变量选择的主题上,我还发现 VIF(变量膨胀因子)是有效的,尤其是在交叉验证时。

require(VIF)
require(cvTools);
#returns selected variables using VIF and kfolds cross validation 
ezvif=function(df,yvar,folds=5,trace=F,ignore=c()){
  df=discard(df,ignore);
  f=cvFolds(nrow(df),K=folds);
  findings=list();
  for(v in names(df)){
    if(v==yvar)next;
    findings[[v]]=0; 
  }
  for(i in 1:folds){   
    if(trace) message("fold ",i);
    rows=f$subsets[f$which!=i] ##leave one out 
    y=df[rows,yvar];
    xdf=df[rows,names(df) != yvar]; #remove output var    
    if(trace) say("trying ",i,yvar,nrow(df),length(y)," subsize=",min(200,floor(nrow(xdf))));
    vifResult=vif(y,xdf,trace=trace,subsize=min(200,floor(nrow(xdf))))
    if(trace) print(names(xdf)[vifResult$select]);
    for(v in names(xdf)[vifResult$select]){
      findings[[v]]=findings[[v]]+1; #vote
    }
  }
  findings=(sort(unlist(findings),decreasing = T))    
  if(trace) print(findings[findings>0]); 
  return( c(yvar,names(findings[findings==findings[1]])) )  
}

上述两个 ez 函数都返回一个变量名向量。以下代码块将返回值转换为公式。

#converts ezvif or ezlasso results into formula
ezformula=function(v,operator=' + '){
  return(as.formula(paste(v[1],'~',paste(v[-1],collapse = operator))))
}

我希望这是有帮助的。

您在这里尝试做的是识别其中最“重要”的变量glmnet,然后尝试将您的功能传递给另一个模型。正如 Max Kuhn 在这里所写的那样,这并不是最优的

在许多情况下,使用这些具有内置特征选择的模型将比在模型外部搜索正确预测变量的算法更有效。内置特征选择通常将预测器搜索算法与参数估计结合起来,并且通常使用单个目标函数(例如错误率或似然度)进行优化。

从理论的角度来看:不同的模型允许不同程度的灵活性和防止过拟合。为什么要在另一个模型中使用来自一个模型的一组最佳参数?

glmnet如果您被迫使用线性回归并且您拥有广泛的特征矩阵(特征多于案例),我能想到的唯一场景是用作特征过滤器。这没有什么问题,只是结果(RMSE,R^2)可能不是最理想的。