6.9. Univerzális függvények

Az univerzális függvény (ufunc) egy olyan matematikai függvény, amely egyetlen hívásban a tömb minden elemére alkalmazódik. Az előző oldalon szereplő aritmetikai operátorok operátorszintaxisba öltöztetett univerzális függvények; ez az oldal a megnevezettek katalógusa, amelyek lefedik a trigonometriát, az exp / log műveleteket, a kerekítést és néhány továbbit.

Minden ufunc elfogad egy skalárt, egy Python iterálhatót vagy egy ndarray objektumot, és vagy egyetlen lebegőpontos számot (ha a bemenet skalár volt), vagy egy lebegőpontos ndarray tömböt ad vissza:

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. A katalógus

A numpy azokat a matematikai függvényeket teszi elérhetővé, amelyekhez egy beágyazott alkalmazás a leggyakrabban nyúl:

Minden függvény a teljes tömböt egyetlen könyvtárhívásban dolgozza fel. A gyorsulás egy olyan Python listaértelmezéshez képest, amely elemenként hívja a math.sin() függvényt, 10-30-szoros egy tipikus pufferen.

6.9.2. Az out= kulcsszó

Minden ufunc-hívás normál esetben friss eredménytömböt foglal le a kimenetének tárolásához. Egy másodpercenként sokszor futó ciklusban ezek a foglalások összeadódnak és RAM-ot pazarolnak. Az out= átadása – egy már létező, a bemenettel azonos alakú lebegőpontos tömb – az eredményt abba a tömbbe írja egy új lefoglalása helyett:

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

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

Ha az out rossz dtype-pal vagy alakkal rendelkezik, a függvény kivételt vált ki. A kulcsszót ezen az oldalon szereplő minden ufunc támogatja; ez a legtisztább módja annak, hogy egy streamelő jelfeldolgozó ciklust foglalásmentesen tartsunk.

6.9.3. Kétargumentumú ufunc-ok

A arctan2() az egyetlen valódi kétargumentumú ufunc a fenti listában – a y / x kvadránstudatos arkusztangensét adja vissza, és a két operandust broadcastolja:

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. Univerzális függvények összeállítása

Az univerzális függvények bármely más tömbkifejezéshez hasonlóan állíthatók össze. Néhány minta, amely a kamerán felmerül:

Gamma-korrekció (lebegőpontos térben)

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

Egy egyszerű aluláteresztő simító (az 1.0 értékhez közeli alpha lassú frissítést jelent):

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

Szigmoid

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

Teljesítményspektrum dB-ben

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

6.9.5. np.vectorize

Egy szokványos Python függvény ufunc-alakúvá léptethető elő a vectorize() segítségével. Az így kapott meghívható objektum elfogad skalárokat, iterálhatókat vagy ndarray értékeket:

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

Alapértelmezésben az eredmény dtype-ja float. Az otypes= felülírja ezt:

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

A Python függvénynek egyetlen argumentumot kell vennie, és egyetlen számot kell visszaadnia.

A vectorize() többnyire szintaktikai – a becsomagolt Python függvénynek továbbra is elemenként egyszer kell lefutnia, így a valódi ufunc által elkerült elemenkénti értelmezői költség nagy része visszatér. Egy listaértelmezéshez képest szerény, 30%-50%-os gyorsulásra számíts, nem egy valódi univerzális függvény 30-szorosára. A megfelelő eszköz, ha egyetlen függvénynek skalárokon, listákon és tömbökön kell ugyanazon a néven működnie – nem akkor, ha a nyers sebesség a cél.

A fent felsorolt összes univerzális függvény teljes hívási szignatúrájáért lásd: numpy — numpy-kompatibilis tömbműveletek.