【发布时间】:2013-07-20 09:57:36
【问题描述】:
我有一个 N 维 numpy 数组 S。每次迭代,这个数组中只有一个值会改变。
我有第二个数组G,它存储S 的梯度,由numpy 的gradient() 函数计算得出。目前,每次更新S 时,我的代码都会不必要地重新计算所有G,但这是不必要的,因为S 中只有一个值发生了变化,所以我只需要重新计算@987654329 中的1+d*2 值@,其中d 是S 中的维数。
如果我知道数组的维数,这将是一个更容易解决的问题,但是在没有这些知识的情况下我提出的解决方案效率非常低(并不比重新计算所有 G 好很多) )。
有没有一种有效的方法来仅重新计算G 中的必要值?
编辑:根据要求添加我的尝试
该函数返回一个向量,表示S 在每个维度上coords 处的梯度。它计算这个而不计算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,将X 的值更改为change。然后,它使用 Jaime 提出的技术的变体更新 G。
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]
【问题讨论】:
-
gradient如果输入是一维的,则返回一个数组;如果输入的维数不是 1,则返回一个数组列表。看起来它不适合与运行时确定维度的数组,并且该列表将排除您可以对数组进行的大多数巧妙的切片分配。
标签: python numpy multidimensional-array slice