Ver también

numpy.broadcast

Array Broadcasting en Numpy

Una introducción a los conceptos discutidos aquí

Nota

Ver Este artículo para ilustraciones de conceptos de radiodifusión.

El término transmisión describe cómo numpy trata las matrices con diferentes formas durante las operaciones aritméticas. Sujeto a ciertas limitaciones, el menor array se “transmite” a través de los array para que tengan formas compatibles. La radiodifusión proporciona un medio de vectorización array operaciones para que el bucle se produzca en C en lugar de Python. Lo hace sin hacer copias innecesarias de datos y generalmente conduce a implementaciones de algoritmos eficientes. Sin embargo, hay casos en los que la transmisión es una mala idea porque conduce a un uso ineficiente de la memoria que ralentiza los cálculos.

Las operaciones NumPy generalmente se realizan en pares de matrices elemento por elemento. En el caso más simple, las dos matrices deben tener exactamente la misma forma, como en el siguiente ejemplo:

>>> a = np.array([1.0,2.0,3.0])>>> b = np.array([2.0,2.0,2.0])>>> a * b
array([2.,4.,6.])

La regla de transmisión de NumPy relaja esta restricción cuando las formas de las matrices cumplen con ciertas restricciones. El ejemplo de radiodifusión más simple ocurre cuando un array y un valor escalar se combinan en una operación:

>>> a = np.array([1.0,2.0,3.0])>>> b =2.0>>> a * b
array([2.,4.,6.])

El resultado es equivalente al ejemplo anterior donde b fue un array. Podemos pensar en el escalar b ser estirado durante la operación aritmética en un array con la misma forma que a. Los nuevos elementos en b son simplemente copias del escalar original. La analogía del estiramiento es solo conceptual. NumPy es lo suficientemente inteligente como para usar el valor escalar original sin hacer copias, de modo que las operaciones de transmisión sean tan eficientes en memoria y computacionalmente como sea posible.

El código del segundo ejemplo es más eficiente que el del primero porque la transmisión mueve menos memoria durante la multiplicación (b es un escalar en lugar de un array).

Reglas generales de transmisión

Cuando se opera en dos matrices, NumPy compara sus formas por elementos. Comienza con las dimensiones finales (es decir, más a la derecha) y avanza hacia la izquierda. Dos dimensiones son compatibles cuando

  1. son iguales, o
  2. uno de ellos es 1

Si no se cumplen estas condiciones, un ValueError: operands could not be broadcast together Se lanza una excepción, lo que indica que las matrices tienen formas incompatibles. El tamaño de la resultante array es el tamaño que no es 1 a lo largo de cada eje de las entradas.

Las matrices no necesitan tener el mismo número de dimensiones. Por ejemplo, si tiene un 256x256x3 array de valores RGB, y desea escalar cada color de la imagen por un valor diferente, puede multiplicar la imagen por un valor unidimensional array con 3 valores. Alinear los tamaños de los ejes posteriores de estos arreglos de acuerdo con las reglas de transmisión muestra que son compatibles:

Image  (3d array):256 x 256 x 3
Scale  (1d array):3
Result (3d array):256 x 256 x 3

Cuando cualquiera de las dimensiones comparadas es una, se utiliza la otra. En otras palabras, las dimensiones con tamaño 1 se estiran o “copian” para que coincidan con las otras.

En el siguiente ejemplo, tanto el A y B Los arreglos tienen ejes con una longitud uno que se expanden a un tamaño mayor durante la operación de transmisión:

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

A continuación, se muestran algunos ejemplos más:

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

A continuación, se muestran ejemplos de formas que no se transmiten:

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

Un ejemplo de radiodifusión en la práctica:

>>> 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
ValueError: operands could not be broadcast together with shapes (4,)(5,)>>> 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.]])

La radiodifusión proporciona una forma conveniente de tomar el producto externo (o cualquier otra operación externa) de dos arreglos. El siguiente ejemplo muestra una operación de suma externa de dos matrices 1-d:

>>> 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.]])

Aquí el newaxis El operador de índice inserta un nuevo eje en a, haciéndolo bidimensional 4x1 array. Combinando el 4x1 array con b, que tiene forma (3,), produce un 4x3 array.