Comment quadriller ou élever à une puissance (par élément) un tableau numpy 2D?

J'ai besoin de quadriller un tableau numpy 2D (par élément) et j'ai essayé le code suivant:

import numpy as np
a = np.arange(4).reshape(2, 2)
print a^2, 'n'
print a*a

Qui donne:

[[2 3]
[0 1]]

[[0 1]
[4 9]]

Clairement, la notation a*a me donne le résultat que je veux et non a^2.

Je voudrais savoir si une autre notation existe pour élever un tableau numpy à la puissance de 2 ou N? Au lieu de a*a*a*..*a.

21
demandé sur Cleb 2014-09-16 18:03:17

2 réponses

Le moyen Le plus rapide est de faire a*a ou a**2 ou np.square(a) alors que np.power(a, 2) a montré à être beaucoup plus lent.

np.power() vous permet d'utiliser des exposants différents pour chaque élément si au lieu de 2 Vous Passez un autre tableau d'exposants. À partir des commentaires de @GarethRees, je viens d'apprendre que cette fonction vous donnera des résultats différents de a**2 ou a*a, qui deviennent importants dans les cas où vous avez de petites tolérances.

J'ai chronométré quelques exemples en utilisant NumPy 1.9.0 MKL 64 bits, et le les résultats sont présentés ci-dessous:

In [29]: a = np.random.random((1000, 1000))

In [30]: timeit a*a
100 loops, best of 3: 2.78 ms per loop

In [31]: timeit a**2
100 loops, best of 3: 2.77 ms per loop

In [32]: timeit np.power(a, 2)
10 loops, best of 3: 71.3 ms per loop
24
répondu Saullo G. P. Castro 2016-02-15 10:56:41
>>> import numpy
>>> print numpy.power.__doc__

power(x1, x2[, out])

First array elements raised to powers from second array, element-wise.

Raise each base in `x1` to the positionally-corresponding power in
`x2`.  `x1` and `x2` must be broadcastable to the same shape.

Parameters
----------
x1 : array_like
    The bases.
x2 : array_like
    The exponents.

Returns
-------
y : ndarray
    The bases in `x1` raised to the exponents in `x2`.

Examples
--------
Cube each element in a list.

>>> x1 = range(6)
>>> x1
[0, 1, 2, 3, 4, 5]
>>> np.power(x1, 3)
array([  0,   1,   8,  27,  64, 125])

Raise the bases to different exponents.

>>> x2 = [1.0, 2.0, 3.0, 3.0, 2.0, 1.0]
>>> np.power(x1, x2)
array([  0.,   1.,   8.,  27.,  16.,   5.])

The effect of broadcasting.

>>> x2 = np.array([[1, 2, 3, 3, 2, 1], [1, 2, 3, 3, 2, 1]])
>>> x2
array([[1, 2, 3, 3, 2, 1],
       [1, 2, 3, 3, 2, 1]])
>>> np.power(x1, x2)
array([[ 0,  1,  8, 27, 16,  5],
       [ 0,  1,  8, 27, 16,  5]])
>>>

Précision

Selon l'observation discutée sur la précision numérique selon l'objection @ GarethRees dans les commentaires:

>>> a = numpy.ones( (3,3), dtype = numpy.float96 ) # yields exact output
>>> a[0,0] = 0.46002700024131926
>>> a
array([[ 0.460027,  1.0,  1.0],
       [ 1.0,  1.0,  1.0],
       [ 1.0,  1.0,  1.0]], dtype=float96)
>>> b = numpy.power( a, 2 )
>>> b
array([[ 0.21162484,  1.0,  1.0],
       [ 1.0,  1.0,  1.0],
       [ 1.0,  1.0,  1.0]], dtype=float96)

>>> a.dtype
dtype('float96')
>>> a[0,0]
0.46002700024131926
>>> b[0,0]
0.21162484095102677

>>> print b[0,0]
0.211624840951
>>> print a[0,0]
0.460027000241

Performance

>>> c    = numpy.random.random( ( 1000, 1000 ) ).astype( numpy.float96 )

>>> import zmq
>>> aClk = zmq.Stopwatch()

>>> aClk.start(), c**2, aClk.stop()
(None, array([[ ...]], dtype=float96), 5663L)                #   5 663 [usec]

>>> aClk.start(), c*c, aClk.stop()
(None, array([[ ...]], dtype=float96), 6395L)                #   6 395 [usec]

>>> aClk.start(), c[:,:]*c[:,:], aClk.stop()
(None, array([[ ...]], dtype=float96), 6930L)                #   6 930 [usec]

>>> aClk.start(), c[:,:]**2, aClk.stop()
(None, array([[ ...]], dtype=float96), 6285L)                #   6 285 [usec]

>>> aClk.start(), numpy.power( c, 2 ), aClk.stop()
(None, array([[ ... ]], dtype=float96), 384515L)             # 384 515 [usec]
1
répondu user3666197 2014-09-16 21:30:30