R 交叉验证的意外结果
我想使用R 交叉验证的意外结果,r,cross-validation,glmnet,lasso-regression,R,Cross Validation,Glmnet,Lasso Regression,我想使用前列腺数据手动执行10倍交叉验证,以了解如何手动执行。我使用elasticnet包进行编码。我通过glmnet包估计了参数(当然,它也可以执行交叉验证,但我希望手动执行)。在分析之后,在我看来,我需要一个不同的标准来选择调整参数,而不是cv.error的最小值,因为这会给出几乎为零的模型,如果不是这样,“我的错误在哪里?”。(根据Tibshirani的原始论文,优化模型有三个变量) 这是密码 library(ElemStatLearn) library(glmnet) x <-
前列腺数据
手动执行10倍交叉验证,以了解如何手动执行。我使用elasticnet
包进行编码。我通过glmnet包估计了参数(当然,它也可以执行交叉验证,但我希望手动执行)。在分析之后,在我看来,我需要一个不同的标准来选择调整参数,而不是cv.error的最小值,因为这会给出几乎为零的模型,如果不是这样,“我的错误在哪里?”。(根据Tibshirani的原始论文,优化模型有三个变量)
这是密码
library(ElemStatLearn)
library(glmnet)
x <- scale(prostate[,1:8],T,T)
y <- scale(prostate[,9],T,F)
lambda = seq(0,1,0.02)
cv.folds <- function(n, folds = 10){
split(sample(1:n), rep(1:folds, length = n))
}
c.val <- function(x, y, K = 10, lambda, plot.it = TRUE){
n <- nrow(x)
all.folds <- cv.folds(length(y), K)
residmat <- matrix(0, length(lambda), K)
for(i in seq(K)) {
omit <- all.folds[[i]]
xk <- as.matrix(x[-omit, ])
yk <- as.vector(y[-omit])
xg <- x[omit, ]
yg <- y[omit]
fit <- glmnet(xk, yk, family="gaussian",
alpha=1, lambda=lambda,standardize = FALSE, intercept = FALSE)
fit <- predict(fit,newx=xg,lambda=lambda)
if(length(omit)==1){fit<-matrix(fit,nrow=1)}
residmat[, i] <- apply((yg - fit)^2, 2, mean)
}
cv <- apply(residmat, 1, mean)
cv.error <- sqrt(apply(residmat, 1, var)/K)
object<-list(lambda = lambda, cv = cv, cv.error = cv.error)
if(plot.it) {
plot(lambda, cv, type = "b", xlab="lambda", ylim = range(cv, cv + cv.error, cv - cv.error))
invisible(object)
}
}
result <- c.val(x,y,K = 10,lambda = lambda)
lambda.opt <- lambda[which.min(result$cv.error)]
fit <- glmnet(x, y, family="gaussian",
alpha=1, lambda=lambda.opt,standardize = FALSE, intercept = FALSE)
coef(fit)
编辑:
直接从glmnet
生成的模型
fit.lasso <- glmnet(x, y, family="gaussian", alpha=1,
standardize = FALSE, intercept = FALSE)
fit.lasso.cv <- cv.glmnet(x, y, type.measure="mse", alpha=1,
family="gaussian",standardize = FALSE, intercept = FALSE)
coef.lambda.min <- coef(fit.lasso.cv,s=fit.lasso.cv$lambda.min)
coef.lambda.1se <- coef(fit.lasso.cv,s=fit.lasso.cv$lambda.1se)
cbind(coef.lambda.min,coef.lambda.1se)
第二列显示了正确的(lambda.1se
)结果。您的“错误”很难发现:这是因为glmnet
不会使用您自己的lambda
向量的顺序对结果向量进行排序
您使用的数据示例:
res <- glmnet(x, y, lambda=lambda)
res$lambda
最后一句话:使用单个lambda时要小心。当我运行代码时,我得到一个奇怪的lambda最佳值(~0.98)。此外,我认为所谓的“lambda最佳值”实际上并不对应于最佳MSE,而是“lambda的最大值,以便误差在最小值的1个标准误差范围内。”我按照你的建议编辑了代码。结果似乎仍然不正确。我通过完全
glmnet
添加生成正确模型的代码。但是,正如我们所看到的,lambda.min
生成的模型比理论上预期的lambda1se
模型具有更多的变量。我想我看到了我的错误。问题源于cv
和cv.error
的定义。非常感谢您抽出时间。
9 x 2 sparse Matrix of class "dgCMatrix"
1 1
(Intercept) . .
lcavol 0.59892674 0.5286355
lweight 0.23669159 0.1201279
age -0.06979581 .
lbph 0.09392021 .
svi 0.24620007 0.1400748
lcp . .
gleason 0.00346421 .
pgg45 0.06631013 .
res <- glmnet(x, y, lambda=lambda)
res$lambda
lambda = seq(1, 0, 0.02)