Sto usando sympy per generare alcune funzioni per i calcoli numerici. Pertanto io lambdifico un'espressione e la vettorializzo per usarla con gli array numpy. Ecco un esempio:Speedup sympy-lamdified e funzione vettoriale
import numpy as np
import sympy as sp
def numpy_function():
x, y, z = np.mgrid[0:1:40*1j, 0:1:40*1j, 0:1:40*1j]
T = (1 - np.cos(2*np.pi*x))*(1 - np.cos(2*np.pi*y))*np.sin(np.pi*z)*0.1
return T
def sympy_function():
x, y, z = sp.Symbol("x"), sp.Symbol("y"), sp.Symbol("z")
T = (1 - sp.cos(2*sp.pi*x))*(1 - sp.cos(2*sp.pi*y))*sp.sin(sp.pi*z)*0.1
lambda_function = np.vectorize(sp.lambdify((x, y, z), T, "numpy"))
x, y, z = np.mgrid[0:1:40*1j, 0:1:40*1j, 0:1:40*1j]
T = lambda_function(x,y,z)
return T
Il problema tra la versione sympy e una versione pura numpy è la velocità cioè
In [3]: timeit test.numpy_function()
100 loops, best of 3: 11.9 ms per loop
vs.
In [4]: timeit test.sympy_function()
1 loops, best of 3: 634 ms per loop
Quindi non v'è alcun modo per ottenere più vicino alla velocità della versione numpy? Penso che np.vectorize sia piuttosto lento ma in qualche modo parte del mio codice non funziona senza di essa. Grazie per eventuali suggerimenti.
EDIT: Così ho trovato il motivo per cui la funzione vectorize è necessario, vale a dire:
In [35]: y = np.arange(10)
In [36]: f = sp.lambdify(x,sin(x),"numpy")
In [37]: f(y)
Out[37]:
array([ 0. , 0.84147098, 0.90929743, 0.14112001, -0.7568025 ,
-0.95892427, -0.2794155 , 0.6569866 , 0.98935825, 0.41211849])
questo sembra funzionare bene comunque:
In [38]: y = np.arange(10)
In [39]: f = sp.lambdify(x,1,"numpy")
In [40]: f(y)
Out[40]: 1
Così, per semplice espressione come 1
questa funzione non restituisce un array. C'è un modo per risolvere questo problema e non si tratta di una specie di bug o almeno di un design inconsistente?
Grazie per la risposta. Il mio problema è che ho qualcosa come self.T = T (x, y, z) quindi in questo caso la trasmissione non funziona. Quale sarebbe il modo migliore per farlo ? – jrsm
Sembra che 'numpy.array' sia un no-op quando viene chiamato con un array, quindi puoi usare' np.array (T (x, y, z)) 'per assicurarti che il risultato sia sempre un array. – asmeurer
Anche se non riesco ancora a capire perché il caso d'uso non funzioni con la trasmissione. – asmeurer