tmp
/
pip-install-ghxuqwgs
/numpy_78e94bf2b6094bf9a1f3d92042f9bf46
/build
/lib.linux-x86_64-cpython-310
/numpy
/doc
/broadcasting.py
""" | |
======================== | |
Broadcasting over arrays | |
======================== | |
The term broadcasting describes how numpy treats arrays with different | |
shapes during arithmetic operations. Subject to certain constraints, | |
the smaller array is "broadcast" across the larger array so that they | |
have compatible shapes. Broadcasting provides a means of vectorizing | |
array operations so that looping occurs in C instead of Python. It does | |
this without making needless copies of data and usually leads to | |
efficient algorithm implementations. There are, however, cases where | |
broadcasting is a bad idea because it leads to inefficient use of memory | |
that slows computation. | |
NumPy operations are usually done on pairs of arrays on an | |
element-by-element basis. In the simplest case, the two arrays must | |
have exactly the same shape, as in the following example: | |
>>> a = np.array([1.0, 2.0, 3.0]) | |
>>> b = np.array([2.0, 2.0, 2.0]) | |
>>> a * b | |
array([ 2., 4., 6.]) | |
NumPy's broadcasting rule relaxes this constraint when the arrays' | |
shapes meet certain constraints. The simplest broadcasting example occurs | |
when an array and a scalar value are combined in an operation: | |
a = np.array([1.0, 2.0, 3.0]) | |
b = 2.0 | |
a * b | |
array([ 2., 4., 6.]) | |
The result is equivalent to the previous example where ``b`` was an array. | |
We can think of the scalar ``b`` being *stretched* during the arithmetic | |
operation into an array with the same shape as ``a``. The new elements in | |
``b`` are simply copies of the original scalar. The stretching analogy is | |
only conceptual. NumPy is smart enough to use the original scalar value | |
without actually making copies, so that broadcasting operations are as | |
memory and computationally efficient as possible. | |
The code in the second example is more efficient than that in the first | |
because broadcasting moves less memory around during the multiplication | |
(``b`` is a scalar rather than an array). | |
General Broadcasting Rules | |
========================== | |
When operating on two arrays, NumPy compares their shapes element-wise. | |
It starts with the trailing dimensions, and works its way forward. Two | |
dimensions are compatible when | |
1) they are equal, or | |
2) one of them is 1 | |
If these conditions are not met, a | |
``ValueError: frames are not aligned`` exception is thrown, indicating that | |
the arrays have incompatible shapes. The size of the resulting array | |
is the maximum size along each dimension of the input arrays. | |
Arrays do not need to have the same *number* of dimensions. For example, | |
if you have a ``256x256x3`` array of RGB values, and you want to scale | |
each color in the image by a different value, you can multiply the image | |
by a one-dimensional array with 3 values. Lining up the sizes of the | |
trailing axes of these arrays according to the broadcast rules, shows that | |
they are compatible:: | |
Image (3d array): 256 x 256 x 3 | |
Scale (1d array): 3 | |
Result (3d array): 256 x 256 x 3 | |
When either of the dimensions compared is one, the other is | |
used. In other words, dimensions with size 1 are stretched or "copied" | |
to match the other. | |
In the following example, both the ``A`` and ``B`` arrays have axes with | |
length one that are expanded to a larger size during the broadcast | |
operation:: | |
A (4d array): 8 x 1 x 6 x 1 | |
B (3d array): 7 x 1 x 5 | |
Result (4d array): 8 x 7 x 6 x 5 | |
Here are some more examples:: | |
A (2d array): 5 x 4 | |
B (1d array): 1 | |
Result (2d array): 5 x 4 | |
A (2d array): 5 x 4 | |
B (1d array): 4 | |
Result (2d array): 5 x 4 | |
A (3d array): 15 x 3 x 5 | |
B (3d array): 15 x 1 x 5 | |
Result (3d array): 15 x 3 x 5 | |
A (3d array): 15 x 3 x 5 | |
B (2d array): 3 x 5 | |
Result (3d array): 15 x 3 x 5 | |
A (3d array): 15 x 3 x 5 | |
B (2d array): 3 x 1 | |
Result (3d array): 15 x 3 x 5 | |
Here are examples of shapes that do not broadcast:: | |
A (1d array): 3 | |
B (1d array): 4 # trailing dimensions do not match | |
A (2d array): 2 x 1 | |
B (3d array): 8 x 4 x 3 # second from last dimensions mismatched | |
An example of broadcasting in practice:: | |
>>> x = np.arange(4) | |
>>> xx = x.reshape(4,1) | |
>>> y = np.ones(5) | |
>>> z = np.ones((3,4)) | |
>>> x.shape | |
(4,) | |
>>> y.shape | |
(5,) | |
>>> x + y | |
<type 'exceptions.ValueError'>: shape mismatch: objects cannot be broadcast to a single shape | |
>>> xx.shape | |
(4, 1) | |
>>> y.shape | |
(5,) | |
>>> (xx + y).shape | |
(4, 5) | |
>>> xx + y | |
array([[ 1., 1., 1., 1., 1.], | |
[ 2., 2., 2., 2., 2.], | |
[ 3., 3., 3., 3., 3.], | |
[ 4., 4., 4., 4., 4.]]) | |
>>> x.shape | |
(4,) | |
>>> z.shape | |
(3, 4) | |
>>> (x + z).shape | |
(3, 4) | |
>>> x + z | |
array([[ 1., 2., 3., 4.], | |
[ 1., 2., 3., 4.], | |
[ 1., 2., 3., 4.]]) | |
Broadcasting provides a convenient way of taking the outer product (or | |
any other outer operation) of two arrays. The following example shows an | |
outer addition operation of two 1-d arrays:: | |
>>> a = np.array([0.0, 10.0, 20.0, 30.0]) | |
>>> b = np.array([1.0, 2.0, 3.0]) | |
>>> a[:, np.newaxis] + b | |
array([[ 1., 2., 3.], | |
[ 11., 12., 13.], | |
[ 21., 22., 23.], | |
[ 31., 32., 33.]]) | |
Here the ``newaxis`` index operator inserts a new axis into ``a``, | |
making it a two-dimensional ``4x1`` array. Combining the ``4x1`` array | |
with ``b``, which has shape ``(3,)``, yields a ``4x3`` array. | |
See `this article <http://wiki.scipy.org/EricsBroadcastingDoc>`_ | |
for illustrations of broadcasting concepts. | |
""" | |
from __future__ import division, absolute_import, print_function | |