2017-03-06 117 views
1

我嘗試運行代碼的Python NumPy的內存佈局

import numpy as np 
a = np.zeros((3,2)) 
b = a.T.reshape(3*2) 
b[0] = 99 
a 
array([[0,0], 
     [0,0], 
     [0,0]]) 

這裏的問題是,在numpy的的重塑函數返回原始數組的一個觀點,如果任何改變發生在視圖對象或主要對象將貫穿整個觀點和主要目標。

但在上述情況下,它不會發生。請解釋。

回答

1

official document給出了一個回答你的問題。

這將是可能的話新的查看對象;否則,它將成爲副本。請注意,不保證返回數組的內存佈局(C-或Fortran-連續)。

+0

如果它創建它的一個觀點,然後np.may_share_memory應返回true,但在我的問題的情況下,它返回false我不知道爲什麼但是如果在重塑函數中,而不是象(3 * 2)那樣寫入,如果你寫(3,2)np.may_share_memory函數返回true。我不是很確定,但是我猜測有一些與3 * 2相關的東西可以複製它我猜 – Mayank

2

你正在做最後的重塑不能在原來的內存佈局的進步表示:

orig     1 2 3 4 5 6 ok, strides 2, 1 

transpose    1 3 5 2 4 6 ok, strides 1, 2 

reshaped transpose 1 3 5 2 4 6 impossible 

我不是100%肯定,我理解這一點正確的(或者,更準確地說,我「M幾乎100%地肯定我沒有),但可能有一些obscure cases當一個副本寫回。無論如何,這不是其中之一。

+0

a = np.array([[1,2],[3,4],[4, 5]]) 然後在給出 陣列([[1,3,4], [2,4,5]]) 然後 aTreshape(3,2)給出 陣列([[1,3 ], [4,2], [4,5]]) 整形發生但沒有完全適當的格式我不明白爲什麼會發生這種情況 – Mayank

+0

我寫的數字並不是指數值,而是指內存位置。內存是線性的,任何多維數組都被劃分爲一組內存地址。爲了保持可管理性,每個維度都有一個_stride_。數組的單元格(2,4)位於內存位置array_base + stride0 x 2 + stride1 x 4.一個新數組通常是C連續的,即最後一個步長爲1,最後一個形狀爲[-1]等等。轉移交換stride0和stride1。 1d數組只有stride0。該示意圖演示了原始佈局不適應扁平轉置的原因。 –

1

reshape文檔

你能想到的整形作爲第一脫散的陣列(使用給定的索引順序),然​​後使用相同種類的索引的插入從拆紗數組中的元素到新陣列的訂購用於散列

transpose是一個視圖,但改變形狀,步幅和順序。通過沿着列而不是跨行來獲取原始順序中的元素。但現在嘗試平移轉置 - 按C順序。元素將被洗牌。原始1 2 3 4 5 6 ...變成1 4 7 2 5 8 3 ...您不能在沒有複製的情況下獲得該訂單。

In [48]: a=np.arange(1,7).reshape(3,2) 
In [49]: a 
Out[49]: 
array([[1, 2], 
     [3, 4], 
     [5, 6]]) 

arange產生[1,2,3....]。這些數據緩存仍用於a,您可以通過跨行閱讀「恢復」它。

In [50]: b = a.T 
In [51]: b 
Out[51]: 
array([[1, 3, 5], 
     [2, 4, 6]]) 

移調通過改變形狀,進展和順序生成。現在是訂單='F'。 (我可以.flags.__array_interface__表明這一點。這是一個觀點,並且仍然共享原始arange值。只是現在,因爲進步和秩序的,你讀下來列。

In [52]: c = b.reshape(3,2) 
In [53]: c 
Out[53]: 
array([[1, 3], 
     [5, 2], 
     [4, 6]]) 

這有相同的形狀,長足的進步,和「C」順序a,但數據緩衝區是原[1,3,5,2..]重新排序的副本。這是相同的順序,你會從b通過跨行閱讀得到。


另一種方式來看待在c的重新排序是跟蹤原始元素順序1,2,3 ...

[0,0],[1,1],[0,1],[2,0],[1,0],[2,1] 

或用2名索引列表:

In [57]: a[[0,0,1,1,2,2],[0,1,0,1,0,1]] # regular pattern 
Out[57]: array([1, 2, 3, 4, 5, 6]) 
In [58]: b[[0,1,0,1,0,1],[0,0,1,1,2,2]] # same, switch order 
Out[58]: array([1, 2, 3, 4, 5, 6]) 
In [59]: c[[0,1,0,2,1,2],[0,1,1,0,0,1]] # a jumble 
Out[59]: array([1, 2, 3, 4, 5, 6]) 
+0

我完全同意轉置共享內存空間。 a與b共享內存,但爲什麼b不與c共享空間。 – Mayank

+0

在'a','b'和'c'的二維顯示中,追蹤1,2,3 ...在那些簡單的Z字形圖案上。但在'c'上它是一個混亂的 - 對角線,向上,雙對角線等'numpy'不能使用步幅和形狀從原來的1,2,3產生'c' ... – hpaulj

+0

Causerie其中c得到分開的記憶..正確的! – Mayank