使用带有长变量列表的R函数nls

时间:2018-06-12 08:35:17

标签: r arguments nls non-linear-regression

我正在尝试使用R函数nls估计非线性模型。

我将通过" help"中的示例说明我的问题。 nls的设施。

Treated <- Puromycin[Puromycin$state == "treated", ]
weighted.MM <- function(resp, conc, Vm, K)
{
    pred <- (Vm * conc)/(K + conc)
    (resp - pred) / sqrt(pred)
}

Pur.wt <- nls( ~ weighted.MM(rate, conc, Vm, K), data = Treated,
          start = list(Vm = 200, K = 0.1))

在这个例子中,weighted.MM是一个参数数量非常有限的函数,对于我正在使用的模型类型实现类似方法没有问题。

但是,我现在正在努力转向一个更现实的问题,在这个问题上,我确实有几十个参数传递给函数。我当然可以简单地列举它们,但我觉得这有点笨拙。

我考虑先将它们放在一个单独的列表中。例如,使用上面的例子,我首先定义:

MyArguments <- list(Vm, K)  

然后将MyArguments作为参数传递给函数(并从函数中访问各个参数)。但是,这不起作用,因为我收到了错误消息

Error: object 'Vm' not found

可替换地,

    MyArguments <- list("Vm", "K") 

weighted.MM1 <- function(resp, conc1, conc.1, thearguments)
{
  conc <- c(conc1, conc.1)
  pred <- (thearguments[[1]] * conc)/(thearguments[[2]] + conc)
  (resp - pred) / sqrt(pred)
}

Pur.wt1 <- nls( ~ weighted.MM1(rate, conc1, conc.1, MyArguments),
                data = lisTreat, start = list(Vm = 200, K = 0.1))

的产率:

Error in thearguments[[1]] * conc : 
  non-numeric argument to binary operator
Called from: weighted.MM1(rate, conc1, conc.1, MyArguments)

这有什么解决方法吗?

2 个答案:

答案 0 :(得分:1)

由于您正在寻找参数的值,因此您无需定义它们:请查看以下代码:

weighted.MM1 <- function(resp, conc1, conc.1, thearguments)
{
  conc <- c(conc1, conc.1)
  pred <- (thearguments[1] * conc)/(thearguments[2] + conc)
  (resp - pred) / sqrt(pred)
}
nls( ~ weighted.MM1(rate, conc1, conc.1, MyArguments),
                data = lisTreat, start = list(MyArguments =c( 200, 0.1)))
Nonlinear regression model
  model: 0 ~ weighted.MM1(rate, conc1, conc.1, MyArguments)
   data: lisTreat
MyArguments1 MyArguments2 
   206.83468      0.05461 
 residual sum-of-squares: 14.6

Number of iterations to convergence: 5 
Achieved convergence tolerance: 3.858e-06

答案 1 :(得分:0)

我尝试根据@Onyambu友好提出的建议实施新的解决方案。

但这会产生新的问题。

首先,我尝试使用nls实现解决方案。这是我使用的实际代码:

DiffModel <- nls(COPERTFreq ~ CalculateProbaVehChoiceDiffusion(MyArguments, years = RegistYear),
                 data = DataSetForModel , start = list(MyArguments = c(ASC_Mat, ASC_No_Size)))

其中CalculateProbaVehChoiceDiffusion()是在其他地方定义的非线性函数,RegistYear是常量,MyArguments是要估计的系数列表,其中c(ASC_Mat,ASC_No_Size)为初始值。

这会导致以下错误消息:

Error in numericDeriv(form[[3L]], names(ind), env) : 
  Missing value or an infinity produced when evaluating the model

现在,我已经在其他地方读过这个问题可以通过使用nlsLM来解决。这会导致出现新的错误消息:

Error in `rownames<-`(`*tmp*`, value = "MyArguments") : 
  length of 'dimnames' [1] not equal to array extent

好的,所以我在调试模式下使用nls.lm再次运行模型。这表明错误消息源自以下代码行:

names(out$par) <- rownames(out$hessian) <- colnames(out$hessian) <- names(out$diag) <- names(par)

然而,这是通过检查&#34; out&#34;在问题所在的地方变得清晰的对象。首先,$ hessian只是一个标量,而我希望它的行数和列数等于参数的数量。其次,$ par $ MyArguments显示除了第一个元素之外,MyArguments的值不会从一次迭代变为另一次迭代。

这是一个已知错误还是我必须修改我将MyArguments传递给函数调用的方式?

请注意,据我所知,当我将nlsLm应用于@Onyambu提供的示例时,也会出现此问题:

> undebug(nls.lm)
> Treated <- Puromycin[Puromycin$state == "treated", ]
> 
> lisTreat <- with(Treated,
+                  list(conc1 = conc[1], conc.1 = conc[-1], rate = rate))
> 
> weighted.MM1 <- function(resp, conc1, conc.1, thearguments)
+ {
+   conc <- c(conc1, conc.1)
+   pred <- (thearguments[1] * conc)/(thearguments[2] + conc)
+   (resp - pred) / sqrt(pred)
+ }
> nls( ~ weighted.MM1(rate, conc1, conc.1, MyArguments),
+      data = lisTreat, start = list(MyArguments =c( 200, 0.1)))
Nonlinear regression model
  model: 0 ~ weighted.MM1(rate, conc1, conc.1, MyArguments)
   data: lisTreat
MyArguments1 MyArguments2 
   206.83468      0.05461 
 residual sum-of-squares: 14.6

Number of iterations to convergence: 5 
Achieved convergence tolerance: 3.858e-06
> 
> nlsLM( ~ weighted.MM1(rate, conc1, conc.1, MyArguments),
+        data = lisTreat, start = list(MyArguments =c( 200, 0.1)))
Error in `rownames<-`(`*tmp*`, value = "MyArguments") : 
  length of 'dimnames' [1] not equal to array extent

因此,虽然nls适用于此示例,但nlsLM不会,并产生与我的代码相同的错误消息。 然后我在调试模式下使用nls.lm再次运行nlsLM。在以下行之后,

out <- .Call("nls_lm", par, lower, upper, fn1, jac1, ctrl, 
    new.env(), PACKAGE = "minpack.lm")

我检查out对象并看到:

$par
$par$MyArguments
[1] 244.5117   0.1000


$hessian
[1] 0.02859739

$fvec
 [1] -5.5215487 -0.9787468 -0.5543382 -1.5986605  0.4486608 -0.9651245  0.7020058  1.2419040  1.1430780  0.4488084  1.1445818  1.6121474

$info
[1] 1

$message
[1] "Relative error in the sum of squares is at most `ftol'."

$diag
$diag[[1]]
[1] 0.2077949


$niter
[1] 4

$rsstrace
[1] 112.59784  43.41211  42.89350  42.89349  42.89349

因此,第二个参数的值在4次迭代后没有改变。 当然可以是正确的解决方案。但我发现这与我的模型同样发生了一个有趣的巧合。

最终编辑:我终于决定重新使用所有参数的完整枚举。正如我在问题陈述中所写的那样,它不是很优雅,但至少它适用于nls.lm(尽管仍然没有使用nls)。