使用R中的nls进行非线性回归的交叉验证

时间:2016-05-31 10:36:41

标签: r cross-validation nls non-linear-regression

问题:

我有一个数据集inputAll.data。我希望将80%的数据用作模型构造输入,并在剩余的20%数据上验证模型。

我手动将数据集拆分为两个较小的数据集input80.datainput20.data,分别包含80%和20%的数据。

我的数据集中的数据格式:

Name      xvalues     yvalues
Prog1     0.654219    59.70282
Prog2     0.149516    49.59548
Prog3     0.50577     50.53859
Prog4     0.77783     59.95499
Prog5     0.237923    49.61133
Prog6     0.756063    50.63021
Prog7     0.015625    53.77959

我使用80%的数据来构建使用nls的非线性回归模型。

df = data.frame(input80.data)
yval = df$yvalues
xval = df$xvalues
model1 = nls(formula = yval ~ exp(xval + beta * xval), start = list(beta = 0))
sm1 = summary(model1)
fit1 = fitted.values(model1)

我正在获取剩余的20%数据以获得预测值。我保存了此数据的副本,其中包含名为y的另一个文件中的实际input20Actual.data值,但input20.data仅包含x值。

dfNew = data.frame(input20.data)
xpred = dfNew$xvalues
dfVerify = data.frame(input20Actual.data)
yverify = dfVerify$yvalues
xverify = dfVerify$xvalues

obtainedPred = predict(model1, data.frame(xvalues = c(xpred) ))

然后我使用名为RMSE的自定义函数来计算预测值与实际值之间的误差。

RMSE <- function(fitted, actual){
  sqrt(mean((fitted - actual)^2))
}

通过获取每个预测值并将其与我在input20Actual.data中存储的实际值进行比较来完成误差计算。我将输出存储在一个文件中。

sink("ErrorsOut.txt")
cat("\n\nRMSE:\n")
for (i in 1:13) {
    #There are 13 values to be predicted in input20.data
    corr = obtainedPred[[i]]
    act = yverify[[i]]
    err = RMSE(act, corr)
    cat(err)
    cat(" ")
}
cat("\n")
sink()

问题是我手动拆分输入集。我想自动执行此操作,并对不同的拆分(每次不同的数据)执行相同的操作,并获得计算错误的平均值。

我尝试了什么:

我已经阅读了关于R中交叉验证的StackOverflow。我的理解是它迭代地需要一些数据用于模型创建,剩下的用于测试。如果我可以在nls中使用交叉验证功能,我就不必将输入数据拆分为两个文件。

我在SO上搜索了很多解决方案。关于交叉验证的许多答案都是lm。但我特别要求nls进行交叉验证。我还阅读了caret包,但我尝试安装它,但大多数时候我最终得到包安装错误,如下所示:

Warning: dependency ‘plyr’ is not available
package ‘plyr’ is not available (for R version 3.0.2)

所以我希望有一种直接的方法可以在不安装更多软件包的情况下执行交叉验证(在rkward中)。 R中是否有一个函数或API可用于迭代创建模型并对其进行测试?

请注意我是R的完全新手。抱歉,这是一个显而易见的问题。

1 个答案:

答案 0 :(得分:2)

使用内置数据框BOD尝试下面fo中显示的简单模型。首先使用sample来获取样本内行的索引并在其上运行模型。然后使用predict.nls使用带有样本内模型的样本外数据来获取预测值。由此可以计算残差平方和(RSS)和其他结果。每次运行sample都会生成一组可能不同的索引(提供set.seed时不会重新运行)。这可以打包在一个函数中并重复运行。没有包使用。

set.seed(123) # for reproducibility

n <- nrow(BOD)
frac <- 0.8
ix <- sample(n, frac * n) # indexes of in sample rows

fo <- demand ~ a + Time * b
fm <- nls(fo, BOD, start = c(a = 0, b = 0), subset = ix) # in sample model

BOD.out <- BOD[-ix, ] # out of sample data
pred <- predict(fm, new = BOD.out)
act <- BOD.out$demand
RSS <- sum( (pred - act)^2 )
RSS