【问题标题】:How can you obtain same coefficients with different set.seed in elasticnet in R?如何在 R 中的 elasticnet 中获得具有不同 set.seed 的相同系数?
【发布时间】:2021-01-02 10:02:19
【问题描述】:

这个问题在 CrossValidation 被关闭,因为它专注于编程,所以这里更适合:

我正在对我的数据进行弹性网络逻辑回归。我研究了每次在相同数据上运行相同模型时如何获得可复制系数。但是,它似乎没有发生。我尝试设置nfolds 和foldid,但是一旦我更改set.seed,系数就会发生变化。

我了解交叉验证的工作原理以及set.seed 可能会如何改变整个过程。有些人建议像在我的代码中那样设置foldid,但是一旦set.seed 发生变化,它对我的​​情况就没有帮助。

每次运行获得相同系数或模型系数的统计合理测量的可能性有哪些?

df <- read_csv("data.csv")
View(df)

set.seed(123)
library(caret)
library(tidyverse)
library(glmnet)
library(ROCR)
library(doParallel)
registerDoParallel(4, cores = 4)
training.samples <- df$V1 %>% createDataPartition(p = 0.8, list = FALSE)
train <- df[training.samples, ]
test <- df[-training.samples, ]
x.train <- data.frame(train[, names(train) != "V1"])
x.train <- data.matrix(x.train)
y.train <- train$V1
x.test <- data.frame(test[, names(test) != "V1"])
x.test <- data.matrix(x.test)
y.test <- test$V1
foldid <- sample(rep(seq(10), length.out = nrow(train)))
 
list.of.fits <- list()
for (i in 0:10){
    fit.name <- paste0("alpha", i/10) 
    list.of.fits[[fit.name]] <- cv.glmnet(x.train, y.train, type.measure = "dev",
    alpha = i/10, family = "binomial", nfolds = 10, foldid = foldid, parallel = TRUE)
}
coef <- coef(list.of.fits[[fit.name]], s = list.of.fits[[fit.name]]$lambda.1se)
coef

我的输出结果如下:

set.seed(123)

(Intercept) -18.533050
V2          -0.0049142
V3          -0.0013228
V4          -0.0029664
V5           0.0123987
V6           0.1433817
V7           .           
V8          -0.0188888
V9           0.0007504
V10         -0.0626482
set.seed(42)

(Intercept) -22.16271709
V2          -0.005898701
V3          -0.001332854
V4          -0.003506514
V5           0.013343484
V6           0.097911065
V7          -0.269346185
V8          -0.024876785
V9           0.027937690
V10         -0.070759818

【问题讨论】:

    标签: r regression feature-selection glmnet


    【解决方案1】:

    有两种不同类型的再现性。一种是设置种子,以便可以为 cv.glmnet 获得相同的输出。这就是你所做的,设置种子,并提供折叠作为输入。因此,如果您使用相同的种子再次运行代码,它会得到相同的结果。

    在您的问题和示例中,您使用不同的交叉验证折叠运行它并使用 1se 提取系数。每次采样中每个 lambda 值的误差当然会有所不同,这就是交叉验证的目的,但您不会期望 lambda 差异太大。

    我们可以用一个示例数据集来看看这个:

    library(glmnet)
    library(mlbench)
    data(Sonar)
    set.seed(111)
    idx = sample(nrow(Sonar),150)
    x.train = as.matrix(Sonar[idx,1:60])
    y.train = as.numeric(Sonar$Class)[idx]
    x.test = as.matrix(Sonar[-idx,1:60])
    y.test = as.numeric(Sonar$Class)[-idx]
    

    使用 5 个不同的种子,1 个常数 alpha:

    o = lapply(1:5,function(i){
    set.seed(i)
    foldid <- sample(rep(seq(10), length.out = nrow(x.train)))
    fit = cv.glmnet(x.train, y.train, type.measure = "dev",
             alpha = 0.5, nfolds = 10, family="binomial",foldid = foldid)
    
    wh = which(fit$lambda==fit$lambda.1se)
    data.frame(seed=i,lambda = fit$lambda.1se,error = fit$cvm[wh],
               hi = fit$cvup[wh] , lo = fit$cvlo[wh])
    })
    

    看到 lambda 1 se 差别不大,还有报错:

    do.call(rbind,o)
      seed     lambda    error       hi       lo
    1    1 0.08047217 1.020349 1.071294 0.969404
    2    2 0.14062741 1.099030 1.148053 1.050007
    3    3 0.12813445 1.101091 1.160062 1.042121
    4    4 0.11675134 1.104327 1.165262 1.043392
    5    5 0.10637948 1.059930 1.114897 1.004962
    

    如果您的数据足够大,您会看到这些 lambda 和错误值越来越接近。因此,使用其中一个 lambda 表达式应该足以为您提供可以最小化错误的预测。

    【讨论】:

      猜你喜欢
      • 2021-10-20
      • 1970-01-01
      • 1970-01-01
      • 2021-05-08
      • 1970-01-01
      • 2021-10-10
      • 1970-01-01
      • 1970-01-01
      • 2021-07-13
      相关资源
      最近更新 更多