You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言中nls()返回负标准差的原因探究

问题:nls()拟合正态曲线返回负标准差的原因及解决办法

我尝试在R语言中将数据建模为正态曲线,使用的方程形式为正态分布函数,以下是计算方程参数的代码:

filtered_sp14 <- c(549.778714, 259.835892, 992.874178, 75.267324, 53.014376, 128.281700, 10.471976, 58.904862,
                   88.357293, 102.756260, 201.585529, 29.452431, 1130.973355, 198.967535, 233.001455, 106.028752,
                   962.112750, 75.921822, 858.047494, 82.466807, 198.967535, 70.685835, 68.722339, 130.899694,
                   52.359878, 41.233404, 53.014376, 187.186562, 10.471976, 26.179939, 39.269908, 7.853982,
                   26.179939, 47.123890, 311.541271, 157.734131, 111.919238, 53.014376, 392.699082, 58.904862,
                   294.524311, 141.371669, 52.359878, 114.537232, 15.707963, 47.123890, 147.262156, 23.561945,
                   16.755161, 26.179939)

filtered_osf <- c(22.885584, 24.905062, 8.816039, 6.877041, 8.782836, 5.853161, 4.088499, 11.792189, 17.533123, 7.043904,
                  9.189750, 11.216450, 22.821028, 27.308823, 10.652498, 18.590091, 5.973716, 4.387657, 5.091982, 5.973609,
                  5.012901, 22.547434, 11.238273, 19.235493, 6.206930, 3.276575, 3.791221, 3.460380, 5.404704, 12.278297,
                  4.604634, 10.614706, 5.425239, 3.450711, 2.214432, 2.573192, 5.037149, 40.996842, 26.001749, 6.615399,
                  8.947295, 3.335943, 48.198579, 10.110514, 9.286836, 7.668401, 17.463995, 14.653925, 10.574502, 8.403515)

A_initial <- max(filtered_sp14)
mean_initial <- mean(filtered_osf)
sd_initial <- sd(filtered_osf)

# Set up the non-linear least squares model
nls_model <- nls(filtered_sp14 ~ A * exp(-((filtered_osf - mean)^2) / (2 * sd^2)),
                 start = list(A=A_initial, mean=mean_initial, sd=sd_initial),
                 control = nls.control(maxiter = 1000))

plot(filtered_osf, filtered_sp14, main="Non-linear Regression", xlab="X", ylab="Y", pch=19, col="blue")

运行后得到模型系数:

> coefficients(nls_model)
        A      mean        sd 
284.14143  25.33275 -16.82272

其中均值符合预期,但标准差应为正数,请问为何nls()会返回负标准差?


解答

这是因为你用的正态曲线方程里,标准差s是以平方项s²的形式出现的——不管s是正还是负,s²的结果都是正数,对拟合的曲线形状没有任何影响。nls()做非线性最小二乘拟合时,只是找到能最小化残差平方和的参数值,它不会自动考虑标准差必须为正的统计意义,所以如果迭代过程中找到负的s能达到局部最优解,就会直接返回这个值。

解决办法

有几种方式可以强制标准差为正:

  1. 拟合方差参数而非标准差
    修改模型,把sd²作为待拟合的参数(比如命名为var),最后再开平方得到标准差:

    nls_model <- nls(filtered_sp14 ~ A * exp(-((filtered_osf - mean)^2) / (2 * var)),
                     start = list(A=A_initial, mean=mean_initial, var=sd_initial^2),
                     control = nls.control(maxiter = 1000))
    # 计算标准差
    sd_estimate <- sqrt(coef(nls_model)["var"])
    
  2. 在模型中使用绝对值约束
    直接在方程里用abs(sd)代替sd,确保平方项始终为正:

    nls_model <- nls(filtered_sp14 ~ A * exp(-((filtered_osf - mean)^2) / (2 * abs(sd)^2)),
                     start = list(A=A_initial, mean=mean_initial, sd=sd_initial),
                     control = nls.control(maxiter = 1000))
    
  3. 使用带参数约束的优化方法
    可以用nlsLM()(来自minpack.lm包),它支持设置参数的上下限:

    library(minpack.lm)
    nls_model <- nlsLM(filtered_sp14 ~ A * exp(-((filtered_osf - mean)^2) / (2 * sd^2)),
                       start = list(A=A_initial, mean=mean_initial, sd=sd_initial),
                       lower = c(A=0, mean=-Inf, sd=0.0001),  # 限制sd大于0
                       control = nls.control(maxiter = 1000))
    

内容的提问来源于stack exchange,提问作者fre1990

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 16:34:52