broadcasting arrays in numpy

2019-08-19 10:01发布

I got an array and reshaped it to the following dimentions: (-1,1,1,1) and (-1,1):

 Array A:
[-0.888788523827  0.11842529285   0.319928774626  0.319928774626  0.378755429421  1.225877519716  3.830653798838]

A.reshape(-1,1,1,1):
[[[[-0.888788523827]]]


 [[[ 0.11842529285 ]]]


 [[[ 0.319928774626]]]


 [[[ 0.319928774626]]]


 [[[ 0.378755429421]]]


 [[[ 1.225877519716]]]


 [[[ 3.830653798838]]]]

A.reshape(-1,1):
[[-0.888788523827]
 [ 0.11842529285 ]
 [ 0.319928774626]
 [ 0.319928774626]
 [ 0.378755429421]
 [ 1.225877519716]
 [ 3.830653798838]]

Then I have done substractig and broadcasting came in, so my resulting matrix is 7x1x7x1.

I have a hard time to visualize the intermediate step what broadcasting does. I mean I cannot imagine what elements of arrays are repeated and what they look like while broadcasting. Could somebody shed some light on this problem,please?

1条回答
你好瞎i
2楼-- · 2019-08-19 10:44
In [5]: arr = np.arange(4)
In [6]: A = arr.reshape(-1,1,1,1)
In [7]: B = arr.reshape(-1,1)
In [8]: C = A + B
In [9]: C.shape
Out[9]: (4, 1, 4, 1)
In [10]: A.shape
Out[10]: (4, 1, 1, 1)
In [11]: B.shape
Out[11]: (4, 1)

There are 2 basic broadcasting rules:

  • expand the dimensions to match - by adding size 1 dimensions at the start
  • adjust all size 1 dimensions to match

So in this example:

 (4,1,1,1) + (4,1)
 (4,1,1,1) + (1,1,4,1)    # add 2 size 1's to B
 (4,1,4,1) + (4,1,4,1)    # adjust 2 of the 1's to 4
 (4,1,4,1)

The first step is, perhaps, the most confusing. The (4,1) is expanded to (1,1,4,1), not (4,1,1,1). The rule is intended to avoid ambiguity - by expanding in a consistent manner, not necessarily what a human might intuitively want.

Imagine the case where both arrays need expansion to match, and it could add a dimension in either direction:

 (4,) and (3,)
 (1,4) and (3,1)  or (4,1) and (1,3)
 (3,4)            or (4,3)
 confusion

The rule requires that the programmer choose which one expands to the right (4,1) or (3,1). numpy can then unambiguously add the other.


For a simpler example:

In [22]: A=np.arange(3).reshape(-1,1)
In [23]: B=np.arange(3)
In [24]: C = A+B   (3,1)+(3,) => (3,1)+(1,3) => (3,3)
In [25]: C
Out[25]: 
array([[0, 1, 2],
       [1, 2, 3],
       [2, 3, 4]])
In [26]: C.shape
Out[26]: (3, 3)

The [0,2,4] are present, but on the diagonal of C.

When broadcasting like this, the result is a kind of outer sum:

In [27]: np.add.outer(B,B)
Out[27]: 
array([[0, 1, 2],
       [1, 2, 3],
       [2, 3, 4]])
查看更多
登录 后发表回答