我正在尝试使用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)
这有什么解决方法吗?
答案 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)。