2010-01-20 12 views
9

Digamos que tienen una matriz 2D Numpy:Adición de matrices con diferente número de dimensiones

>>> a = np.random.random((4,6)) 

y quiero agregar una matriz de 1D a cada fila:

>>> c = np.random.random((6,)) 
>>> a + c 

Esto funciona. Ahora bien, si lo intento de añadir una matriz 1D a cada columna, me sale un error:

>>> b = np.random.random((4,)) 
>>> a + b 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: shape mismatch: objects cannot be broadcast to a single shape 

puedo solucionar este problema mediante el uso de np.newaxis:

>>> a + b[:,np.newaxis] 

el cual funciona como se esperaba.

¿Cuáles son las reglas de coincidencia de formas para evitar tener que usar np.newaxis? ¿Es que el último elemento de la tupla de forma numpy tiene que coincidir? ¿Esta regla también se aplica a dimensiones más altas? Por ejemplo, las siguientes obras:

>>> a = np.random.random((2,3,4,5)) 
>>> b = np.random.random((4,5)) 
>>> a + b 

Así que mi pregunta es si esto está documentado en cualquier lugar, y si se trata de un comportamiento que se puede confiar en, o si es mejor utilizar siempre np.newaxis?

Respuesta

10

Esta es una característica distintiva de numpy llamada broadcasting. Se realiza utilizando cuatro reglas que son un poco complicado en la formulación, pero son bastante intuitiva una vez entendido:

  1. All input arrays with ndim smaller than the input array of largest ndim , have 1’s prepended to their shapes.
  2. The size in each dimension of the output shape is the maximum of all the input sizes in that dimension.
  3. An input can be used in the calculation if its size in a particular dimension either matches the output size in that dimension, or has value exactly 1.
  4. If an input has a dimension size of 1 in its shape, the first data entry in that dimension will be used for all calculations along that dimension. In other words, the stepping machinery of the ufunc will simply not step along that dimension (the stride will be 0 for that dimension).

La operación es posible (resultado no funciona en shape mismatch error que usted ha mencionado) en tres casos:

  1. The arrays all have exactly the same shape.
  2. The arrays all have the same number of dimensions and the length of each dimensions is either a common length or 1.
  3. The arrays that have too few dimensions can have their shapes prepended with a dimension of length 1 to satisfy property 2.

Los ejemplos se pueden encontrar a través del enlace de arriba.

+0

Esto ahora tiene sentido, ¡gracias! – astrofrog

2

A ver si lo entiendo ...

>>> from numpy import ones, newaxis 
>>> A = ones((4,3)) # 4 rows x 3 cols 
>>> A.shape 
(4, 3) 
>>> A 
array([[ 1., 1., 1.], 
     [ 1., 1., 1.], 
     [ 1., 1., 1.], 
     [ 1., 1., 1.]]) 
>>> 
>>> ones((4,1))  # 4 rows x 1 col 
array([[ 1.], 
     [ 1.], 
     [ 1.], 
     [ 1.]]) 
>>> A + ones((4,1)) 
array([[ 2., 2., 2.], 
     [ 2., 2., 2.], 
     [ 2., 2., 2.], 
     [ 2., 2., 2.]]) 
>>> 
>>> ones((1,3))  # 1 row x 3 cols 
array([[ 1., 1., 1.]]) 
>>> A + ones((1,3)) 
array([[ 2., 2., 2.], 
     [ 2., 2., 2.], 
     [ 2., 2., 2.], 
     [ 2., 2., 2.]]) 
>>> 
>>> B = ones((3,)) # a 1D array 
>>> B 
array([ 1., 1., 1.]) 
>>> B.shape 
(3,) 
>>> A + B 
array([[ 2., 2., 2.], 
     [ 2., 2., 2.], 
     [ 2., 2., 2.], 
     [ 2., 2., 2.]]) 
>>> 
>>> C = ones((4,)) # a 1D array 
>>> C.shape 
(4,) 
>>> C 
array([ 1., 1., 1., 1.]) 
>>> A + C 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: shape mismatch: objects cannot be broadcast to a single shape 
>>> 
>>> D = C[:,newaxis] 
>>> D.shape 
(4, 1) 
>>> A + D 
array([[ 2., 2., 2.], 
     [ 2., 2., 2.], 
     [ 2., 2., 2.], 
     [ 2., 2., 2.]]) 

La transmisión necesaria para hacer 4 x 3 vector más un vector 1D con 3 elementos tiene éxito.

La emisión necesaria para hacer un vector 4 x 3 más un vector 1D con 4 elementos falla.

>>> D = C[:,newaxis] 

convierte C en un vector 2D de una forma compatible.

Cuestiones relacionadas