【发布时间】:2018-03-19 16:46:38
【问题描述】:
当我知道只有一小部分项发生变化时,我想找到一种快速更新残差平方和的方法。让我更详细地描述这个问题。
我有 N 个来自嘈杂阶跃函数数据的数据点。
N = 100000
realStepList = [200, 500, 900]
x = np.zeros(N)
for realStep in realStepList:
x[realStep:] += 1
x+=np.random.randn(len(x))*0.1 #Add noise
我想计算此数据的残差平方和以及任意步骤位置列表。这是我的做法。
a = [0, 250, 550, N]
def Q(x, a):
q = np.sum([np.sum((x[ai:af] - i)**2) for i, (ai,af) in enumerate(zip(a[:-1],a[1:]))])
return q
a 是我的潜在步骤列表。使用始终将0 作为第一个元素,将N 作为最后一个元素的列表更容易。
这是相对较慢的,因为它是N 平方的总和。但是,我意识到,如果我将a 更改相对较小的量,这些N 术语中的大部分将保持不变,这意味着我不必再次计算它们。
假设我已经像上面那样计算了Q(x,a)。我现在有另一个列表
b = [aa + dd for aa, dd in zip(a, d)]
其中d 是两个列表之间的差异。我不想像上面那样计算Q(x,b)(N 元素的另一个总和),我想找到
deltaQ(x, a, d) 这样
Q(x, b) = Q(x,a) + deltaQ(x, a, d)
我写过这样的函数,但是速度慢而且草率。实际上,它比Q 慢!
def deltaQ(x, a, d):
z = np.zeros(len(x))
J = np.zeros(len(x))
s = 0
for j, [dd, aa] in enumerate(zip(d, a[1:-1])):
if dd >= 0:
z[aa:aa+dd] += 1
s += sum(x[aa:aa+dd])
if dd < 0:
z[aa+dd:aa] += -1
s += -sum(x[aa+dd:aa])
J[aa:] += 1
dq = 2*s - sum((J**2 - (J-z)**2))
return dq
这个想法是识别x 中将受到影响的所有点。例如,如果原始列表是a = [0, 5, 10] 和b = [0, 7, 10],那么只有与x[5:7] 对应的项会在总和中发生变化。我使用列表z 跟踪这一点。然后我根据这个计算变化。
我不认为我是世界上第一个遇到这个问题的人。所以我的问题是:
有没有一种快速的方法来计算残差平方和的差异,因为这通常比从头重新计算新的总和要少得多的元素?
【问题讨论】:
-
次要注意,
b = [aa + dd for zip(a, d)]语法无效。 -
在进行这些小改动时,
a的形状是否保持不变?换句话说,只有值会改变还是步数也会改变?另外,你能举一个d的例子吗? -
@Graipher 最终我想改变形状,但我对答案很感兴趣,如果它也没有改变。在我给出的示例中,d = [2],因为只有一步,它从 5 -> 7
-
更改了合成器,@droooze。感谢您的提醒。
-
我读了几篇文章,才意识到您并没有要求找到真正的台阶位置。如果你是,我也可以帮助你:)