2014-03-05 51 views
8

鑑於3個numpy的數組:一個多維數組x,一個矢量y尾隨單尺寸,和一個矢量z沒有拖尾單尺寸,numpy的廣播切片陣列和矢量

x = np.zeros((M,N)) 
y = np.zeros((M,1)) 
z = np.zeros((M,)) 

的廣播操作的行爲變化取決於在向量表示和上下文:

x[:,0] = y  # error cannot broadcast from shape (M,1) into shape (M) 
x[:,0] = z  # OK 

x[:,0] += y  # error non-broadcastable output with shape (M) doesn't match 
       # broadcast shape(M,M) 
x[:,0] += z  # OK 

x - y   # OK 
x - z   # error cannot broadcast from shape (M,N) into shape (M) 

我知道我可以做到以下幾點:

x - z[:,None] # OK 

但我不明白這個明確的表示法會給我什麼。它當然不會購買可讀性。我不明白爲什麼表達x - y是好的,但x - z是不明確的。

爲什麼Numpy會處理帶有或不帶尾隨單獨尺寸的矢量?

編輯:documentation指出:兩個維度是兼容當它們相等時,或它們中的一個是1,但yz均爲功能M x 1矢量,由於M x 0向量不包含任何元素。

+0

的一個關鍵點是,'X [:0]'是一維。 'x [:,[0]]'是(M,1)。 'z [:] = y'可能會給出相同的錯誤。 – hpaulj

+0

'z'可以在不進行復制的情況下重新整形爲(M,1)或(1,M)。但從功能上來說,它更接近(1,M),因爲開始時的自動擴展。 – hpaulj

回答

4

約定是廣播將在數組形狀的開始處插入單身尺寸。這使得在數組的最後一個維度上執行操作變得很方便,所以(x.T - z).T應該可以工作。

如果它是自動決定其中x軸通過z匹配,像x - z的操作將導致一個錯誤,如果且僅當N == M,使得代碼難以進行測試。所以這個約定允許一些方便,同時對一些錯誤也很有效。

如果您不喜歡z[:, None]速記,也許您會發現z[:, np.newaxis]更清晰。

對於像x[:,0] = y這樣的任務可以使用,您可以使用x[:,0:1] = y來代替。

+0

你可以舉一個例子,說明單身人士維度有用嗎?我想要執行的常見操作是從矩陣中減去列平均值,但最直觀的方法'x - = np.mean(x,axis = 1)'實際上並不像人們希望的那樣工作。 – hbristow

+0

'x - = np.mean(x,axis = 0)'起作用並且也很有用! – joeln

0

使用,而不是陣列接口numpy的矩陣界面產生了desired broadcasting behaviours

x = np.asmatrix(np.zeros((M,N))) 
y = np.asmatrix(np.zeros((M,1))) 

x[:,0] = y    # OK 
x[:,0] = y[:,0]   # OK 
x[:,0] = y[:,0:1]  # OK 
x[:,0] += y    # OK 
x - y     # OK 
x - np.mean(x, axis=0) # OK 
x - np.mean(x, axis=1) # OK 
+0

另一方面,介紹各種其他問題。矩陣幾乎總是難以發現錯誤的來源。舉例來說,'*'操作符執行矩陣乘法,而不是元素明智的。如果你將它提供給一個期望數組的函數,那麼你就被擰緊了。 – Davidmh

0

一個治療(M,1)(M,)不同的好處是,使您可以指定對齊什麼尺寸,什麼尺寸廣播

假設你有:

a = np.arange(4) 
b = np.arange(16).reshape(4,4) 
# i.e a = array([0, 1, 2, 3]) 
# i.e b = array([[ 0, 1, 2, 3], 
# [ 4, 5, 6, 7], 
# [ 8, 9, 10, 11], 
# [12, 13, 14, 15]]) 

當你c = a + bab將在axis=1對齊和a將沿着axis=0廣播:

array([[0, 1, 2, 3], 
    [0, 1, 2, 3], 
    [0, 1, 2, 3], 
    [0, 1, 2, 3]]) 

但是,如果你要對齊abaxis=1axis=0和廣播呢?

array([[0, 0, 0, 0], 
    [1, 1, 1, 1], 
    [2, 2, 2, 2], 
    [3, 3, 3, 3]]) 

(M,1) VS (M,)差異,您可以指定對齊和廣播的維度。

(即如果(M,1)(M,)被同等對待,你怎麼告訴numpy的要在axis=1播出?)

+0

我的錯誤是從代數的角度來看待numpy數組,而不是通用容器。在上面突出顯示的情況下,'c = a.T + b'和'c = a + b',其中'a.shape ==(M,1)'將以對我直觀有意義的方式廣播。通過詢問爲什麼在numpy的設計中做出了特定的決定,我試圖理解哲學上的差異。謝謝你的幫助! – hbristow

+0

你是對的** 2D **'a.T + b'可以指定廣播首選項,但將其應用於更高維操作確實很難。我猜numpy的方法更一般。 – aha