6.9. Univerzální funkce¶
Univerzální funkce (ufunc) je matematická funkce, která se v jednom volání aplikuje na každý prvek pole. Aritmetické operátory na předchozí stránce jsou univerzální funkce v hávu operátorové syntaxe; tato stránka je katalogem těch pojmenovaných, které pokrývají trigonometrii, exp / log, zaokrouhlování a několik dalších.
Každá ufunc přijímá skalár, iterovatelný objekt Pythonu nebo ndarray a vrací buď jeden float (když byl vstup skalár), nebo ndarray typu float:
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. Katalog¶
numpy zpřístupňuje matematické funkce, po kterých vestavěná aplikace sahá nejčastěji:
Trigonometrie –
sin(),cos(),tan(),asin(),acos(),atan(),arctan2(),sinh(),cosh(),tanh(),asinh(),acosh(),atanh(),sinc().Exponenciály a logaritmy –
exp(),expm1(),log(),log10(),log2(),sqrt().
Každá funkce zpracuje celé pole v jednom volání knihovny. Zrychlení oproti generátorovému výrazu Pythonu, který volá math.sin() prvek po prvku, je na typickém bufferu 10-30násobné.
6.9.2. Klíčové slovo out=¶
Každé volání ufunc normálně alokuje nové výsledkové pole pro svůj výstup. Ve smyčce, která běží mnohokrát za sekundu, se tyto alokace nasčítají a plýtvají RAM. Předání out= – již existujícího pole typu float stejného tvaru jako vstup – zapíše výsledek do tohoto pole místo alokace nového:
x = np.linspace(0, 2 * np.pi, num=256)
y = np.zeros(256)
while True:
np.sin(x, out=y)
# use y ...
Pokud má out špatný dtype nebo tvar, funkce vyvolá výjimku. Toto klíčové slovo je podporováno u každé ufunc na této stránce; je to nejčistší způsob, jak udržet průběžnou smyčku zpracování signálu bez alokací.
6.9.3. Ufunc se dvěma argumenty¶
arctan2() je jedinou skutečnou ufunc se dvěma argumenty ve výše uvedeném seznamu – vrací arkustangens y / x s ohledem na kvadrant a broadcastuje oba operandy:
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. Skládání univerzálních funkcí¶
Univerzální funkce se skládají jako kterýkoli jiný výraz nad poli. Několik vzorů, které se na kameře objevují:
Gama korekce (v prostoru float)
gamma = 0.5
out = 255.0 * (frame / 255.0) ** gamma
Jednoduchý dolnopropustný vyhlazovač (alpha blízko 1.0 znamená pomalou aktualizaci):
alpha = 0.95
filtered = alpha * filtered + (1.0 - alpha) * sample
Sigmoid
sigmoid = 1.0 / (1.0 + np.exp(-x))
Výkonové spektrum v dB
spectrum = 20.0 * np.log10(np.abs(real) + 1e-12)
6.9.5. np.vectorize¶
Běžnou funkci Pythonu lze povýšit na funkci ve tvaru ufunc pomocí vectorize(). Výsledný volatelný objekt přijímá skaláry, iterovatelné objekty nebo hodnoty typu ndarray
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])
Ve výchozím nastavení je dtype výsledku float. otypes= jej přepíše:
vf_u8 = np.vectorize(f, otypes=np.uint8)
vf_u8([1, 2, 3, 4])
# array([1, 4, 9, 16], dtype=uint8)
Funkce Pythonu musí přijímat jediný argument a vracet jediné číslo.
vectorize() je převážně syntaktická – zabalená funkce Pythonu se stále musí spustit jednou na každý prvek, takže většina nákladů interpretu na jeden prvek, kterým se skutečná ufunc vyhýbá, je zpět. Očekávejte mírné zrychlení o 30 %-50 % oproti generátorovému výrazu, nikoli 30násobek skutečné univerzální funkce. Je to správný nástroj, když jedna funkce musí pracovat na skalárech, seznamech i polích pod stejným názvem – ne když je cílem čistá rychlost.
Úplné signatury volání každé výše uvedené univerzální funkce najdete v numpy — operace s poli kompatibilní s numpy.