Numpy: используйте reshape или newaxis для добавления размеров
или ndarray.reshape
или numpy.newaxis
можно использовать для добавления нового измерения в массив. Они оба, похоже, создают представление, есть ли причина или преимущество использовать один вместо другого?
>>> b
array([ 1., 1., 1., 1.])
>>> c = b.reshape((1,4))
>>> c *= 2
>>> c
array([[ 2., 2., 2., 2.]])
>>> c.shape
(1, 4)
>>> b
array([ 2., 2., 2., 2.])
>>> d = b[np.newaxis,...]
>>> d
array([[ 2., 2., 2., 2.]])
>>> d.shape
(1, 4)
>>> d *= 2
>>> b
array([ 4., 4., 4., 4.])
>>> c
array([[ 4., 4., 4., 4.]])
>>> d
array([[ 4., 4., 4., 4.]])
>>>
`
1 ответов
я не вижу большой разницы. Вы можете сделать тест времени на очень больших массивах. В основном оба играют с формой и, возможно, шагами. __array_interface__
это хороший способ доступа к этой информации. Например:
In [94]: b.__array_interface__
Out[94]:
{'data': (162400368, False),
'descr': [('', '<f8')],
'shape': (5,),
'strides': None,
'typestr': '<f8',
'version': 3}
In [95]: b[None,:].__array_interface__
Out[95]:
{'data': (162400368, False),
'descr': [('', '<f8')],
'shape': (1, 5),
'strides': (0, 8),
'typestr': '<f8',
'version': 3}
In [96]: b.reshape(1,5).__array_interface__
Out[96]:
{'data': (162400368, False),
'descr': [('', '<f8')],
'shape': (1, 5),
'strides': None,
'typestr': '<f8',
'version': 3}
оба создают представление, используя то же самое data
буфер как оригинал. Та же форма, но reshape не изменяет strides
. reshape
позволяет указать order
.
и .flags
показывает различия в C_CONTIGUOUS
флаг.
reshape
может быть быстрее, потому что он вносит меньше изменений. Но в любом случае операция не должна сильно влиять на время больших вычислений.
, например, для больших b
In [123]: timeit np.outer(b.reshape(1,-1),b)
1 loops, best of 3: 288 ms per loop
In [124]: timeit np.outer(b[None,:],b)
1 loops, best of 3: 287 ms per loop
интересное наблюдение, что: b.reshape(1,4).strides -> (32, 8)
вот моя догадка. .__array_interface__
отображает базовый атрибут, и .strides
больше похоже на свойство (хотя все это может быть похоронено в коде C). Базовое значение по умолчанию None
, и при необходимости для расчета (или отображения с .strides
) он вычисляет его из формы и размер товара. 32
- расстояние до конца 1-й строки (4x8). np.ones((2,4)).strides
имеет одно и то же (32,8)
(и None
на __array_interface__
.
b[None,:]
С другой стороны готовится массив для вещания. При трансляции существующие значения используются повторно. Вот что такое 0
на (0,8)
делает.
In [147]: b1=np.broadcast_arrays(b,np.zeros((2,1)))[0]
In [148]: b1.shape
Out[148]: (2, 5000)
In [149]: b1.strides
Out[149]: (0, 8)
In [150]: b1.__array_interface__
Out[150]:
{'data': (3023336880L, False),
'descr': [('', '<f8')],
'shape': (2, 5),
'strides': (0, 8),
'typestr': '<f8',
'version': 3}
b1
отображает же np.ones((2,5))
но есть только 5 пунктов.
np.broadcast_arrays
- это функция, в /numpy/lib/stride_tricks.py
. Он использует as_strided
из того же файла. Эти функции непосредственно играют с атрибутами shape и strides.