使用nls()拟合指数衰减模型:拟合失败或结果偏差求助
问题原因与解决方案
你的拟合结果偏差极大的核心问题是模型结构错误:你使用的exp(-k*incu_time)在时间为0时预测值为1,但你的数据中t≈0时结合率接近100,模型完全不符合数据的初始条件。正确的指数衰减模型需要加入初始振幅参数A,形式应为:
perc_binding = A * exp(-k*incu_time)
另外,你的数据未按时间排序,直接用lines()绘制拟合曲线会出现乱连的情况,需要先对数据排序。
具体解决步骤
修正模型并设置合理初始值
给模型加入初始振幅A,初始值可参考数据中最大的结合率(≈100);k的初始值可根据数据衰减趋势估算(比如0.01)。排序数据
按incu_time从小到大排序,确保拟合曲线的绘制逻辑正确。可选:线性化方法获取更稳定的初始值
对模型两边取对数得到log(perc_binding) = log(A) - k*incu_time,先用线性回归拟合,再将结果转换为nls的初始值,能大幅提升拟合稳定性。
完整代码示例
library(tibble) koff_dat <- tribble( ~incu_time, ~perc_binding, 179.20634920634922, 3.94736842105263, 120.47619047619048, 10.197368421052616, 91.11111111111111, 18.09210526315789, 60.95238095238095, 35.526315789473685, 45.87301587301587, 31.25, 30.793650793650798, 55.921052631578945, 16.50793650793652, 68.75, 0.6349206349206398, 99.34210526315789 ) # 按时间排序数据 koff_dat_sorted <- koff_dat[order(koff_dat$incu_time), ] # 方法1:直接用修正后的模型拟合 fit2 <- nls(perc_binding ~ A * exp(-k*incu_time), data = koff_dat_sorted, start = list(A = 100, k = 0.01)) # 方法2:用线性化获取初始值(更稳定) lm_fit <- lm(log(perc_binding) ~ incu_time, data = koff_dat_sorted) start_vals <- list(A = exp(coef(lm_fit)[1]), k = -coef(lm_fit)[2]) fit2 <- nls(perc_binding ~ A * exp(-k*incu_time), data = koff_dat_sorted, start = start_vals) # 查看拟合结果 summary(fit2) # 绘图 plot(perc_binding ~ incu_time, data = koff_dat_sorted) lines(koff_dat_sorted$incu_time, predict(fit2), col = "red", lwd = 2)
效果说明
修正模型后,拟合曲线会与数据点高度贴合,参数k的估计值也会符合实际衰减趋势。你可以通过summary(fit2)查看参数的置信区间和拟合统计量,验证拟合质量。
内容的提问来源于stack exchange,提问作者PPenton
相关产品推荐
相关产品推荐

