6.9. Universaalifunktiot

Universaalifunktio (ufunc) on matemaattinen funktio, joka soveltuu taulukon jokaiseen alkioon yhdellä kutsulla. Edellisen sivun aritmeettiset operaattorit ovat universaalifunktioita operaattorisyntaksiin puettuna; tämä sivu on luettelo nimetyistä funktioista, jotka kattavat trigonometrian, eksponentit / logaritmit, pyöristyksen ja muutaman muun.

Jokainen ufunc hyväksyy skalaarin, Python-iteroitavan tai ndarray-olion ja palauttaa joko yhden liukuluvun (kun syöte oli skalaari) tai liukuluku-ndarray-olion:

from ulab import numpy as np

np.exp(2.0)                    # 7.389...
np.sin(range(4))               # 1-D float ndarray
np.sqrt([1, 4, 9, 16])         # array([1.0, 2.0, 3.0, 4.0])

a = np.arange(9).reshape((3, 3))
np.exp(a)                      # 3x3 float ndarray

6.9.1. Luettelo

numpy tarjoaa matemaattiset funktiot, joihin sulautettu sovellus useimmin tarttuu:

Jokainen funktio käsittelee koko taulukon yhdellä kirjastokutsulla. Nopeutus verrattuna Python-listageneraattoriin, joka kutsuu math.sin() -funktiota alkio kerrallaan, on 10-30-kertainen tyypillisellä puskurilla.

6.9.2. out=-avainsana

Jokainen ufunc-kutsu varaa normaalisti tuoreen tulostaulukon tulostaan varten. Silmukassa, joka suoritetaan monta kertaa sekunnissa, nämä varaukset kertyvät ja tuhlaavat RAM-muistia. out=-avainsanan välittäminen – jo olemassa oleva liukulukutaulukko, jolla on sama muoto kuin syötteellä – kirjoittaa tuloksen kyseiseen taulukkoon uuden varaamisen sijaan:

x = np.linspace(0, 2 * np.pi, num=256)
y = np.zeros(256)

while True:
    np.sin(x, out=y)
    # use y ...

Jos out-taulukolla on väärä dtype tai muoto, funktio nostaa poikkeuksen. Avainsana on tuettu jokaisessa tämän sivun ufunc-funktiossa; se on siisteimmän tapa pitää virtaava signaalinkäsittelysilmukka varauksista vapaana.

6.9.3. Kaksiargumenttiset ufunc-funktiot

arctan2() on yllä olevan listan ainoa aito kaksiargumenttinen ufunc – se palauttaa neljänneksen huomioivan arkustangentin osamäärästä y / x ja lähettää (broadcast) kaksi operandia:

y = np.array([1, 2.2, 33.33, 444.444])
np.arctan2(y, 1.0)             # against a scalar
np.arctan2(1.0, y)             # the other way
np.arctan2(y, y)               # against another array

6.9.4. Universaalifunktioiden yhdistäminen

Universaalifunktiot yhdistyvät kuten mikä tahansa muu taulukkolauseke. Muutama kuvioista, joita kameralla tulee vastaan:

Gammakorjaus (liukulukuavaruudessa)

gamma = 0.5
out = 255.0 * (frame / 255.0) ** gamma

Yksinkertainen alipäästösuodatin (alpha lähellä arvoa 1.0 tarkoittaa hidasta päivitystä):

alpha = 0.95
filtered = alpha * filtered + (1.0 - alpha) * sample

Sigmoid

sigmoid = 1.0 / (1.0 + np.exp(-x))

Tehospektri desibeleinä

spectrum = 20.0 * np.log10(np.abs(real) + 1e-12)

6.9.5. np.vectorize

Tavallinen Python-funktio voidaan korottaa ufunc-muotoiseksi funktiolla vectorize(). Tuloksena saatava kutsuttava hyväksyy skalaareja, iteroitavia tai ndarray-arvoja:

def f(x):
    return x * x

vf = np.vectorize(f)

vf(44.0)                          # array([1936.0])
vf(np.array([1, 2, 3, 4]))        # array([1.0, 4.0, 9.0, 16.0])
vf([2, 3, 4])                     # array([4.0, 9.0, 16.0])

Oletuksena tuloksen dtype on float. otypes= ohittaa sen:

vf_u8 = np.vectorize(f, otypes=np.uint8)
vf_u8([1, 2, 3, 4])
# array([1, 4, 9, 16], dtype=uint8)

Python-funktion täytyy ottaa yksi argumentti ja palauttaa yksi luku.

vectorize() on enimmäkseen syntaktinen – kääritty Python-funktio joutuu silti suorittumaan kerran alkiota kohden, joten suurin osa alkiokohtaisesta tulkkikustannuksesta, jonka aito ufunc välttää, on jälleen läsnä. Odotettavissa on maltillinen 30-50 % nopeutus verrattuna listageneraattoriin, ei aidon universaalifunktion 30-kertaisuus. Tämä on oikea työkalu, kun yhden funktion täytyy toimia skalaareilla, listoilla ja taulukoilla saman nimen alla – ei silloin, kun tavoitteena on pelkkä nopeus.

Jokaisen yllä luetellun universaalifunktion täydelliset kutsuallekirjoitukset löytyvät sivulta numpy — numpy-yhteensopivat taulukko-operaatiot.