Numpy 广播机制(两个不同维度对象进行数学运算)
1. 數(shù)組相加
一個 2*5 維的數(shù)組對象和一個 1 維的數(shù)組對象進行相加,結(jié)果會怎樣?
In [1]: import numpy as npIn [2]: a = np.arange(10).reshape(2,5)In [3]: a
Out[3]:
array([[0, 1, 2, 3, 4],[5, 6, 7, 8, 9]])In [4]: b = np.array([2])In [5]: a + b
Out[5]:
array([[ 2, 3, 4, 5, 6],[ 7, 8, 9, 10, 11]])In [6]:
可以看到在維度不同時是將小維度的值全部匹配到大維度的值上,即把 a 中的每個元素都加上 b 的元素。但是看看下面的計算。
In [12]: c = np.array([1,2])In [13]: c
Out[13]: array([1, 2])In [14]: a + c
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-14-e81e582b6fa9> in <module>
----> 1 a + cValueError: operands could not be broadcast together with shapes (2,5) (2,) In [15]: c.shape
Out[15]: (2,)In [16]:
為什么 2*5 維的數(shù)組和 2 維的數(shù)組相加會報錯呢? 這是因為 Numpy 的廣播機制。因為 a、c 按照廣播的規(guī)則,無法達成一致的 shape,所以拋出異常。
因為廣播機制的存在,b 數(shù)組會適配 a 數(shù)組,按照第 0、1 維度,分別發(fā)生一次廣播,廣播后的 b 變?yōu)?#xff1a;
In [21]: b
Out[21]: array([2])In [22]: b = np.tile(b,(2,5))In [23]: b
Out[23]:
array([[2, 2, 2, 2, 2],[2, 2, 2, 2, 2]])In [24]:
然后,執(zhí)行再執(zhí)行加法操作時,因為 a、b 的 shape 變得完全一致,所以就能實現(xiàn)相加操作了。
2. 廣播規(guī)則
從上面我們可以看到,不是任意 shape 的多個數(shù)組,操作時都能廣播到一起,必須滿足一定的約束條件。
NumPy首先會比較最靠右的維度,如果最靠右的維度相等或其中一個為 1,則認為此維度相等;- 那么,再繼續(xù)向左比較,如果一直滿足,則認為兩者兼容;
- 最后,分別在對應(yīng)維度上發(fā)生廣播,以此補齊直到維度一致;
如下,兩個數(shù)組 a、b,shape 分別為 (2,1,3)、(4,3), 它們能否廣播兼容?我們來分析下。
a = np.arange(6).reshape(2,1,3) # shape: (2,1,3)
b = np.arange(12).reshape(4,3) # shape: (4,3)
- 按照規(guī)則,從最右側(cè)維度開始比較,數(shù)組 a, b 在此維度上的長度都為 3,相等;
- 繼續(xù)向左比較,a 在此維度上長度為 1,b 長度為 4,根據(jù)規(guī)則,也認為此維度是兼容的;
- 繼續(xù)比較,但是數(shù)組 b 已到維度終點,停止比較。
結(jié)論,數(shù)組 a 和 b 兼容,通過廣播能實現(xiàn) shape 一致。
3. 廣播步驟
下面看看,數(shù)組 a 和 b 廣播操作實施的具體步驟。
In [1]: import numpy as npIn [2]: a = np.arange(6).reshape(2,1,3)In [3]: b = np.arange(12).reshape(4, 3)In [4]: a
Out[4]:
array([[[0, 1, 2]],[[3, 4, 5]]])In [5]: b
Out[5]:
array([[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]])In [6]:
維度編號從 0 開始,數(shù)組 a 在維度 1 上發(fā)生廣播,復(fù)制 4 次:
In [6]: a = np.repeat(a, 4, axis=1)In [7]: a
Out[7]:
array([[[0, 1, 2],[0, 1, 2],[0, 1, 2],[0, 1, 2]],[[3, 4, 5],[3, 4, 5],[3, 4, 5],[3, 4, 5]]])In [8]:
此時,數(shù)組 a 和 b 在后兩個維度一致,但是數(shù)組 b 維度缺少一維,所以 b 也會廣播一次:
In [8]: b = b[np.newaxis,:,:] # 首先增加一個維度In [9]: b
Out[9]:
array([[[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]]])In [10]: b = np.repeat(b,2,axis=0) # 在維度 0 上復(fù)制 2 次In [11]: b
Out[11]:
array([[[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]],[[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]]])In [12]:
經(jīng)過以上操作,數(shù)組 a 和 b 維度都變?yōu)?(2,4,3),至此廣播完成,做個加法操作:
In [11]: b
Out[11]:
array([[[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]],[[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]]])In [12]: a
Out[12]:
array([[[0, 1, 2],[0, 1, 2],[0, 1, 2],[0, 1, 2]],[[3, 4, 5],[3, 4, 5],[3, 4, 5],[3, 4, 5]]])In [13]: a + b
Out[13]:
array([[[ 0, 2, 4],[ 3, 5, 7],[ 6, 8, 10],[ 9, 11, 13]],[[ 3, 5, 7],[ 6, 8, 10],[ 9, 11, 13],[12, 14, 16]]])In [14]:
驗證我們自己實現(xiàn)的廣播操作,是否與 NumPy 中的廣播操作一致,直接使用原始的 a 和 b 數(shù)組相加,看到與上面得到的結(jié)果一致。
In [14]: a = np.arange(6).reshape(2,1,3)In [15]: b = np.arange(12).reshape(4,3)In [16]: a + b
Out[16]:
array([[[ 0, 2, 4],[ 3, 5, 7],[ 6, 8, 10],[ 9, 11, 13]],[[ 3, 5, 7],[ 6, 8, 10],[ 9, 11, 13],[12, 14, 16]]])In [17]:
至此,我們已經(jīng)了解了廣播的規(guī)則,所以再遇到如下的廣播錯誤時,我們就可以很清楚的知道該如何解決這樣的錯誤。
ValueError: operands could not be broadcast together with shapes (2,5) (2,)
總結(jié)
以上是生活随笔為你收集整理的Numpy 广播机制(两个不同维度对象进行数学运算)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 爱情誓言个性签名浪漫
- 下一篇: 龙井多少钱一斤啊?