【问题标题】:Why calculating MSE in lasso regression gives different outputs?为什么在 lasso 回归中计算 MSE 会给出不同的输出?
【发布时间】:2017-01-21 18:53:51
【问题描述】:

我正在尝试对来自 lasso2 包的前列腺癌数据运行不同的回归模型。当我使用 Lasso 时,我看到了两种不同的方法来计算均方误差。但是它们确实给了我完全不同的结果,所以我想知道我是否做错了什么,或者这是否意味着一种方法比另一种更好?

# Needs the following R packages.
library(lasso2)
library(glmnet)

# Gets the prostate cancer dataset
data(Prostate)

# Defines the Mean Square Error function 
mse = function(x,y) { mean((x-y)^2)}

# 75% of the sample size.
smp_size = floor(0.75 * nrow(Prostate))

# Sets the seed to make the partition reproductible.
set.seed(907)
train_ind = sample(seq_len(nrow(Prostate)), size = smp_size)

# Training set
train = Prostate[train_ind, ]

# Test set
test = Prostate[-train_ind, ]

# Creates matrices for independent and dependent variables.
xtrain = model.matrix(lpsa~. -1, data = train)
ytrain = train$lpsa
xtest = model.matrix(lpsa~. -1, data = test)
ytest = test$lpsa

# Fitting a linear model by Lasso regression on the "train" data set
pr.lasso = cv.glmnet(xtrain,ytrain,type.measure='mse',alpha=1)
lambda.lasso = pr.lasso$lambda.min

# Getting predictions on the "test" data set and calculating the mean     square error
lasso.pred = predict(pr.lasso, s = lambda.lasso, newx = xtest) 

# Calculating MSE via the mse function defined above
mse.1 = mse(lasso.pred,ytest)
cat("MSE (method 1): ", mse.1, "\n")

# Calculating MSE via the cvm attribute inside the pr.lasso object
mse.2 = pr.lasso$cvm[pr.lasso$lambda == lambda.lasso]
cat("MSE (method 2): ", mse.2, "\n")

所以这些是我为两个 MSE 得到的输出:

MSE (method 1): 0.4609978 
MSE (method 2): 0.5654089 

而且它们完全不同。有谁知道为什么? 非常感谢您的帮助!

塞缪尔

【问题讨论】:

  • 如果我没看错的话,mse.1 是测试 MSE,mse.2 是所选模型的交叉验证错误——但仅基于训练数据。
  • 感谢您指出这一点。所以正确的顺序是在训练数据上运行 cv.glmnet 以获得最佳 lambda,然后对 MSE 使用方法 1?我认为在测试数据上第二次重新运行 cv.glmnet 以获取 cvm(平均交叉验证错误)没有意义?对不起,我有点困惑。
  • 您使用交叉验证来估计测试错误,以便确定在测试数据上使用哪个 lambda 值。您应该只触摸一次测试数据。
  • @alistaire 谢谢!所以我可以放弃第二种方法,它实际上没有意义。

标签: r machine-learning glmnet lasso-regression mean-square-error


【解决方案1】:

正如@alistaire 所指出的,在第一种情况下,您使用测试数据来计算 MSE,在第二种情况下,报告来自交叉验证(训练)折叠的 MSE,所以这不是苹果对苹果比较。

我们可以执行以下类似的操作来进行苹果与苹果的比较(通过保持训练折叠上的拟合值),我们可以看到如果在相同的训练折叠上计算,mse.1 和 mse.2 完全相等(虽然值和你的差别不大,但我的桌面 R 版本是 3.1.2,x86_64-w64-mingw32,windows 10):

# Needs the following R packages.
library(lasso2)
library(glmnet)

# Gets the prostate cancer dataset
data(Prostate)

# Defines the Mean Square Error function 
mse = function(x,y) { mean((x-y)^2)}

# 75% of the sample size.
smp_size = floor(0.75 * nrow(Prostate))

# Sets the seed to make the partition reproductible.
set.seed(907)
train_ind = sample(seq_len(nrow(Prostate)), size = smp_size)

# Training set
train = Prostate[train_ind, ]

# Test set
test = Prostate[-train_ind, ]

# Creates matrices for independent and dependent variables.
xtrain = model.matrix(lpsa~. -1, data = train)
ytrain = train$lpsa
xtest = model.matrix(lpsa~. -1, data = test)
ytest = test$lpsa

# Fitting a linear model by Lasso regression on the "train" data set
# keep the fitted values on the training folds
pr.lasso = cv.glmnet(xtrain,ytrain,type.measure='mse', keep=TRUE, alpha=1)
lambda.lasso = pr.lasso$lambda.min
lambda.id <- which(pr.lasso$lambda == pr.lasso$lambda.min)

# get the predicted values on the training folds with lambda.min (not from test data)
mse.1 = mse(pr.lasso$fit[,lambda.id], ytrain) 
cat("MSE (method 1): ", mse.1, "\n")

MSE (method 1):  0.6044496 

# Calculating MSE via the cvm attribute inside the pr.lasso object
mse.2 = pr.lasso$cvm[pr.lasso$lambda == lambda.lasso]
cat("MSE (method 2): ", mse.2, "\n")

MSE (method 2):  0.6044496 

mse.1 == mse.2
[1] TRUE

【讨论】:

  • 感谢您的回答@sandipan。所以 cv.glmnet 默认使用 10 倍。通过指定更多的折叠数,是否意味着交叉验证的结果会更好?
  • 折叠次数越多可能会导致过度拟合,因为您需要训练更多数据。
  • 好的,所以最好保留默认值 K = 10 ?或者有没有办法找到最佳折叠数?
  • 非常感谢您的链接!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-30
  • 1970-01-01
  • 1970-01-01
  • 2014-02-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多