如何为R中nls函数确定最优初始值?附数据集与报错问题
非线性模型拟合:初始值确定与奇异梯度问题解决
数据集
使用的数据集如下:
x <- cbind(c(1,2,3,4,5,6,7,8,9,10,11,12,13)) y <- cbind(c(0.37, 0.25, 0.23, 0.24, 0.32, 0.23, 0.24, 0.26, 0.24, 0.26, 0.27, 0.27)) df <- data.frame('x' = x, 'y' = y)
模型需求
需要拟合非线性模型:y = a + exp(b + c*x)
之前的尝试与问题
尝试直接用原数据线性回归的截距作为a的初始值,斜率作为b的初始值,同时设c的初始值与b相同,运行以下代码:
m1 <- nls(y ~ model_func1(x, a, b, c), data = df , start = list(a = -0.003033, b=0.284778, c=0.284778), trace = T) summary(m1)
但始终报错:
Error in nls(y ~ model_func1(x, a, b, c), data = df, : singular gradient
该错误源于初始值与模型真实参数偏差过大,导致nls算法无法计算有效的梯度,无法收敛。
针对该模型的初始值确定方法
核心思路:变量变换转线性回归
对于模型y = a + exp(b + c*x),可通过变量变换将其转化为线性形式,从而利用线性回归得到可靠的初始值:
- 确定
a的初始值:由于exp(b + c*x)始终为正,因此a必须小于所有y的取值(否则y - a可能为负,无法取对数)。观察数据集,y的最小值为0.23,因此可设a的初始值为0.2(或略小于0.23的其他值)。 - 构造线性化变量:计算
z = ln(y - a),此时模型转化为z = b + c*x,这是标准的线性模型。 - 线性回归求
b和c的初始值:用z对x做线性回归,回归的截距即为b的初始值,斜率即为c的初始值。
具体实现代码
# 1. 设定a的初始值 a_start <- 0.2 # 2. 构造线性化变量z df$z <- log(df$y - a_start) # 3. 线性回归获取b和c的初始值 lm_fit <- lm(z ~ x, data = df) b_start <- coef(lm_fit)[1] # 截距项作为b的初始值 c_start <- coef(lm_fit)[2] # 斜率项作为c的初始值 # 定义模型函数 model_func1 <- function(x, a, b, c) { a + exp(b + c*x) } # 4. 拟合nls模型 m1 <- nls(y ~ model_func1(x, a, b, c), data = df, start = list(a = a_start, b = b_start, c = c_start), trace = TRUE) summary(m1)
其他可选初始值确定方法
- 可视化观察:绘制
x与y的散点图,观察曲线的渐近趋势,猜测a的取值(比如曲线趋近的水平值),手动调整b和c使曲线大致贴合数据点,以此作为初始值。 - 网格搜索:对
a、b、c设定合理的取值范围,遍历所有参数组合,计算每个组合对应的残差平方和,选择残差最小的组合作为初始值。
内容的提问来源于stack exchange,提问作者Farrelyto Theodorus
相关产品推荐
相关产品推荐

