【问题标题】:how can I estimate a series of linear segments to fit an exponential curve?如何估计一系列线性段以拟合指数曲线?
【发布时间】:2021-08-06 14:12:21
【问题描述】:

这可能更像是一个数学问题,但最终我想在 R 中执行这个。如果我有一个基本的指数曲线,我想了解如何使用 R 将一系列线性函数应用于尽我所能拟合指数曲线。原因是线性线是一种特定的关系,这些线代表一个变化率,在每个拐点,变化率都会增加。这些拐点对于用户来说很重要。我附上了我要完成的工作的粗略图。

黑线是指数曲线,红线是一系列线性线,橙色圆圈当然代表线相交的地方。我可以随意地执行这项任务,只需选择任意数据点并构建线性模型,直到找到我认为最适合指数曲线的组合,但我知道还有比这更好的方法。

下面是一些可能有帮助的代码:

data <- c(1:34)
sales <- c(20000000, 25000000,  30000000,   35000000,   43000000,    
50000000,   57000000,   65000000,   72000000,   80000000,   89000000,    
97000000,   108000000,  118000000,  128000000,  138000000,  150000000,   
161000000,  174000000,  187000000,  203000000,  218000000,  235000000,   
251000000,  260000000,  280000000   ,293000000, 310000000,  333000000,   
363000000,  390000000,  415000000,  454000000,  540000000)
data2 <- data.frame(data,sales)

plot(data2$data,data2$sales)

【问题讨论】:

  • 我确实建议您上传代码;那么社区将有一些事情要做。欢迎!

标签: r linear-regression curve-fitting exponential


【解决方案1】:

这是一个拟合由三个线性段组成的分段函数的问题。

https://fr.scribd.com/document/380941024/Regression-par-morceaux-Piecewise-Regression-pdf 中解释了一个非常简单的方法(不是迭代的,不需要初始猜测)。处理 pp.20-22 中的方便案例

下面给出了一个数值示例。下图显示了结果:

x = 0.17 0.23 0.293 0.349 0.401 0.457 0.509 0.563 0.619 0.668 0.713 0.756 0.798 0.832 0.864 0.889 0.912 0.935 0.957 0.977

y = 0.09 0.094 0.09 0.067 0.082 0.114 0.141 0.173 0.212 0.247 0.278 0.325 0.408 0.459 0.518 0.584 0.631 0.698 0.78 0.859

为了使代码的实现和检查更容易,演算如下所示:

拟合的标准是一次拍摄整个数据的最小均方误差(不是逐段)。

注意:上面的例子选择了几个点 (20)。这是为了便于检查。缺点是与要优化的参数(5)的数量相比,点的数量少是失败或偏差的风险。该方法基于数​​值积分,需要尽可能多的点才能获得更好的精度。

【讨论】:

  • 再一次,我喜欢这个解决方案的简单性。但是,在这种情况下,我有疑问。在两个线性步骤中的每一个中,系数的误差很容易通过标准矩阵运算来计算。 .现在第一步的结果以非线性方式进入第二步,即在阶跃函数中。由于 H 的导数是 delta(在 Schwartz 分布的框架内),传播误差是否有意义?这将如何完成?这似乎有点问题,因为最终误差不是步进位置的连续函数。
  • 另一方面,考虑到数据在两个函数之间跳转并且跳转位置的误差变得明显大于两个数据点之间的距离的更广阔的区域,我预计步位置误差对第二个线性拟合参数的误差。
  • @mikuszefski。你的怀疑是有道理的。如果函数的形状与由三个线性段组成的分段函数不太远,则所提出的简化方法很方便。这不是指数曲线的情况。尤其是 OP 提供的新数据。因此,Ben Bolker 的后一个答案更可取。
  • 顺便说一句,在链接的PDF第6页右下角的矩阵应该是F2k和G2k吧?
  • @mikuszefski。你说的对。布拉沃指出错字。
【解决方案2】:

使用segmented 包(参见this question):

library(segmented)
m1 <- lm(sales ~ data, data = data2)  ## initial fit
s1 <- segmented(m1)     ## one breakpoint
s2 <- segmented(m1, psi = c(10,25))  ## two breakpoints, estimated starting values
plot(sales ~ data, data = data2)
lines(data2$data, predict(s1))
lines(data2$data, predict(s2), col = 2, lwd =2)

结果:

s2
Call: segmented.lm(obj = m1, psi = c(10, 25))

Meaningful coefficients of the linear terms:
(Intercept)         data      U1.data      U2.data  
    5942857      7732143      7105220     26962637  

Estimated Break-Point(s):
psi1.data  psi2.data  
    15.72      29.65  

与@JJacquelin 提供的解决方案不同,您确实需要在估计 >1 个断点时提供断点的起始值,但它们只需要是合理的——尤其是对于简单/行为良好的数据,结果将是(几乎)对于一系列相似的起始值选择相同。

从数学上讲,我会很挑剔地说,指数曲线并没有真正的拐点——斜率不断地逐渐增加——但如果这是一种有用的方式来传达一些东西给观众,加油。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-22
    • 2012-09-15
    • 2016-02-13
    • 2017-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多