Почему numpy.ravel возвращает копию?
В следующем примере:
>>> import numpy as np
>>> a = np.arange(10)
>>> b = a[:,np.newaxis]
>>> c = b.ravel()
>>> np.may_share_memory(a,c)
False
Почему numpy.ravel
возвращает копию моего массива? Не нужно ли возвращать a
?
Edit:
Я только что обнаружил, что np.squeeze
не возвращает копию.
>>> b = a[:,np.newaxis]
>>> c = b.squeeze()
>>> np.may_share_memory(a,c)
True
Почему существует разница между squeeze
и ravel
в этом случае?
Edit:
Как указано в mgilson, newaxis
отмечает массив как несменяемый, поэтому ravel
возвращает копию.
Итак, новый вопрос заключается в том, почему newaxis
помещает массив как несмежный.
История становится еще более странной:
>>> a = np.arange(10)
>>> b = np.expand_dims(a,axis=1)
>>> b.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
>>> c = b.ravel()
>>> np.may_share_memory(a,c)
True
В соответствии с документацией для expand_dims
она должна быть эквивалентна newaxis
.
Ответы
Ответ 1
Это может быть не лучший ответ на ваш вопрос, но похоже, что вставка newaxis вызывает numpy для просмотра массива как несмежного - возможно, для целей вещания:
>>> a=np.arange(10)
>>> b=a[:,None]
>>> a.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : True
OWNDATA : True
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
>>> b.flags
C_CONTIGUOUS : False
F_CONTIGUOUS : False
OWNDATA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
Однако изменение не приведет к такому:
>>> c=a.reshape(10,1)
>>> c.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
И эти массивы разделяют одну и ту же память:
>>> np.may_share_memory(c.ravel(),a)
True
ИЗМЕНИТЬ
np.expand_dims
фактически реализуется с использованием reshape
, поэтому он работает (это небольшая ошибка в документации, я полагаю). Здесь источник (без docstring):
def expand_dims(a,axis):
a = asarray(a)
shape = a.shape
if axis < 0:
axis = axis + len(shape) + 1
return a.reshape(shape[:axis] + (1,) + shape[axis:])
Ответ 2
Похоже, что это может быть связано с шагами:
>>> c = np.expand_dims(a, axis=1)
>>> c.strides
(8, 8)
>>> b = a[:, None]
>>> b.strides
(8, 0)
>>> b.flags
C_CONTIGUOUS : False
F_CONTIGUOUS : False
OWNDATA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
>>> b.strides = (8, 8)
>>> b.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
Я не уверен, какую разницу может сделать шаг по размеру 1, но похоже, что создание numpy относится к массиву как к непрерывному.