我想要一个模型,其中包含一个变量系数的总和,例如这里
我想编写代码,以便潜在用户在运行拟合例程时指定系数的数量(即将 i 设置为任何正整数值),但我没有想法如何开始编码。当然,我可以简单地写出大量潜在变量的结果方程(例如 1 ),并在开始时切换到指定的变量,但我更愿意一个“更漂亮”的解决方案(即更少的行),如果在R中可用,我现在正在使用 nls ,但我当然会对任何解决方案感到满意。
这是我到目前为止所尝试的内容:
Model <- function(X0, t, X, tau){X0+((X*tau*(exp(1/tau)-1))*exp(-t/tau))}
set.seed(1)
df <- data.frame(t=sort(sample(1:100,50)))
df$P <- jitter(with(df, Model(X0=0.1, t=t, X=0.2, tau=5)), 1000)
Model_fit <- nls(P ~ Model(X0=0.1, t=t, X=X1_fit, tau=5)
, start = list(X1_fit=c(0.1)), data=df, trace = F)
plot(df$t,df$P)
lines(df$t, predict(Model_fit, list(P = df$P)))
效果很好。只需将矢量传递给X1_fit
,就可以很容易地拟合多个系数。然而,我现在正在努力的是如何正确地在公式中形成总和。我不能只使用
X=c(0.2,5)
Model <- function(X0, t, X, tau){X0+sum((X*tau*(exp(1/tau)-1))*exp(-t/tau))}
因为这当然会返回一个值,即对t
的依赖性会丢失。相反,代码只需要为t
的每个单独值获取总和,以便函数仍然返回长度为t
的向量。但是,我正在努力弄清楚如何在不回复循环的情况下做到这一点,这也可能很难通过nls来适应?
干杯!
修改
@G。格洛腾迪克的答案很好,但我意识到拟合程序对方程中的微小修改非常敏感,特别是当不仅需要安装一个常数时。例如
set.seed(1)
Model <- function(X0, t, X, tau) {
res <- X0 + rowSums(sapply(seq_along(X), function(i)
(X[i]*tau[i]/5*(exp(5/tau[i])-1))*exp(-t/tau[i])))}
df <- data.frame(t=sort(sample(1:100,50)))
df$P <- jitter(with(df, Model(X0=0.1, t=t, X=c(0.2, 2), tau=c(4, 7))), 1000)
Model_fit <- nls(P ~ Model(X0=0.1, t=t, X=X1_fit, tau=tau_fit)
, start = list(X1_fit=c(0.1, 1), tau_fit=5:6), data=df)
无法运行
Error in nls(P ~ Model(X0 = 0.1, t = t, X = X1_fit, tau = tau_fit), start = list(X1_fit = c(0.1, :
step factor 0.000488281 reduced below 'minFactor' of 0.000976562
(我在两个地方添加了一个常量5
,现在也尝试适合tau
),即使在减小步长和增加迭代次数时也是如此。原则上,我理解拟合4个系数很容易变得不稳定,但我在Matlab中的替代代码似乎对它处理得很好(对于那个问题,甚至更合适的系数)。也许这在一个单独的问题中会更好,但是由于线程引用了“任意数量的拟合参数”,我觉得这个后续最好是作为编辑完成的。
答案 0 :(得分:1)
sapply
我创建了一个二维矩阵并使用rowSums
来执行求和:
set.seed(1)
Model <- function(X0, t, X, tau) {
res <- X0 + rowSums(sapply(seq_along(X), function(i)
(X[i]*tau[i]*(exp(1/tau[i])-1))*exp(-t/tau[i])))
}
df <- data.frame(t=sort(sample(1:100,50)))
df$P <- jitter(with(df, Model(X0=0.1, t=t, X=c(0.2, 2), tau=c(4, 7))), 1000)
Model_fit <- nls(P ~ Model(X0=0.1, t=t, X=X1_fit, tau=5:6)
, start = list(X1_fit=c(0.1, 1)), data=df, trace = F)
plot(df)
lines(fitted(Model_fit) ~ t, df, col = "red")
,并提供:
> Model_fit
Nonlinear regression model
model: P ~ Model(X0 = 0.1, t = t, X = X1_fit, tau = 5:6)
data: df
X1_fit1 X1_fit2
0.2107 2.0849
residual sum-of-squares: 0.5175
Number of iterations to convergence: 1
Achieved convergence tolerance: 1.511e-07