2014-10-08 23 views
5

Jaki jest efektywny (szybki) sposób stosowania funkcji Kawałek na macierzy Numpy?Kawałki funkcji na tablicach Numpy

Załóżmy na przykład, funkcje odcinkowo są jak

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

Oto co zrobiłem.

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]]) 

Czy istnieje skuteczna metoda dla mniejszych tablic, dużych tablic, wielu funkcji itp? Moje obawy dotyczą wykorzystania funkcji lambda. Nie jestem pewien, czy są one zoptymalizowane Numpy.

Odpowiedz

3

W tym przypadku nie powinieneś się martwić o lambdas: optymalizacja Numpy polega na zmniejszeniu narzutów, poprzez umożliwienie funkcji oceny wielu wartości w tym samym czasie w grupie. W każdym wywołaniu np.piecewise, każda funkcja w funclist (części funkcji) jest wywoływana dokładnie raz, z tablicą numpy składającą się ze wszystkich wartości, w których właściwy warunek jest prawdziwy. Tak więc te lambdy są nazywane w sposób zoptymalizowany pod kątem numpy.

Podobny jest np.select (i np.where dla dokładnie dwóch części). Koszt narzutowy jest taki sam, jak jest wektorowany w ten sam sposób, ale oceni wszystkie funkcje dla wszystkich punktów danych. W związku z tym będzie wolniejszy niż np.piecewise, szczególnie gdy funkcje są drogie. W niektórych przypadkach jest to wygodniejsze (brak lambda) i łatwiej można rozszerzyć koncepcję na wiele zmiennych.

+0

Dobra odpowiedź. Inną zaletą używania 'np.select()' lub 'np.where()' jest to, że masz dostęp do całej tablicy podczas wykonywania obliczeń. Jeśli twoja funkcja zależy od innych wartości na wejściu (na przykład sąsiednich wartości każdego punktu), będzie to przydatne. Ale w przypadku OP nie ma znaczenia, a 'np.piecewise()' jest dobre. –