非单调双指数曲线拟合:初始参数值求解及报错咨询
解决非单调双指数曲线拟合的初始值问题及报错修复
问题分析
你用的y ~ k*(exp(-b1*x) - exp(-b2*x))属于药代里的吸收-消除双指数模型,这次报错是因为初始值选得不合理:当b1和b2初始值相等时,模型退化为线性项,梯度矩阵直接奇异;同时k=1远大于数据的y峰值(0.068),也会导致拟合方向完全偏离。
步骤1:合理估算初始值
手动估算(基于数据特征)
- k:模型峰值近似为
k*(b2/(b2-b1))^((b2)/(b2-b1)),你的y峰值是0.068,直接把k初始值设为略大于峰值,比如0.1。 - b1(消除速率):看x≥12的消除阶段(y从0.05降到0.0043),取后3个点拟合单指数估算:
elim_df <- df[df$x >= 12, ] lm(log(y) ~ x, data = elim_df) # 输出中x的系数是-b1,算出来大概在0.05左右
- b2(吸收速率):吸收速率必须大于消除速率(否则不会出现峰值),直接设为
0.2即可。
用Sbiexp自动获取初始值
如果你已经加载了带Sbiexp的PK工具包,直接传入数据就能得到适配的初始值:
init_vals <- Sbiexp(df$x, df$y) # 提取对应的k、b1、b2,注意和你的模型参数名对应
步骤2:修正拟合代码
用估算好的初始值重新拟合,建议加上algorithm = "port"并限制参数范围,避免出现b2 ≤ b1这类不符合药代逻辑的参数:
nls_mod_bi <- nls( y ~ k * (exp(-b1*x) - exp(-b2*x)), start = c(k = 0.1, b1 = 0.05, b2 = 0.2), data = df, algorithm = "port", lower = c(k = 0, b1 = 0, b2 = 0.051), # 强制b2 > b1 upper = c(k = 1, b1 = 0.2, b2 = 1) ) # 查看拟合结果 summary(nls_mod_bi) # 绘图验证拟合效果 plot(df$x, df$y) lines(df$x, predict(nls_mod_bi), col = "red", lwd = 2)
额外提示
- 如果还是报错,检查是否
b1和b2初始值过于接近,适当拉大两者差距; - 药代领域也可以用
nlme包的nlme函数拟合,对初始值的鲁棒性比nls更好; - 拟合前可以先画数据散点图,确认曲线趋势是否符合非单调双指数的特征(先升后降)。
内容的提问来源于stack exchange,提问作者LucaS
相关产品推荐
相关产品推荐

