[英]Numpy: Broadcasting from submatrix
給定兩個2D數組:
A =[[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]]
B =[[1, 2],
[3, 4]]
A - B = [[ 0, -1, 1, 0],
[-2, -3, -1, -2],
[ 2, 1, 3, 2],
[ 0, -1, 1, 0]]
B的形狀為2,2,A的形狀為4,4。 我想對A進行廣播減法B:A-B。
我特別想使用廣播,因為我要處理的陣列大小非常大(8456,8456)。 我希望廣播將提供一個小的性能優化。
我試過重塑數組,但沒有運氣,而且很困惑。 我無法使用Scikit。
您可以通過將B
在兩個維度上平鋪兩次來展開B
:
print A - numpy.tile(B, (2, 2))
產量
[[ 0 -1 1 0]
[-2 -3 -1 -2]
[ 2 1 3 2]
[ 0 -1 1 0]]
但是,對於大型矩陣,這可能會在RAM中產生大量開銷。
或者,您可以使用Scikit Image的skimage.util.view_as_blocks
塊查看A
並在適當位置進行修改
Atmp = skimage.util.view_as_blocks(A, block_shape=(2, 2))
Atmp -= B
print A
這將導致,而無需不必要地重復B
[[ 0 -1 1 0]
[-2 -3 -1 -2]
[ 2 1 3 2]
[ 0 -1 1 0]]
方法#1:這是一種使用strides
的方法,該方法使用views
的概念而無需制作實際副本即可從A
減去,因此應該非常有效-
m,n = B.strides
m1,n1 = A.shape
m2,n2 = B.shape
s1,s2 = m1//m2, n1//n2
strided = np.lib.stride_tricks.as_strided
out = A - strided(B,shape=(s1,m2,s2,n2),strides=(0,n2*n,0,n)).reshape(A.shape)
樣品運行-
In [78]: A
Out[78]:
array([[29, 53, 30, 25, 92, 10],
[ 2, 20, 35, 87, 0, 9],
[46, 30, 20, 62, 79, 63],
[44, 9, 78, 33, 6, 40]])
In [79]: B
Out[79]:
array([[35, 60],
[21, 86]])
In [80]: m,n = B.strides
...: m1,n1 = A.shape
...: m2,n2 = B.shape
...: s1,s2 = m1//m2, n1//n2
...: strided = np.lib.stride_tricks.as_strided
...:
In [81]: # Replicated view
...: strided(B,shape=(s1,m2,s2,n2),strides=(0,n2*n,0,n)).reshape(A.shape)
Out[81]:
array([[35, 60, 35, 60, 35, 60],
[21, 86, 21, 86, 21, 86],
[35, 60, 35, 60, 35, 60],
[21, 86, 21, 86, 21, 86]])
In [82]: A - strided(B,shape=(s1,m2,s2,n2),strides=(0,n2*n,0,n)).reshape(A.shape)
Out[82]:
array([[ -6, -7, -5, -35, 57, -50],
[-19, -66, 14, 1, -21, -77],
[ 11, -30, -15, 2, 44, 3],
[ 23, -77, 57, -53, -15, -46]])
方法2:我們可以將A
和B
都reshape
為4D
形狀,其中B
具有兩個單例尺寸,當從A
4D
版本中減去其元素時,將沿其broadcasted
。 減去后,我們將重新調整為2D
形狀以進行最終輸出。 因此,我們將有一個實現,像這樣-
m1,n1 = A.shape
m2,n2 = B.shape
out = (A.reshape(m1//m2,m2,n1//n2,n2) - B.reshape(1,m2,1,n2)).reshape(m1,n1)
如果A的尺寸是B的尺寸的倍數,則此方法應該起作用:
A - np.tile(B, (int(A.shape[0]/B.shape[0]), int(A.shape[1]/B.shape[1])))
結果:
array([[ 0, -1, 1, 0],
[-2, -3, -1, -2],
[ 2, 1, 3, 2],
[ 0, -1, 1, 0]])
如果不想平鋪,則可以調整A的形狀以提取(2, 2)
個塊,並使用廣播減去B:
C = A.reshape(A.shape[0]//2, 2, A.shape[1]//2, 2).swapaxes(1, 2)
C - B
array([[[[ 0, -1],
[-2, -3]],
[[ 1, 0],
[-1, -2]]],
[[[ 2, 1],
[ 0, -1]],
[[ 3, 2],
[ 1, 0]]]])
然后向后交換軸並重塑形狀:
(C - B).swapaxes(1, 2).reshape(A.shape[0], A.shape[1])
這應該快得多,因為C是A上的視圖,而不是構造的數組。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.