简体   繁体   English

如何使用 nls() 在指数衰减 model 中拟合多个常数?

[英]How to use nls() to fit multiple constants in exponential decay model?

I am dealing with the relationship:我正在处理这种关系:

y = h * R + x * v * h y = h * R + x * v * h

where:在哪里:

x = (N - M) * exp(-Q * u) + M x = (N - M) * exp(-Q * u) + M

which gives the principal equation:这给出了主要方程:

y = h * R + v * h * (N - M) * exp(-Q * u) + v * h * M y = h * R + v * h * (N - M) * exp(-Q * u) + v * h * M

All uppercase letters are constants, and all lowercase letters are variables.所有大写字母都是常量,所有小写字母都是变量。

I have real data for all the variables, but I either do not know the values of the constants (R and Q), or want to check the ability of the data to fit the values of the constants (N and M).我有所有变量的真实数据,但我要么不知道常量(R 和 Q)的值,要么想检查数据拟合常量(N 和 M)值的能力。 I want to use nls() to fit the equation using the data for the variables, to estimate these constant parameters.我想使用 nls() 使用变量数据来拟合方程,以估计这些常数参数。

How do I write code using the nls() function to depict the principal equation, to allow estimation of the parameters R, N, Q, and M from the mock measurement data?如何使用 nls() function 编写代码来描述主要方程,以允许从模拟测量数据中估计参数 R、N、Q 和 M? (Mock measurement data = lower cases letters with _j suffix, see below.) (模拟测量数据 = 带 _j 后缀的小写字母,见下文。)

To create mock data:创建模拟数据:

library(dplyr)
library(ggplot2)

### Generate mock data

# Equations:
# y = h*R + x*v*h
# x = (N-M)*exp(-Q*u) + M
# y = h*R + ((N-M)*exp(-Q*u) + M)*v*h
# y = h*R + v*h*(N-M)*exp(-Q*u) + v*h*M

### Variables have varying periodicity,
# and so can be approximated via different functions,
# with unique noise added to each to simulate variability:

# Variability for each variable
n <- 1000 # number of data points
t <- seq(0,4*pi,length.out = 1000)
a <- 3
b <- 2

y.norm <- rnorm(n)
u.norm <- rnorm(n)
u.unif <- runif(n)
v.norm <- rnorm(n)
v.unif <- runif(n)
amp <- 1

# Create reasonable values of mock variable data for all variables except h;
# I will calculate from known fixed values for R, N, Q, and M.

y <- 1.5*a*sin(b*t)+y.norm*amp-10 # Gaussian/normal error
u <- ((1*a*sin(11*b*t)+u.norm*amp)+(0.5*a*sin(13*b*t)+u.unif*amp)+7)/2
v <- 1/((2*a*sin(11*b*t)+v.norm*amp)+(1*a*sin(13*b*t)+v.unif*amp)+20)*800-25

# Put vectors in dataframe
dat <- data.frame("t" = t, "y" = y, "u" = u, "v" = v)

### Create reasonable values for constants:

R=0.5
N=1.12
Q=0.8
M=1

### Define final variable based on these constants and the previous
# mock variable data:

dat$h = y/(R + v*(N-M)*exp(-Q*dat$u))

### Gather data to plot relationships:

dat_gathered <- dat %>%
  gather(-t, value = "value", key = "key")

### Plot data to check all mock variables:

ggplot(dat_gathered, aes(x = t, y = value, color = key)) + geom_line()

# Add small error (to simulate measurement error):

dat <- dat %>%
  mutate(h_j = h + rnorm(h, sd=0.05)/(1/h)) %>%
  mutate(u_j = u + rnorm(u, sd=0.05)/(1/u)) %>%
  mutate(v_j = v + rnorm(v, sd=0.05)/(1/v)) %>%
  mutate(y_j = y + rnorm(y, sd=0.05)/(1/y))

nls appears to work OK, but it looks like the solution (in terms of parameters) is non-unique... or I made a mistake somewhere. nls似乎工作正常,但看起来解决方案(就参数而言)不是唯一的......或者我在某处犯了错误。

## parameter values chosen haphazardly
n1 <- nls(y ~ h_j*(R + v_j*((N-M)*exp(-Q*u_j)+M)),
    start=list(R=1,N=2,M=1,Q=1),
    data=dat)

## starting from known true values
true_vals <- c(R=0.5,N=1.12,Q=0.8,M=1)
n2 <- update(n1, start=as.list(true_vals))

round(cbind(coef(n1),coef(n2),true_vals),3)
              true_vals
R 0.495 0.495      0.50
N 0.120 0.120      1.12
M 0.001 0.818      0.80
Q 0.818 0.001      1.00

Using AIC() on the two fits shows they have essentially equivalent goodness of fits (and the predictions are almost identical), which suggests that there's some symmetry in your model that allows M and Q to be interchanged.在两个拟合上使用AIC()表明它们具有基本相同的拟合优度(并且预测几乎相同),这表明 model 中存在一些对称性,允许MQ互换。 I haven't thought about/looked at the equation hard enough to know why this would be the case.我还没有认真考虑/仔细研究过这个等式,以了解为什么会这样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM