我有一个 N 维 numpy 数组S
。每次迭代,这个数组中的一个值都会改变。
我有第二个数组,G
它存储 的梯度S
,由 numpy 的gradient()
函数计算得出。目前,我的代码G
每次更新时都会不必要地重新计算所有内容S
,但这是不必要的,因为只有一个值S
发生了变化,所以我只需要重新计算中的1+d*2
值G
,其中d
是 中的维数S
。
如果我知道数组的维数,这将是一个更容易解决的问题,但是在没有这些知识的情况下我提出的解决方案效率非常低(并不比仅仅重新计算所有的 更好G
)。
有没有一种有效的方法来仅重新计算中的必要值G
?
编辑:根据要求添加我的尝试
S
该函数返回一个向量,表示atcoords
在每个维度上的梯度。它计算这个而不计算S
每个点的梯度,但问题是它似乎不是很有效。
它在某些方面看起来与已经发布的答案相似,但也许有一些效率很低的地方?
想法如下:我遍历每个维度,创建一个仅在该维度中作为向量的切片。对于这些切片中的每一个,我计算梯度并将该梯度中的适当值放入返回的向量中的正确位置grad
。
min()
和的用途max()
是处理边界条件。
def getSGradAt(self,coords) :
"""Returns the gradient of S at position specified by
the vector argument 'coords'.
self.nDim : the number of dimensions of S
self.nBins : the width of S (same in every dim)
self.s : S """
grad = zeros(self.nDim)
for d in xrange(self.nDim) :
# create a slice through S that has size > 1 only in the current
# dimension, d.
slices = list(coords)
slices[d] = slice(max(0,coords[d]-1),min(self.nBins,coords[d]+2))
# take the middle value from the gradient vector
grad[d] = gradient(self.s[sl])[1]
return grad
问题是这不会很快运行。事实上,只取整个数组的梯度S
似乎跑得更快(对于nBins = 25
和nDim = 4
)。
再次编辑,添加我的最终解决方案
这是我最终使用的。此函数更新S
,将 at 的值更改为X
amount change
。G
然后,它使用 Jaime 提出的技术的变体进行更新。
def changeSField(self,X,change) :
# change s
self.s[X] += change
# update g (gradient field)
slices = tuple(slice(None if j-2 <= 0 else j-2, j+3, 1) for j in X)
newGrads = gradient(self.s[slices])
for i in arange(self.nDim) :
self.g[i][slices] = newGrads[i]