6.9. Funções universais¶
Uma função universal (ufunc) é uma função matemática que se aplica a cada elemento de um array em uma única chamada. Os operadores aritméticos da página anterior são funções universais vestindo sintaxe de operador; esta página é o catálogo das funções nomeadas que cobrem trigonometria, exp / log, arredondamento e algumas outras.
Cada ufunc aceita um escalar, um iterável Python ou um ndarray, e retorna um único float (quando a entrada era escalar) ou um ndarray de floats:
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. O catálogo¶
O numpy expõe as funções matemáticas que uma aplicação embarcada usa com mais frequência:
Trigonometria –
sin(),cos(),tan(),asin(),acos(),atan(),arctan2(),sinh(),cosh(),tanh(),asinh(),acosh(),atanh(),sinc().Exponenciais e logaritmos –
exp(),expm1(),log(),log10(),log2(),sqrt().
Cada função processa o array inteiro em uma única chamada de biblioteca. A aceleração em relação a uma compreensão de lista Python que chama math.sin() elemento a elemento é de 10 a 30x em um buffer típico.
6.9.2. A palavra-chave out=¶
Cada chamada de ufunc normalmente aloca um novo array de resultado para conter sua saída. Em um laço que roda muitas vezes por segundo, essas alocações se acumulam e desperdiçam RAM. Passar out= – um array de floats que já existe, com a mesma forma da entrada – escreve o resultado nesse array em vez de alocar um novo:
x = np.linspace(0, 2 * np.pi, num=256)
y = np.zeros(256)
while True:
np.sin(x, out=y)
# use y ...
Se out tiver dtype ou forma errados, a função lança uma exceção. A palavra-chave é suportada em todas as ufuncs desta página; é a maneira mais limpa de manter um laço de processamento de sinais em fluxo livre de alocações.
6.9.3. Ufuncs de dois argumentos¶
arctan2() é a única ufunc de dois argumentos de verdade na lista acima – ela retorna a arco-tangente de y / x com consciência de quadrante e faz broadcasting dos dois operandos:
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. Compondo funções universais¶
Funções universais se compõem como qualquer outra expressão de array. Alguns padrões que surgem na câmera:
Correção de gama (no espaço de float)
gamma = 0.5
out = 255.0 * (frame / 255.0) ** gamma
Um suavizador passa-baixa simples (alpha próximo de 1.0 significa atualização lenta):
alpha = 0.95
filtered = alpha * filtered + (1.0 - alpha) * sample
Sigmoide
sigmoid = 1.0 / (1.0 + np.exp(-x))
Espectro de potência em dB
spectrum = 20.0 * np.log10(np.abs(real) + 1e-12)
6.9.5. np.vectorize¶
Uma função Python comum pode ser promovida a uma com formato de ufunc por vectorize(). O chamável resultante aceita escalares, iteráveis ou valores 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])
Por padrão, o dtype do resultado é float. otypes= o sobrescreve:
vf_u8 = np.vectorize(f, otypes=np.uint8)
vf_u8([1, 2, 3, 4])
# array([1, 4, 9, 16], dtype=uint8)
A função Python deve receber um único argumento e retornar um único número.
vectorize() é principalmente sintática – a função Python encapsulada ainda precisa rodar uma vez por elemento, então a maior parte do custo de interpretador por elemento que uma ufunc de verdade evita está de volta. Espere uma aceleração modesta de 30%-50% em relação a uma compreensão de lista, não os 30x de uma função universal de verdade. É a ferramenta certa quando uma função tem de trabalhar com escalares, listas e arrays sob o mesmo nome – não quando o objetivo é velocidade pura.
Para as assinaturas de chamada completas de todas as funções universais listadas acima, consulte numpy — operações de array compatíveis com numpy.