我有一些很短的时间序列(可能是30到100个时间点),并且它们具有一般形状:它们从高位开始,快速下降,可能或者可能不是在零附近高原,然后再回升。如果他们不是高原,他们看起来像一个简单的二次方,如果他们做高原,你可能有一长串零。
我正在尝试使用lmfit
模块来拟合连续的分段线性曲线。 我想推断线条在哪里改变渐变,也就是说,我想知道曲线“qualitatitively”改变渐变的位置。我想知道渐变何时停止下降,以及当它再次开始增加时,一般而言。我遇到了一些问题:
lmfit
似乎至少需要两个参数,因此我必须通过_
。 could not broadcast input array from shape (something) into shape (something)
错误这是一些代码。首先,我的目标函数,最小化。
def piecewiselinear(params, data, _) :
t1 = params["t1"].value
t2 = params["t2"].value
m1 = params["m1"].value
m2 = params["m2"].value
m3 = params["m3"].value
c = params["c"].value
# Construct continuous, piecewise-linear fit
model = np.zeros_like(data)
model[:t1] = c + m1 * np.arange(t1)
model[t1:t2] = model[t1-1] + m2 * np.arange(t2 - t1)
model[t2:] = model[t2-1] + m3 * np.arange(len(data) - t2)
return model - data
然后我打电话,
p = lmfit.Parameters()
p.add("t1", value = len(data)/4, min = 1, max = len(data))
p.add("t2", value = len(data)/4*3, min = 2, max = len(data))
p.add("m1", value = -100., max=0)
p.add("m2", value = 0.)
p.add("m3", value = 20., min = 1.)
p.add("c", min=0, value = 800.)
result = lmfit.minimize(piecewiselinear, p, args = (data, _) )
该模型是,在某个时间t1,线的梯度发生变化,同样的情况发生在t2。需要推断出这两个参数以及线段的梯度(和一个截距)。
我可以使用MCMC方法做到这一点,但我有太多这些系列,而且需要很长时间。
部分追溯:
15 model = np.zeros_like(data)
16 model[:t1] = c + m1 * np.arange(t1)
---> 17 model[t1:t2] = model[t1-1] + m2 * np.arange(t2-t1)
18 model[t2:] = model[t2-1] + m3 * np.arange(len(data) - t2)
19
ValueError: could not broadcast input array from shape (151) into shape (28)
时间序列的几个例子:
欢迎任何和所有建议。非常感谢你。
答案 0 :(得分:0)
这是一个来自一个相当蛮力的3-pwlin钳工的情节; 将交换测试用例的粗略代码。
另外,有几个链接:
Fit-piecewise-linear-data
在dsp.stack上可能会给你一些想法;添加了一点
Dynamic programming。
github.com/NickFoubert/simple-segment
有python用于分段,例如心电图有max_error(不是件数),
来自Keogh等人的一篇好文章,
An online algorithm for segmenting time series,2001,8p。
还有一种可能的替代方案:你能否在p
,y ~ x^p
中使用log y ~ p log x^2
。
(将x
转换为[-1 .. 1]和y
> 1e-6左右后)?
这将是健壮,快速,并且易于策划和理解
人们应该重视目的
这样错误大致平淡而正常
另外一个人可以将左右两半分开p
p'
。
答案 1 :(得分:0)
走下蛮力路线似乎可以解决问题。我只是测试开关点的所有组合并选择最合适的。它非常快速且可以相当稳健。这是一个特别适合的结果。
我强迫第二行的渐变为零。这样可以确保我们无法适合两条线并且非常适合一条线,这可能会获得更高的分数(我在这里使用R ^ 2值的总和)。绿色标记切换点,这些应该适用于我的应用程序。
我想学习更优雅的想要做到这一点,但与此同时,这是一个选择...