R中的单变量非线性优化

时间:2015-02-19 08:39:09

标签: r

我试图在R中找到与MATLAB的信任区域反射算法类似的解决方案。之前已经提出过这个问题,但要求作者提供可重复的例子。我无法在那里评论,所以唯一的解决方案是发布新问题。这是我的榜样:

    x <- c(5000,5000,5000,5000,2500,2500,2500,2500,1250,1250,1250,1250,625,625, 625,625,312,312,312,312,156,156,156,156)
    y <- c(0.209065186,0.208338898,0.211886104,0.209638321,0.112064803,0.110535275,0.111748670,0.111208841,0.060416469,0.059098975,0.059274827,0.060859512,0.032178730,0.033190833,0.031621743,0.032345817,0.017983939,0.016632180,0.018468540,0.019513489,0.011490089,0.011076365,0.009282322,0.012309134)

由于初始参数值是我尝试使用&#39; nls2&#39;的核心问题。使用&#39;暴力&#39;算法找到好的起始参数。即使这样,nls和nls.lm也无法达成收敛。以下是一些基本代码:

    library('nls2'); library('minpack.lm')
    fo <- y ~ I(A * (x ^ B) + C)
    sA <- seq(-2,1,len=10) # range of parameter values
    sB <- seq(-1,1,len=10)
    sC <- seq(-1,1,len=10)
    st1 <- expand.grid(A=sA,B=sB,C=sC)
    mod1 <- nls2(fo,start=st1,algorithm="brute-force")
    fit_ <- nls(fo,start=coef(mod1)) # basic nls
    # or nls.lm
    fit_ <- nlsLM(fo, start=coef(mod1),algorithm = "LM")

MATLAB制作:

     a =   7.593e-05  (6.451e-05, 8.736e-05)
     b =      0.9289  (0.9116, 0.9462)
     c =    0.002553  (0.001333, 0.003772)

     Goodness of fit:
       SSE: 2.173e-05
       R-square: 0.9998
       Adjusted R-square: 0.9998
       RMSE: 0.001017

是的,使用这些参数值,R也产生了解决方案。 问题:如何在不使用matlab的情况下在R中获得这个?

1 个答案:

答案 0 :(得分:1)

在查看绘制的数据后,我猜测合适的起始值是没有问题的:

plot(y ~ x)

数据几乎在0的直线上。因此良好的起始值vor B和C应分别为1和0。那你只需要猜测直线的斜率。当然,您也可以使用lm(y ~ x)来查找A和C的起始值。

fo <- y ~ A * (x ^ B) + C
DF <- data.frame(x, y)

fit <- nls(fo, start = list(A = 0.001, B = 1, C = 0), data = DF)
summary(fit)
#Formula: y ~ A * (x^B) + C
#
#Parameters:
#   Estimate Std. Error t value Pr(>|t|)    
#A 7.593e-05  5.495e-06  13.820 5.17e-12 ***
#B 9.289e-01  8.317e-03 111.692  < 2e-16 ***
#C 2.552e-03  5.866e-04   4.351 0.000281 ***
#---
#Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#
#Residual standard error: 0.001017 on 21 degrees of freedom
#
#Number of iterations to convergence: 5 
#Achieved convergence tolerance: 9.084e-07

lines(seq(min(x), max(x), length.out = 100),
      predict(fit, newdata = data.frame(x = seq(min(x), max(x), length.out = 100))),
      col = "blue")

resulting plot