Tengo una matriz numpy (una imagen) llamada a con este tamaño:
[3,128,192]
ahora quiero crear una matriz numpy que contenga n copias de una que tenga esta dimensión:
[n,3,128,192]
¿Existe una función numpy que pueda ayudarme con este problema sin usar instrucciones de bucle?
Simplemente usa np.stack
# say you need 10 copies of a 3D array `a` In [267]: n = 10 In [266]: np.stack([a]*n)
Alternativamente, debería usar np.concatenate
si está realmente preocupado por el rendimiento.
In [285]: np.concatenate([a[np.newaxis, :, :]]*n)
Ejemplo:
In [268]: a Out[268]: array([[[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15]], [[16, 17, 18, 19], [20, 21, 22, 23], [24, 25, 26, 27], [28, 29, 30, 31]], [[32, 33, 34, 35], [36, 37, 38, 39], [40, 41, 42, 43], [44, 45, 46, 47]]]) In [271]: a.shape Out[271]: (3, 4, 4) In [269]: n = 10 In [270]: np.stack([a]*n).shape Out[270]: (10, 3, 4, 4) In [285]: np.concatenate([a[np.newaxis, :, :]]*n).shape Out[285]: (10, 3, 4, 4)
Actuación:
# ~ 4x faster than using `np.stack` In [292]: %timeit np.concatenate([a[np.newaxis, :, :]]*n) 100000 loops, best of 3: 10.7 µs per loop In [293]: %timeit np.stack([a]*n) 10000 loops, best of 3: 41.1 µs per loop
Enfoque # 1: Una forma sería con np.repeat
para repetir a lo largo del primer eje después de extender la matriz de entrada para tener una dimensión más, un singleton con None/np.newaxis
–
np.repeat(a[None],n,axis=0)
Ejecuciones de muestra
1) caso 2D:
In [209]: a Out[209]: array([[7, 8, 0, 1], [5, 0, 1, 0], [4, 3, 0, 1]]) In [210]: np.repeat(a[None],2,axis=0) Out[210]: array([[[7, 8, 0, 1], [5, 0, 1, 0], [4, 3, 0, 1]], [[7, 8, 0, 1], [5, 0, 1, 0], [4, 3, 0, 1]]])
2) caso 3D:
In [214]: a Out[214]: array([[[7, 2, 4, 2], [6, 7, 7, 6], [6, 8, 2, 1]], [[1, 5, 8, 5], [8, 0, 6, 4], [1, 2, 8, 8]]]) In [215]: np.repeat(a[None],2,axis=0) Out[215]: array([[[[7, 2, 4, 2], [6, 7, 7, 6], [6, 8, 2, 1]], [[1, 5, 8, 5], [8, 0, 6, 4], [1, 2, 8, 8]]], [[[7, 2, 4, 2], [6, 7, 7, 6], [6, 8, 2, 1]], [[1, 5, 8, 5], [8, 0, 6, 4], [1, 2, 8, 8]]]])
Enfoque # 2: Si no le importa una versión de solo lectura de la matriz de entrada, podríamos usar np.broadcast_to
–
np.broadcast_to(a, (n,) + a.shape)
Enfoque n. ° 3: si no le importa una vista en la matriz de entrada, aquí hay una con pasos NumPy:
def strided_repeat_newaxis0(a, n): s0,s1,s2 = a.strides shp = (n,) + a.shape return np.lib.index_tricks.as_strided(a, shape=shp, strides=(0,s0,s1,s2))
Prueba de tiempo de ejecución
In [290]: a = np.random.randint(0,9,(3,128,192)) In [291]: %timeit np.repeat(a[None],100,axis=0) 100 loops, best of 3: 6.15 ms per loop In [292]: %timeit strided_repeat_newaxis0(a, 100) 100000 loops, best of 3: 4.69 µs per loop In [293]: %timeit np.broadcast_to(a, (n,) + a.shape) 100000 loops, best of 3: 3.03 µs per loop