从r

时间:2015-04-24 10:32:57

标签: r validation lm

我想在R中使用lm函数对我的数据运行MLR。但是,我使用数据拆分交叉验证方法来访问模型的可靠性。我打算使用“样本”功能以80:20的比例将数据随机分成校准和验证数据集。我要重复说100次。没有设定种子,我相信不同采样的模型会有所不同。我在前面的帖子中遇到了这个功能,它解决了第一部分;

lst <- lapply(1:100, function(repetition) {
mod <- lm(...)   
# Replace this with the code you need to train your model
return(mod)
})
save(lst, file="myfile.RData")

现在关注的是如何验证这100个模型中的每一个并获得每个模型的RSME,ME,Rsquare等可靠性测试统计数据,并希望获得置信区间。

如果我能以数据框的形式获得包含所有100个模型的预测值的输出,那么我应该从那里开始。

请帮忙吗?

由于

1 个答案:

答案 0 :(得分:0)

快速回顾一下您的问题:您似乎希望将MLR模型拟合到大型训练集,然后使用此模型对剩余的验证集进行预测。您希望重复此过程100次,之后您希望能够分析各个模型的特征和预测。

要完成此任务,您可以在模型生成和预测过程中将临时模型信息存储在数据结构中。然后,您可以重新获取并处理所有信息。您没有在描述中提供自己的数据集,因此我将使用R的内置数据集之一来演示这可能如何工作:

> library(car)
> Prestige <- Prestige[,c("prestige","education","income","women")]
> Prestige[,c("income")] <- log2(Prestige[,c("income")])
> head(Prestige,n=5)
                    prestige education      income women
gov.administrators      68.8     13.11 -0.09620212 11.16
general.managers        69.1     12.26 -0.04955335  4.02
accountants             63.4     12.77 -0.11643822 15.70
purchasing.officers     56.8     11.42 -0.11972061  9.11
chemists                73.5     14.62 -0.12368966 11.68

我们首先初始化一些变量。假设您要创建100个模型并将80%的数据用于培训目的:

nrIterations=100
totalSize <- nrow(Prestige)
trainingSize <- floor(0.80*totalSize)

我们还想创建将用于保存中间模型信息的数据结构。在这方面,R是一种非常通用的高级语言,所以我们只创建一个列表列表。这意味着每个监听都可以自己再次保存另一个信息列表。这使我们可以灵活地添加我们需要的东西:

trainTestTuple <- list(mode="list",length=nrIterations)

我们现在准备创建我们的模型和预测。在每个循环期间,创建不同的随机训练子集,同时使用剩余数据进行测试。接下来,我们将模型拟合到trainingdata,然后使用此获得的模型对testdata进行预测。请注意,我们明确使用自变量来预测因变量:

for(i in 1:nrIterations)
{
  trainIndices <- sample(seq_len(totalSize),size = trainingSize)
  trainSet <- Prestige[trainIndices,]
  testSet <- Prestige[-trainIndices,]

  trainingFit <- lm(prestige ~ education + income + women, data=trainSet)

  # Perform predictions on the testdata
  testingForecast <- predict(trainingFit,newdata=data.frame(education=testSet$education,income=testSet$income,women=testSet$women),interval="confidence",level=0.95)
  # Do whatever else you want to do (compare with actual values, calculate other stuff/metrics ...)
  # ...

  # add your training and testData to a tuple and add it to a list
  tuple <- list(trainingFit,testingForecast) # Add whatever else you need ..
  trainTestTuple[[i]] <- tuple # Add this list to the "list of lists"
}

现在,相关部分:在迭代结束时,我们将拟合模型和样本外预测结果放在一个列表中。此列表包含我们要为当前迭代保存的所有中间信息。我们将此列表放在列表列表中完成。

现在我们完成了建模,我们仍然可以访问我们需要的所有信息,我们可以按照自己的方式进行处理和分析。我们将看一下模型50的建模和预测结果。首先,我们从列表列表中提取模型和预测结果:

