2013-07-21 37 views
1

我有一個N維numpy陣列S。每次迭代,數組中的恰好一個值將會改變。有效重新計算具有未知維度的numpy陣列的梯度

我有第二個數組,G,它存儲S,如numpy的gradient()函數計算的梯度。目前,我的代碼不必要地重新計算所有G每次我更新S,但這是不必要的,因爲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 = 25nDim = 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] 
+1

'如果輸入是一維和數組列表,如果輸入有許多比1其它尺寸的gradient'返回數組。它看起來並不意味着與運行時確定的維度數組一起使用,並且該列表將排除可以對數組執行的大部分巧妙的片分配。 – user2357112

回答

1

您的問題很值得您打個比較好的答案:發佈效率低下的代碼總是一個好主意,這樣潛在的回答者可以更好地幫助您。無論如何,讓我們說你知道已經改變點的座標,並且將它們存儲在一個名爲coords的元組中。首先,讓我們構建涵蓋切片您點的元組:

slices = tuple(slice(None if j-1 <= 0 else j-1, j+2, 1) for j in coords) 

您可能希望限制擴展到j-2j+3使梯度利用中央差異儘可能計算,但它會慢一些。

現在,您可以更新您數組做這樣的事情:

G[slices] = np.gradient(N[slices]) 
+0

謝謝你的迴應。這似乎是正確的方向。爲了使它與漸變兼容(請參閱上面的user2357112所做的註釋),所需的分配比您建議的要多一點。 '對於我在arange(len(g)): g [i] [slices] = s [i]' – weemattisnot

0

Uhmmm,我可以更好地工作,如果我有一個例子,但關於剛剛創建一個輔助陣列,S2(順便說一下,我會選擇更長,更有意義的名稱爲您的變量)是什麼,並重新計算它的漸變,G2,然後將它引回到G?

另一個問題是:如果你不知道S的維度,你將如何改變特定元素的變化?你只是重新計算整個S?

我建議你澄清這件事情,以便人們可以更好地幫助你。 乾杯!

+0

我知道數組在運行時的維數,但不是在那之前。 – weemattisnot

+0

感謝您的回覆,但我看不到輔助數組S2會如何幫助。你能澄清嗎?再次感謝。 – weemattisnot

+0

當然,我可以嘗試澄清。你感到不舒服的是重新計算整個數組S的梯度。如果你改變S [ii,jj](假設兩個維度),那麼將改變的梯度的唯一值就是那些whitin [ii-1: ii + 2]和[jj-1:jj + 2],即以[ii,jj]爲中心的正方形3x3。其餘的都不受這種變化的影響,對吧?所以,我建議在[ii,jj]周圍「切割」一片S,以便重新計算梯度,然後將其插入到G中。爲此,您需要在[ii,jj]周圍有一個5x5的方塊,將採取你需要的3x3。 – Jblasco