Numpy: use remodelar o newaxis para agregar dimensiones

Se ndarray.reshape usar ndarray.reshape o numpy.newaxis para agregar una nueva dimensión a una matriz. Ambos parecen crear una vista, ¿hay alguna razón o ventaja para usar una en lugar de la otra?

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

`

No veo evidencia de mucha diferencia. Podrías hacer una prueba de tiempo en arreglos muy grandes. Básicamente, tanto el violín con la forma, y ​​posiblemente los pasos. __array_interface__ es una buena forma de acceder a esta información. Por ejemplo:

 In [94]: b.__array_interface__ Out[94]: {'data': (162400368, False), 'descr': [('', ' 

Ambos crean una vista, utilizando el mismo búfer de data que el original. La misma forma, pero remodelar no cambia los strides . reshape permite especificar el order .

Y .flags muestra diferencias en la bandera C_CONTIGUOUS .

reshape puede ser más rápido porque está haciendo menos cambios. Pero de cualquier manera, la operación no debería afectar mucho el tiempo de los cálculos más grandes.

por ejemplo, para grandes 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 

Observación interesante de que: b.reshape(1,4).strides -> (32, 8)

Aquí está mi conjetura. .__array_interface__ está mostrando un atributo subyacente, y .strides se .strides más a una propiedad (aunque puede que todo esté enterrado en el código C). El valor subyacente predeterminado es None , y cuando es necesario para el cálculo (o visualización con .strides ), lo calcula a partir de la forma y el tamaño del elemento. 32 es la distancia al final de la primera fila (4x8). np.ones((2,4)).strides tiene el mismo (32,8) (y None en __array_interface__ .

b[None,:] por otro lado está preparando la matriz para la transmisión. Cuando se emiten, los valores existentes se utilizan repetidamente. Eso es lo que hace el 0 en (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': [('', ' 

b1 muestra lo mismo que np.ones((2,5)) pero solo tiene 5 elementos.

np.broadcast_arrays es una función en /numpy/lib/stride_tricks.py . Utiliza as_strided desde el mismo archivo. Estas funciones juegan directamente con los atributos de forma y zancada.

Una razón para usar numpy.newaxis sobre ndarray.reshape es cuando tiene más de una dimensión “desconocida” con la que operar. Así, por ejemplo, para la siguiente matriz:

 >>> arr.shape (10, 5) 

Esto funciona:

 >>> arr[:, np.newaxis, :].shape (10, 1, 5) 

Pero esto no lo hace:

 >>> arr.reshape(-1, 1, -1) ... ValueError: can only specify one unknown dimension