给出两个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:A - B上执行B的广播减法。
我特别想使用广播,因为我正在处理的数组大小非常大(8456,8456)。我希望广播能够提供一个小的性能优化。
我尝试过改造阵列,但没有运气,我很难过。我无法使用Scikit。
答案 0 :(得分:2)
您可以通过在两个维度中平铺两次来展开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中产生大量开销。
或者,您可以view A
in blocks使用Scikit Image' skimage.util.view_as_blocks
并对其进行修改
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 :(得分:2)
方法#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
和4D
B
形状4D
A
有两个单身从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)
版本中减去其元素reshape
时的尺寸。减法后,我们重新形成sessions
以获得最终输出。因此,我们将有一个实现,如此 -
public ActionResult ClickCounter()
{
return View();
}
答案 2 :(得分:1)
如果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]])
答案 3 :(得分: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的视图,而不是构造的数组。