es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Optimización de código utilizando matrices numpy. ¿Existe una mejor solución?

Estoy intentando optimizar una función que calcula: aexp(bx)+c

Probé tres métodos usando arreglos de numpy:

def model(a,b,c,x):
    return a*np.exp(b*x)+c

def myFoo1(modelParam,x):
    return([model(*i,x) for i in modelParam])

def myFoo2(modelParam,x):
    return([i[0]*np.exp(i[1]*x)+i[2] for i in modelParam])

def myFoo3(modelParam,x):
    return(np.exp(np.outer(modelParam[:,1],x))*modelParam[:,0][:,None]+modelParam[:,2][:,None])

Cuando se mide el tiempo de ejecución:

x=np.array(np.arange(0,100,0.1))
params=np.array([[10,0.1,2],[20,0.3,4],[30,0.2,6],[15,0.2,4],[16,0.5,7]])
%time myFoo1(params,x)
%time myFoo2(params,x)
%time myFoo3(params,x)

La salida es:

CPU times: user 3.58 ms, sys: 0 ns, total: 3.58 ms
Wall time: 2 ms
CPU times: user 855 µs, sys: 0 ns, total: 855 µs
Wall time: 703 µs
CPU times: user 690 µs, sys: 0 ns, total: 690 µs
Wall time: 564 µs

El primero era mi código original porque es el más fácil de programar. Pero, el tercero es 4 veces más rápido. ¿Puedo mejorarlo nuevamente?

Y con %timeit (pregunta editada según la sugerencia en el comentario):

211 µs ± 663 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
199 µs ± 199 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
164 µs ± 56.1 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Basado en los resultados obtenidos de %time y %timeit, parece que el tercer método (myFoo3) es el más rápido entre los tres enfoques. Sin embargo, es posible optimizarlo aún más evitando el uso de la función np.outer.

    Una solución posible es utilizar la propiedad de transmisión de las matrices de numpy de la siguiente manera:

    def myFoo4(modelParam, x):
        return modelParam[:,0][:,None] * np.exp(modelParam[:,1][:,None] * x) + modelParam[:,2][:,None]
    

    Este enfoque evita el uso de np.outer y se espera que sea más rápido que myFoo3. Puede ser probado usando %timeit y el resultado puede ser comparado con los anteriores para determinar cuál es la solución más óptima.

Comments are closed.