k在purr和模型中进行交叉验证

时间:2017-12-24 00:11:01

标签: r purrr modelr

我遇到了这个例子

library(mtcars)
set.seed(17)
cv.error.10 = rep(0,10)
for (i in 1:10){
    glm.fit = glm(mpg∼poly(horsepower ,i),data=Auto)
    cv.error.10[i] = cv.glm(Auto,glm.fit,K=10)$delta[1]
}

cv.error.10
[1] 24.21 19.19 19.31 19.34 18.88 19.02 18.90 19.71 18.95 19.50

我一直在尝试选择purrrmodelr。这似乎是尝试复制的一个很好的例子,因为它包括循环和交叉验证。我如何将此代码转换为更整洁的类似的东西?

更新

根据以下建议,这是代码所在的位置

data(mtcars)
cv_mtcars = mtcars %>%
  crossv_kfold(k = 5)
cv_models = cv_mtcars %>%
  mutate(model = map(train, ~lm(mpg ~ hp, data = .)),
         rmse_all_models = map2_dbl(model, test, ~rmse(.x, .y)))
print(cv_models)

我想要做的是重复这个以增加hp的多项式,例如hp^2hp^3等。我猜有一种purr方法可以做此

更新2

以下是未迭代代码的示例

data(mtcars)
cv_mtcars = mtcars %>%
  crossv_kfold(k = 5)
cv_models = cv_mtcars %>%
  mutate(model1 = map(train, ~lm(mpg ~ hp, data = .)),
         model2 = map(train, ~lm(mpg ~I(hp^2), data = .)),
         model3 = map(train, ~lm(mpg ~I(hp^3), data = .)),         
         model4 = map(train, ~lm(mpg ~I(hp^4), data = .)),
         model5 = map(train, ~lm(mpg ~I(hp^5), data = .)),
         model6 = map(train, ~lm(mpg ~I(hp^6), data = .)),
         rmse_all_models1 = map2_dbl(model1, test, ~rmse(.x, .y)),
         rmse_all_models2 = map2_dbl(model2, test, ~rmse(.x, .y)),
         rmse_all_models3 = map2_dbl(model3, test, ~rmse(.x, .y)),
         rmse_all_models4 = map2_dbl(model4, test, ~rmse(.x, .y)),
         rmse_all_models5 = map2_dbl(model5, test, ~rmse(.x, .y)),
         rmse_all_models6 = map2_dbl(model6, test, ~rmse(.x, .y)))
print(cv_models)

1 个答案:

答案 0 :(得分:2)

我不知道mtcars库,但如果您需要访问mtcars数据,可以使用以下内容:

data(mtcars)
library(tidyverse)
library(modelr)

然后,您可以使用cross_mc()

创建重新采样列表
cv_mtcars = mtcars %>%
  crossv_mc(n = 50)

print(cv_mtcars)

现在您可以在重新采样上训练您的模型。 train是包含训练数据框的列。我将mutate()用于名为model的列,我将lm()函数(或任何其他模型)映射到数据。

cv_models = cv_mtcars %>%
  mutate(model = map(train, ~lm(mpg ~ horsepower, data = .)))

print(cv_models)

您可以使用modelr中的rmse()函数添加均方根误差:

rmse_cv = cv_models %>%
  mutate(rmse_all_models = map2_dbl(model, test, ~rmse(.x, .y))) %>%
  pull(rmse_all_models)

print(rmse_cv)

然后,您可以计算所需rmse()的任何统计信息。如果您不熟悉列表列的概念,则此代码可能有点压倒性。您可以在此处详细了解列表列:https://campus.datacamp.com/courses/exploratory-data-analysis-in-r-case-study/tidy-modeling-with-broom?ex=10&_escaped_fragment_=#skiponboarding

我在公共计算机上,因此无法尝试使用该代码,但应该工作。

更新

所以我稍微误解了这个问题,这里有更多的指示:

powers = seq(1:6)

create_form = function(power){
  rhs = substitute(I(hp^pow), list(pow=power))
  rlang::new_formula(quote(mpg), rhs)
}

此函数创建公式,然后您可以将一系列权力映射到此函数:

list_forms = map(seq(1,6), create_form)

然后将结果列表映射到lm

map(list_forms, lm, data=mtcars)

要将其集成到管道工作流程中,您需要创建一个新功能:

train_model = function(cv_data, form){
  cv_data %>%
  mutate(model = map(train, ~lm(form, data = .)))
}

在一个型号上测试:

test = train_model(cv_mtcars, list_forms[[1]])

现在在所有事情上运行它:

all_models = map(list_forms, train_model, cv_data=cv_mtcars)

希望这有帮助。