Как квадрат или поднять к мощности (по-разному) массив 2D numpy?

Мне нужно квадрат массива 2D numpy (elementwise), и я пробовал следующий код:

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

что дает:

[[2 3]
[0 1]]

[[0 1]
[4 9]]

Ясно, что обозначение a*a дает мне результат, который я хочу, а не a^2.

Я хотел бы знать, существует ли другая нотация для создания массива numpy в степени 2 или N? Вместо a*a*a*..*a.

Ответ 1

Самый быстрый способ - сделать a*a или a**2 или np.square(a), тогда как np.power(a, 2) показал, что он значительно медленнее.

np.power() позволяет использовать разные экспоненты для каждого элемента, если вместо 2 вы передаете другой массив показателей. Из комментариев @GarethRees я только что узнал, что эта функция даст вам разные результаты, чем a**2 или a*a, которые становятся важными в тех случаях, когда у вас небольшие допуски.

Я приурочил некоторые примеры, используя NumPy 1.9.0 MKL 64 бит, и результаты показаны ниже:

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

Ответ 2

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

Точность

В соответствии с обсуждаемым замечанием о числовой точности в соответствии с возражением @GarethRees в комментариях:

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

Производительность

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