numpy – funciones vectorizadas: apply_over_axes / apply_along_axis

Quiero calcular el determinante de m m subarreglos de arreglos dimensionales de am m * n, y me gustaría hacerlo de una manera más rápida y elegante. El enfoque de fuerza bruta funciona:

import numpy as n array=n.array([[[0.,1.,2.,3.],[2,1,1,0]],[[0.5, 0.5,2,2],[0.5,1,0,2]]]) detarray=n.zeros(4) for i in range(4): detarray[i]= n.linalg.det(array[:,:,i]) 

Habría intentado hacer esto con apply_along_axis, pero sé que esto es solo para los argumentos 1D de la función, y supongo que no puedo hacer que esto funcione.

Sin embargo, pensé que apply_over_axes también debería funcionar:

 n.apply_over_axes(n.linalg.det, array, [0,1]) 

pero esto me da un error: “det () toma exactamente 1 argumento (2 dados)”

¿Alguien sabe por qué esto no funciona? Si este tipo de cálculo no es realmente posible con apply_over_axes, ¿hay una mejor manera de hacer esto en lugar del bucle for?

Utilizando la semántica de transposición de NumPy para arreglos 3D, simplemente puede pasar el arreglo transpuesto a numpy.linalg.det() como en:

 In [13]: arr = np.array([[[0.,1.,2.,3.], [2, 1, 1, 0]], [[0.5, 0.5,2,2], [0.5, 1, 0, 2]]]) In [14]: np.linalg.det(arr.T) Out[14]: array([-1. , 0.5, -2. , 6. ]) 

En cuanto al rendimiento, este enfoque parece ser el doble de rápido que el otro enfoque de mover manualmente los ejes utilizando numpy.moveaxis

 In [29]: %timeit np.linalg.det(np.moveaxis(arr, 2, 0)) 12.9 µs ± 192 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) In [30]: %timeit np.linalg.det(arr.T) 6.2 µs ± 136 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 

numpy.linalg.det se vectoriza fuera de la caja. Todo lo que necesitas hacer es mover los ejes externos a la izquierda:

 >>> np.linalg.det(np.moveaxis(array, 2, 0)) array([-1. , 0.5, -2. , 6. ])