> tuple_50 <- trainTestTuple[[50]]
> trainingFit_50 <- tuple_50[[1]]
> testingForecast_50 <- tuple_50[[2]]

我们来看看模型摘要:

> summary(trainingFit_50)

Call:
lm(formula = prestige ~ education + log2(income) + women, data = trainSet)

Residuals:
     Min       1Q   Median       3Q      Max 
-15.9552  -4.6461   0.5016   4.3196  18.4882 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)    
(Intercept)  -287.96143   70.39697  -4.091 0.000105 ***
education       4.23426    0.43418   9.752  4.3e-15 ***
log2(income)  155.16246   38.94176   3.984 0.000152 ***
women           0.02506    0.03942   0.636 0.526875    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 7.308 on 77 degrees of freedom
Multiple R-squared:  0.8072,    Adjusted R-squared:  0.7997 
F-statistic: 107.5 on 3 and 77 DF,  p-value: < 2.2e-16

然后我们明确地获得模型R平方和RMSE:

> summary(trainingFit_50)$r.squared
[1] 0.8072008
> summary(trainingFit_50)$sigma
[1] 7.308057

我们来看看样本预测的结果:

> testingForecast_50
        fit       lwr      upr
1  67.38159 63.848326 70.91485
2  74.10724 70.075823 78.13865
3  64.15322 61.284077 67.02236
4  79.61595 75.513602 83.71830
5  63.88237 60.078095 67.68664
6  71.76869 68.388457 75.14893
7  60.99983 57.052282 64.94738
8  82.84507 78.145035 87.54510
9  72.25896 68.874070 75.64384
10 49.19994 45.033546 53.36633
11 48.00888 46.134464 49.88329
12 20.14195  8.196699 32.08720
13 33.76505 27.439318 40.09079
14 24.31853 18.058742 30.57832
15 40.79585 38.329835 43.26187
16 40.35038 37.970858 42.72990
17 38.38186 35.818814 40.94491
18 40.09030 37.739428 42.44117
19 35.81084 33.139461 38.48223
20 43.43717 40.799715 46.07463
21 29.73700 26.317428 33.15657

最后,我们获得了关于第二个预测值和相应置信区间的更详细的结果:

> testingPredicted_2ndprediction <- testingForecast_50[2,1]
> testingLowerConfidence_2ndprediction <- testingForecast_50[2,2]
> testingUpperConfidence_2ndprediction <- testingForecast_50[2,3]

修改 重读之后,我发现你显然没有每次都拆分相同的精确数据集。您在每次迭代期间使用完全不同的数据分区,它们应以80/20方式拆分。但是,仍然可以通过微小的修改来应用相同的解决方案。

另外:出于交叉验证的目的,您应该查看cv.lm()

来自R帮助的说明: 此函数为多元线性回归提供预测准确性的内部和交叉验证度量。 (对于二元逻辑回归,使用CVbinary函数。)数据被随机分配到多个“折叠”。反过来,每个折叠被移除,而剩余的数据用于重新拟合回归模型并预测删除的观察结果。

编辑:回复评论。 您可以采取您保存的相关性能指标的方法。例如,您可以在sapply上使用trainTestTuple,以便从每个子列表中提取相关元素。 sapply会将这些元素作为向量返回,您可以从中计算mean。这应该有效:

mean_ME <- mean(sapply(trainTestTuple,"[[",2))
mean_MAD <- mean(sapply(trainTestTuple,"[[",3))
mean_MSE <- mean(sapply(trainTestTuple,"[[",4))
mean_RMSE <- mean(sapply(trainTestTuple,"[[",5))
mean_adjRsq <- mean(sapply(trainTestTuple,"[[",6))

另一个小编辑:你的MAD的计算看起来很奇怪。仔细检查这是否正是您想要的,这可能是一件好事。