R:拟合 S 形曲线?

R: fitting a sigmoidal curve?

我正在对我的电费单进行一些分析,并试图提取空调设备的使用量。通过假设“正常”用电量在一年中相当稳定,并且 A/C 仅在较热的月份开启,我能够估计出一些分离。

图中有两行:

在尝试通过这种总累积使用来拟合一个好的模型时,R 中的 nls 函数在初始参数估计 处给出了可怕的 奇异梯度矩阵。使用不同的软件 (JMP) 我可以获得良好的初始参数,这反映在紫色拟合曲线中。

知道如何使用 R 获得参数估计而不会出现错误吗?

nls 模型

nls(elec_use_mean ~ b0 + b1 * month + a1 / (a2 + a3 * exp(a4 * month)),
    start = list(b0 = 100, b1 = 310, a1 = 1300, a2 = 0.3, a3 = 600, a4 = -1.2),
    data = cumulative
    )


Error in nlsModel(formula, mf, start, wts, scaleOffset = scOff, nDcentral = nDcntr) : 
  singular gradient matrix at initial parameter estimates

数据:

month,elec_use_mean
1,461.46
2,839.46
3,1197.92
4,1553.59
5,2093.34
6,3096.42
7,4353.67
8,5652.51
9,6729.84
10,7296.92
11,7634.34
12,8071.84

下面是图片

另一种参数化 S 形曲线的方法是使用 tanh,它可以生成一个只有 4 个参数而不是 6 个参数的很好的收敛模型。公式也可以这样写具有明确含义的参数有助于关闭初始估计:

elec_use_mean ~ b1 * month + 6 * b0 * (1 + tanh(a1 * (month - a0)))

其中:

  • b0 是一年中每月的平均空调支出
  • b1 是全年平均每月背景电费支出
  • a0是一年中空调使用率最高的月份
  • a1 是衡量“季节性”空调使用情况的指标,其中 0 根本不是季节性的(每个月使用空调总量的 1/12), 1 表示大约 76% 的空调使用是在最热的两个月。
model <- nls(elec_use_mean ~ b1 * month + 6 * b0 * (1 + tanh(a1 * (month - a0))),
    start = list(b0 = 330, b1 = 300, a0 = 7, a1 = 0.5),
    data = cumulative
    )

summary(model)
#> 
#> Formula: elec_use_mean ~ b1 * month + 6 * b0 * (1 + tanh(a1 * (month - 
#>     a0)))
#> 
#> Parameters:
#>     Estimate Std. Error t value Pr(>|t|)    
#> b0 294.99540   16.88446   17.47 1.18e-07 ***
#> b1 379.93397   16.34690   23.24 1.25e-08 ***
#> a0   7.07014    0.05877  120.31 2.55e-14 ***
#> a1   0.61313    0.05616   10.92 4.39e-06 ***
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Residual standard error: 70.82 on 8 degrees of freedom
#> 
#> Number of iterations to convergence: 8 
#> Achieved convergence tolerance: 2.64e-06

通过生成一组平滑的预测,我们可以看到这非常适合:

library(ggplot2)

new_df <- data.frame(month = seq(1, 12, 0.1))
new_df$elec_use_mean <- predict(model, new_df)

ggplot(cumulative, aes(month, elec_use_mean)) +
  geom_point() +
  geom_line(data = new_df, linetype = 2) +
  scale_x_continuous(breaks = 1:12, labels = month.abb)

reprex package (v2.0.1)

于 2022-04-21 创建

谢谢大家。在Allan的帮助下,我得到了一个很好的答案。

有关详细信息,请参阅 https://github.com/robhanssen/utility/blob/main/analysis/cumulative_model%20alt.r

最终输出: