minpack.lm包nlsLM带参数和约束的NLS拟合报错求助
解决非线性拟合的约束问题
问题分析
你当前的错误在于试图通过在模型公式中添加约束相关的对数项来强制满足A_b+A_s<1等条件,这种方式相当于人为篡改了拟合的响应变量结构,不符合非线性拟合的模型逻辑,导致nlsLM报错。正确的做法是通过参数重参数化,将有约束的参数转换为无约束参数,让优化器可以正常处理。
约束转换方案
针对你的约束条件:
A_b > 0、A_s > 0、k > 0:用指数函数将无约束参数转换为正参数A_b + A_s < 1:先将两者的和S限制在(0,1)区间,再拆分A_b和A_s为S的正比例部分
具体重参数化方式:
- 设
k = exp(d),d为无约束参数,确保k>0 - 设
S = plogis(c)(logistic函数,输出范围(0,1)),c为无约束参数,确保A_b + A_s = S <1 - 设
A_b = S * plogis(a),A_s = S * (1 - plogis(a)),a为无约束参数,确保A_b>0、A_s>0且A_b+A_s=S
修正后的代码
library(minpack.lm) data <- data.frame(x = c(0.63, 0.67, 1.08, 1.37, 1.17, 1.34, 1.33, 1.48, 1.40, 1.58, 1.02, 1.48, 0.90, 0.55, 0.90), y = c(0.58, 0.61, 0.50, 0.51, 0.50, 0.47, 0.49, 0.51, 0.47, 0.48, 0.53, 0.43, 0.57, 0.68, 0.49)) # 定义重参数化后的模型函数 model_fun <- function(x, a, c, d) { S <- plogis(c) # A_b + A_s ∈ (0,1) A_b <- S * plogis(a) # A_b > 0 A_s <- S * (1 - plogis(a)) # A_s > 0 k <- exp(d) # k > 0 # 原模型公式 A_b + (A_s * k / x) * log((x + k)/k) } # 拟合模型,初始值针对无约束参数设置 fit <- nlsLM(y ~ model_fun(x, a, c, d), data = data, start = list(a = 0, c = -1, d = 0)) # 查看拟合结果,并转换回原参数 fit_summary <- summary(fit) original_params <- list( A_b = plogis(coef(fit)["c"]) * plogis(coef(fit)["a"]), A_s = plogis(coef(fit)["c"]) * (1 - plogis(coef(fit)["a"])), k = exp(coef(fit)["d"]) ) print(fit_summary) cat("\n转换后的原参数:\n") print(original_params)
说明
- 重参数化后,所有优化参数
a、c、d都是无约束的,nlsLM可以正常进行非线性最小二乘拟合 - 通过
plogis和exp函数,确保原参数严格满足所有约束条件 - 不需要额外添加假数据点,拟合逻辑完全符合非线性模型的要求
内容的提问来源于stack exchange,提问作者Samuel Charberet
相关产品推荐
相关产品推荐

