适合给定数据集的函数

时间:2015-12-09 23:54:51

标签: r curve-fitting data-fitting

我正在尝试将以下函数y(x)= a *(1 +(x ^ 2)/(b ^ 2))^ t拟合到一组特定数据,其中,a,b和t是想要通过拟合确定的常数。

我尝试以下操作,例如

len <- 24
x = runif(len)
y = x^3 + runif(len, min = -0.1, max = 0.1)
plot(x, y)
s <- seq(from = 0, to = 1, length = 50)
lines(s, s^3, lty = 2)

df <- data.frame(x, y)
m <- nls(y~a*( 1 + (x^2)/(b^2) )^t, data = df, start = list(a=1,t=0, b=1), trace = T)

> Error in nlsModel(formula, mf, start, wts) : 
  singular gradient matrix at initial parameter estimates

有人可以帮助我将这个功能设置到这些点,即使拟合变坏,重要的是要适应这个功能,即她运行数据

谢谢大家

1 个答案:

答案 0 :(得分:0)

由于您的数据随机变化,因此在某些情况下, a 的值接近于零,您的函数变为零。曲线拟合程序在那时失败。随机化启动参数可能适用于某些情况。

使用LM算法可以计算稍微更稳定的输出:

require("minpack.lm")
LMCurveFit <- function(df) {

  # The function to be fit
  FitFunction <- function(params, x) {
    with (
      as.list(params), {
         a*(1 + x^2/b^2)^t
      }
    )
  }

  # Residual
  Residual <- function(params, x, y) {
    FitFunction(params, x) - y
  }

  # Sum of squares of residuals
  ssqfun <- function(params, x, y) {
    sum(Residual(params, x, y)^2)
  }

  # Normalize the data
  x_max = max(x)
  y_max = max(y)
  df$x = df$x/x_max
  df$y = df$y/y_max

  # Define start parameters
  a_start = 0.1
  b_start = 1.0
  t_start = 1.0
  param_start = c(a = a_start,
                  b = b_start,
                  t = t_start)

  # Do LM fit
  nls.out <- nls.lm(par = param_start,
                    fn = Residual,
                    control = nls.lm.control(nprint=0,
                                             ftol=.Machine$double.eps,
                                             ptol=.Machine$double.eps,
                                             maxfev=10000, maxiter=1024),
                    x = df$x,
                    y = df$y)

  # Revert scaling
  nls.out$par[1] = nls.out$par[1]*y_max
  nls.out$par[2] = nls.out$par[2]*x_max

  # Get the parameters
  params_fit = coef(nls.out)
  print(params_fit)

  # Compute predicted values
  predicted = FitFunction(as.list(params_fit), df$x*x_max)
}

# LM fit
pred_y = LMCurveFit(df)
lines(x, pred_y)