2010-01-20 7 views
9

Disons que j'ai un tableau 2D Numpy:tableaux Ajout avec un nombre différent de dimensions

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

et je veux ajouter un tableau 1D à chaque ligne:

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

Cela fonctionne. Maintenant, si je tente d'ajouter un tableau 1D à chaque colonne, je reçois une erreur:

>>> 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 

Je peux résoudre ce problème en utilisant np.newaxis:

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

qui fonctionne comme prévu. Quelles sont les règles de correspondance de forme pour éviter d'avoir à utiliser np.newaxis?

Est-ce que le dernier élément du tuple de forme numérique doit correspondre? Cette règle s'applique-t-elle également aux dimensions supérieures? Par exemple, les travaux suivants:

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

Donc, ma question est de savoir si cela est documenté nulle part, et si elle est un comportement qui peut être invoqué, ou s'il est préférable d'utiliser toujours np.newaxis?

Répondre

10

Ceci est une caractéristique distinctive de numpy appelée broadcasting. Il est fait en utilisant quatre règles qui sont un peu compliqué dans la formulation, mais sont plutôt intuitive compris une fois:

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

L'opération est possible (résultat ne marche pas dans shape mismatch erreur que vous avez mentionné) dans trois cas:

  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.

Des exemples peuvent être trouvés via le lien ci-dessus.

+0

Cela a maintenant du sens - merci! – astrofrog

2

Permettez-moi de voir si je comprends ...

>>> 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 diffusion nécessaire pour faire 4 x 3 vecteur plus un vecteur 1D avec 3 éléments MOTIVEE.

La diffusion nécessaire pour faire un vecteur 4 x 3 plus un vecteur 1D avec 4 éléments échoue.

>>> D = C[:,newaxis] 

convertit C en un vecteur 2D d'une forme compatible.