[英]Efficiently recalculating the gradient of a numpy array with unknown dimensionality
我有一個N維的numpy數組S
每次迭代,此數組中的一個值都會更改。
我有第二個數組G
,它存儲S
的梯度,由numpy的gradient()
函數計算得出。 目前,我每次更新S
時,我的代碼都不必要重新計算G
全部,但這是不必要的,因為S
只有一個值發生了變化,因此我只需要重新計算G
1+d*2
值,其中d
是S
的維數。
如果我知道數組的維數,這將是一個更容易解決的問題,但是在我缺乏這些知識的情況下,我想出的解決方案效率很低(實質上不比重新計算所有G
更好)。
是否有一種有效的方法來僅重新計算G
的必要值?
編輯:根據要求添加我的嘗試
該函數返回一個向量,該向量指示每個維度上coords
處S
的梯度。 它在不計算每個點的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
數量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]
您需要解決的問題很多,您可以獲得一個好的答案:發布效率低下的代碼始終是一個好主意,以便潛在的答復者可以更好地為您提供幫助。 無論如何,可以說您知道已更改點的坐標,並將其存儲在名為coords
的元組中。 首先,讓我們構造一個包含您要點的切片元組:
slices = tuple(slice(None if j-1 <= 0 else j-1, j+2, 1) for j in coords)
您可能希望將限制擴展到j-2
和j+3
以便在可能的情況下使用中心差來計算梯度,但是會慢一些。
您現在可以執行以下操作來更新數組:
G[slices] = np.gradient(N[slices])
嗯,如果有一個示例,我會做得更好,但是僅創建一個輔助數組S2(順便說一句,我會為您的變量選擇更長更有意義的名稱)並重新計算它的梯度G2和然后將其引入G?
另一個問題是:如果您不知道S的維數,您如何更改所更改的特定元素? 您只是重新計算整個S?
我建議您澄清這些事情,以便人們可以更好地幫助您。 干杯!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.