6.9. Universella funktioner¶
En universell funktion (ufunc) är en matematisk funktion som tillämpas på varje element i en array i ett enda anrop. De aritmetiska operatorerna på föregående sida är universella funktioner i operatorsyntax; denna sida är katalogen över de namngivna som täcker trigonometri, exp / log, avrundning och några andra.
Varje ufunc accepterar en skalär, ett itererbart Python-objekt eller en ndarray, och returnerar antingen en enda float (när indata var skalär) eller en float-ndarray
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. Katalogen¶
numpy exponerar de matematiska funktioner som en inbäddad applikation oftast behöver:
Trigonometri –
sin(),cos(),tan(),asin(),acos(),atan(),arctan2(),sinh(),cosh(),tanh(),asinh(),acosh(),atanh(),sinc().Exponentialfunktioner och logaritmer –
exp(),expm1(),log(),log10(),log2(),sqrt().
Varje funktion bearbetar hela arrayen i ett enda biblioteksanrop. Hastighetsökningen jämfört med en Python-listförståelse som anropar math.sin() element för element är 10-30x på en typisk buffert.
6.9.2. Nyckelordet out=¶
Varje ufunc-anrop allokerar normalt en ny resultatarray för att hålla sin utdata. I en loop som körs många gånger per sekund adderas dessa allokeringar och slösar RAM. Att skicka out= – en float-array som redan finns, med samma form som indata – skriver resultatet in i den arrayen i stället för att allokera en ny:
x = np.linspace(0, 2 * np.pi, num=256)
y = np.zeros(256)
while True:
np.sin(x, out=y)
# use y ...
Om out har fel dtype eller form utlöser funktionen ett undantag. Nyckelordet stöds av varje ufunc på denna sida; det är det renaste sättet att hålla en strömmande signalbehandlingsloop allokeringsfri.
6.9.3. Ufunc med två argument¶
arctan2() är den enda äkta ufunc med två argument i listan ovan – den returnerar den kvadrantmedvetna arctangenten av y / x och broadcastar de två operanderna:
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. Komponera universella funktioner¶
Universella funktioner komponeras som vilket annat array-uttryck som helst. Några mönster som dyker upp på kameran:
Gammakorrigering (i float-rymd)
gamma = 0.5
out = 255.0 * (frame / 255.0) ** gamma
En enkel lågpassutjämnare (alpha nära 1.0 betyder långsam uppdatering):
alpha = 0.95
filtered = alpha * filtered + (1.0 - alpha) * sample
Sigmoid
sigmoid = 1.0 / (1.0 + np.exp(-x))
Effektspektrum i dB
spectrum = 20.0 * np.log10(np.abs(real) + 1e-12)
6.9.5. np.vectorize¶
En vanlig Python-funktion kan befordras till en ufunc-formad funktion med vectorize(). Det resulterande anropsbara objektet accepterar skalärer, itererbara objekt eller ndarray-värden:
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])
Som standard är resultatets dtype float. otypes= åsidosätter det:
vf_u8 = np.vectorize(f, otypes=np.uint8)
vf_u8([1, 2, 3, 4])
# array([1, 4, 9, 16], dtype=uint8)
Python-funktionen måste ta ett enda argument och returnera ett enda tal.
vectorize() är mestadels syntaktisk – den inkapslade Python-funktionen måste fortfarande köras en gång per element, så det mesta av den per-element-tolkkostnad som en äkta ufunc undviker är tillbaka. Förvänta dig en blygsam hastighetsökning på 30 %-50 % jämfört med en listförståelse, inte de 30x som en äkta universell funktion ger. Rätt verktyg när en funktion måste fungera på skalärer, listor och arrayer under samma namn – inte när ren hastighet är målet.
För de fullständiga anropssignaturerna för varje universell funktion som listas ovan, se numpy — numpy-kompatibla arrayoperationer.