2014-10-08 9 views
5

Qual è il modo efficiente (velocità) per applicare le funzioni a tratti su Numpy Array?Funzioni a tratti su Numpy Arrays

Diciamo, per esempio, le funzioni a tratti sono come

For (1) : x<=2 f(x) = 2*x + x^2 
    (2) : x>2 f(x) = -(x^2 + 2) 

Ecco quello che ho fatto.

data = np.random.random_integers(5, size=(5,6)) 
print data 
np.piecewise(data, [data <= 2, data > 2], 
      [lambda x: 2*x + pow(2, x), 
       lambda x: -(pow(x, 2) + 2)]) 

data = 
[[4 2 1 1 5 3] 
[4 3 3 5 4 5] 
[3 2 4 2 5 3] 
[2 5 4 3 1 4] 
[5 3 3 5 5 5]] 
output = 
array([[-18, 8, 4, 4, -27, -11], 
     [-18, -11, -11, -27, -18, -27], 
     [-11, 8, -18, 8, -27, -11], 
     [ 8, -27, -18, -11, 4, -18], 
     [-27, -11, -11, -27, -27, -27]]) 

Esiste un metodo efficiente per array più piccoli, array di grandi dimensioni, molte funzioni ecc.? La mia preoccupazione è che vengano utilizzate le funzioni lambda. Non sono sicuro se questi sono ottimizzati per Numpy.

risposta

3

In questo caso, non dovresti preoccuparti dei lambdas: l'ottimizzazione di Numpy riguarda la riduzione del sovraccarico di chiamata, consentendo alle funzioni di valutare molti valori contemporaneamente in batch. In ogni chiamata a np.piecewise, ciascuna funzione in funclist (le parti della funzione) viene chiamata esattamente una volta, con una matrice numpy costituita da tutti i valori in cui la condizione appropriata è vera. Quindi, questi lambda sono chiamati in un modo ottimizzato per il numpy.

Simile è np.select (e np.where per esattamente due parti). L'overhead di chiamata è lo stesso in quanto è vettorizzato nello stesso modo, ma valuterà tutte le funzioni per tutti i punti di dati. Pertanto, sarà più lento di np.piecewise, in particolare, quando le funzioni sono costose. In alcuni casi, è più conveniente (senza lambda) e si può estendere più facilmente il concetto a molte variabili.

+0

Buona risposta. Un altro vantaggio dell'uso di 'np.select()' o 'np.where()' è che quindi si ha accesso all'intero array quando si eseguono i calcoli. Se la tua funzione dipende da altri valori nell'input (ad esempio, i valori vicini di ciascun punto), ciò sarà utile. Ma nel caso dell'OP non ha importanza, e 'np.piecewise()' è buono. –