English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Funcões Gerais ufunc do NumPy

O NumPy fornece dois tipos básicos de objetos, ndarray e objetos ufunc. Ufunc é a abreviação de universal function, que significa “função universal”, é uma função que pode operar em cada elemento de um array.
Muitas funções ufunc são implementadas em nível de linguagem C, portanto, suas velocidades de cálculo são muito rápidas.
Além disso, ufun é mais flexível do que as funções do módulo math. Os inputs do módulo math geralmente são escalares, mas as funções do NumPy podem ser vetores ou matrizes, e usar vetores ou matrizes pode evitar a necessidade de loops, o que é muito importante em aprendizado de máquina e aprendizado profundo.

Por que usar ufuncs?

Ufunc é usado para implementar vectorização no NumPy, o que é muito mais rápido do que iterar pelos elementos.
Eles também fornecem métodos de transmissão e outros, como redução, acumulação, etc., que são muito úteis para cálculos.
Os ufuncs também aceitam outros parâmetros, como:
where é um array booleano ou condição, usado para definir onde a operação deve ser feita.
dtype define o tipo de retorno dos elementos.
O valor de retorno de out deve ser copiado para o array de saída de destino.

Alguns funções comuns de uso geral no NumPy
FunçãoMétodo de uso
sqrt()Calcular a raiz quadrada de dados serializados
sin(), cos()Funções trigonométricas
abs()Calcular o valor absoluto de dados serializados
dot()Operações matriciais
log(), logl(), log2()Função logarítmica
exp()Função exponencial
cumsum(), cumproduct()Soma acumulativa e produto
sum()Somar uma sequência serializada
mean()Calcular a média
median()Calcular a mediana
std()Calcular a desvio padrão
var()Calcular a variância
corrcoef()Calcular o coeficiente de correlação

Comparação de desempenho entre funções math e numpy

import time
 import math
 import numpy as np
 x = [i * 0.001 for i in np.arange(1000000)
 start = time.clock()
 for i, t in enumerate(x):
 x[i] = math.sin(t)
 print("math.sin:", time.clock()) - start)
 x = [i * 0.001 for i in np.arange(1000000)
 x = np.array(x)
 start = time.clock()
 np.sin(x)
 print("numpy.sin:", time.clock()) - start)

Resultados da Execução:

math.sin: 0.5169950000000005
 numpy.sin: 0.05381199999999886

Portanto, numpy.sin é quase tão rápido quanto math.sin: 10 vezes.

Vectorização

Converter expressões iterativas em operações vetoriais é chamado de vectorização.
Devido à otimização de CPU moderna para essas operações, a velocidade é maior.
Somar os elementos de duas listas:
list 1: [1, 2, 3, 4]
list 2: [4, 5, 6, 7]
Um método é percorrer duas listas e somar cada elemento.

Se não houver ufunc, podemos usar o método built-in zip() do Python:

x = [1, 2, 3, 4]
 y = [4, 5, 6, 7]
 z = []
 for i, j in zip(x, y):
   z.append(i + j)
 print(z)

Resultados da Execução:

[5, 7, 9, 11]

Para isso, o NumPy possui uma ufunc chamada add(x, y), que produz o mesmo resultado. Através da ufunc, podemos usar a função add():

import numpy as np
 x = [1, 2, 3, 4]
 y = [4, 5, 6, 7]
 z = np.add(x, y)
 print(z)

Resultados da Execução:

[5, 7, 9, 11]

Comparação entre loop e operações vectorizadas

Utilize plenamente as funções integradas do NumPy (Built-in) no Python-Utilize as funções integradas do NumPy (Built-in) no Python para realizar cálculos vectorizados, o que pode aumentar significativamente a velocidade de execução. As funções integradas do NumPy utilizam instruções SIMD. O uso de vectorização é muito mais rápido do que o cálculo usando loops. Se usar GPU, o desempenho será ainda mais poderoso, embora o NumPy não suporte GPU.
Veja o código abaixo:

import time
 import numpy as np
 x1 = np.random.rand(1000000)
 x2 = np.random.rand(1000000)
 ##Uso de loop para calcular o produto escalar do vetor
 tic = time.process_time()
 dot = 0
 for i in range(len(x1)):
 dot+= x1[i]*x2[i]
 toc = time.process_time()
 print("dot = " + str(dot) + ##Loop for-----Tempo de Cálculo = " + str(1000*(toc - tic)) + "ms")
 ##Uso da função numpy para calcular o produto escalar
 tic = time.process_time()
 dot = 0
 dot = np.dot(x1,x2)
 toc = time.process_time()
 print("dot = " + str(dot) + "\nVersão do Verctor---- Tempo de Cálculo = " + str(1000*(toc - tic)) + "ms")

Resultados da Execução:

 dot = 250215.601995
 loop for-----Tempo de Cálculo = 798.3389819999998ms
 dot = 250215.601995
 Versão do Verctor---- Tempo de Cálculo = 1.885051999999554ms