如何制作一个函数来对线性模型进行 K 折交叉验证?
How can I make a function that does K-fold cross validation for linear models?
我正在尝试开发一个对任何线性回归模型进行 k 折交叉验证的函数。我能够开发下面的代码
K.CV.2<-function(numberOfFolds, inputData){
index <- sample(1:numberOfFolds, nrow(inputData), replace = T)
inputData$index <- index
mse.all <- c()
for (n in 1:numberOfFolds) {
training.data <- inputData[inputData$index!=n,]
testing.data <- inputData[inputData$index==n,]
model.hold <- lm(earn~height+sex+race+ed, data = training.data)
predictions <- predict(model.hold, newdata=testing.data)
mse.hold <- mean((testing.data$earn-predictions)^2)
mse.all <- c(mse.all,mse.hold)
}
return(mse.all)
}
K.CV.2(numberOfFolds, Inputdata)
我对这个功能不满意,因为我试图让它更通用。我想要 function(numberOfFolds, y, x, InputData)
我希望能够使用 c()
函数传递 y
变量的列以及我将在 x
中用作解释变量的所有其他列。
有人可以 help/guide 我在正确的方向吗?
我猜是这样的。一些注意事项:
- 提供示例数据会更容易提供帮助。我已经为这个案例生成了一些虚假数据,但以后要记住一些事情。一般来说,我强烈建议您练习模拟数据来测试您的模型和假设。
- 不要使用
T
。它不是保留值。您可以在脚本中编写 T <- FALSE
,结果可想而知。
- 直接传入您要使用的
x
和y
会更容易。这就是我在这里所做的。然后,您可以遍历数据帧并传入子集 x
和您想要的任何 y
,但它使 CV 函数更清晰。
- 除非绝对必要,否则不要增加对象。参见 the R inferno book。
- 最好避免在代码中使用
1:n
。如果 n
为零,它会创建向量 c(1, 0)
,这通常会导致意外结果。
npred <- 10
nobs <- 100
mat <- matrix(rnorm(npred * nobs), ncol = npred, nrow = nobs)
beta <- rnorm(npred, sd = 2)
y <- (mat %*% beta + rnorm(100, sd=0.2))[, 1]
x <- as.data.frame(mat)
cv_lm <- function(x, y, nfolds) {
## don't use T; it's dangerous.
index <- sample(seq_len(nfolds), nrow(x), replace = TRUE)
stopifnot(nrow(x) == length(y)) ## check to make sure the input is valid
## declare output as a vector of length nfolds
mse <- numeric(nfolds)
## use seq_len(nfolds) instead of 1:nfolds
for (n in seq_len(nfolds)) {
## create x and y training/test split
x_training <- x[index != n, ]
x_testing <- x[index == n, ]
y_training <- y[index != n]
y_testing <- y[index == n]
## fit model (y ~ . means "y against everything")
fit <- lm(y_training ~ ., data = x_training)
predictions <- predict(fit, newdata = x_testing)
## don't grow vectors
mse[[n]] <- mean((y_testing-predictions)^2)
}
return(mse)
}
## predict y with x (true predictors)
cv_lm(x = x, y = y, nfolds = 10)
#> [1] 0.07503477 0.02913210 0.03467926 0.03762000 0.03291574 0.05687162
#> [7] 0.01023195 0.06304727 0.02435436 0.06634923
## predict first predictor in x with the other 9 (no true relationship, hence larger MSE)
cv_lm(x = x[, 2:10], y = x[, 1], nfolds = 10)
#> [1] 0.7447689 1.4850093 1.0964575 2.5117445 1.1037217 1.0684408 1.7798122
#> [8] 0.9962255 1.0208430 1.3867716
我正在尝试开发一个对任何线性回归模型进行 k 折交叉验证的函数。我能够开发下面的代码
K.CV.2<-function(numberOfFolds, inputData){
index <- sample(1:numberOfFolds, nrow(inputData), replace = T)
inputData$index <- index
mse.all <- c()
for (n in 1:numberOfFolds) {
training.data <- inputData[inputData$index!=n,]
testing.data <- inputData[inputData$index==n,]
model.hold <- lm(earn~height+sex+race+ed, data = training.data)
predictions <- predict(model.hold, newdata=testing.data)
mse.hold <- mean((testing.data$earn-predictions)^2)
mse.all <- c(mse.all,mse.hold)
}
return(mse.all)
}
K.CV.2(numberOfFolds, Inputdata)
我对这个功能不满意,因为我试图让它更通用。我想要 function(numberOfFolds, y, x, InputData)
我希望能够使用 c()
函数传递 y
变量的列以及我将在 x
中用作解释变量的所有其他列。
有人可以 help/guide 我在正确的方向吗?
我猜是这样的。一些注意事项:
- 提供示例数据会更容易提供帮助。我已经为这个案例生成了一些虚假数据,但以后要记住一些事情。一般来说,我强烈建议您练习模拟数据来测试您的模型和假设。
- 不要使用
T
。它不是保留值。您可以在脚本中编写T <- FALSE
,结果可想而知。 - 直接传入您要使用的
x
和y
会更容易。这就是我在这里所做的。然后,您可以遍历数据帧并传入子集x
和您想要的任何y
,但它使 CV 函数更清晰。 - 除非绝对必要,否则不要增加对象。参见 the R inferno book。
- 最好避免在代码中使用
1:n
。如果n
为零,它会创建向量c(1, 0)
,这通常会导致意外结果。
npred <- 10
nobs <- 100
mat <- matrix(rnorm(npred * nobs), ncol = npred, nrow = nobs)
beta <- rnorm(npred, sd = 2)
y <- (mat %*% beta + rnorm(100, sd=0.2))[, 1]
x <- as.data.frame(mat)
cv_lm <- function(x, y, nfolds) {
## don't use T; it's dangerous.
index <- sample(seq_len(nfolds), nrow(x), replace = TRUE)
stopifnot(nrow(x) == length(y)) ## check to make sure the input is valid
## declare output as a vector of length nfolds
mse <- numeric(nfolds)
## use seq_len(nfolds) instead of 1:nfolds
for (n in seq_len(nfolds)) {
## create x and y training/test split
x_training <- x[index != n, ]
x_testing <- x[index == n, ]
y_training <- y[index != n]
y_testing <- y[index == n]
## fit model (y ~ . means "y against everything")
fit <- lm(y_training ~ ., data = x_training)
predictions <- predict(fit, newdata = x_testing)
## don't grow vectors
mse[[n]] <- mean((y_testing-predictions)^2)
}
return(mse)
}
## predict y with x (true predictors)
cv_lm(x = x, y = y, nfolds = 10)
#> [1] 0.07503477 0.02913210 0.03467926 0.03762000 0.03291574 0.05687162
#> [7] 0.01023195 0.06304727 0.02435436 0.06634923
## predict first predictor in x with the other 9 (no true relationship, hence larger MSE)
cv_lm(x = x[, 2:10], y = x[, 1], nfolds = 10)
#> [1] 0.7447689 1.4850093 1.0964575 2.5117445 1.1037217 1.0684408 1.7798122
#> [8] 0.9962255 1.0208430 1.3867716