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

Funciones genéricas ufunc de NumPy

NumPy proporciona dos objetos básicos, es decir, ndarray y objetos ufunc. Ufunc es la abreviatura de universal function, lo que significa 'función universal', y es una función que puede operar en cada elemento del array.
Muchas funciones ufunc se implementan a nivel de lenguaje C, por lo que su velocidad de cálculo es muy rápida.
Además, ufun son más flexibles que las funciones del módulo math. Los inputs del módulo math generalmente son escalar, pero las funciones de NumPy pueden ser vectores o matrices, y el uso de vectores o matrices puede evitar el uso de instrucciones de bucle, lo que es muy importante en el aprendizaje automático y el aprendizaje profundo.

¿Por qué usar ufuncs?

Ufunc se utiliza para implementar vectorización en NumPy, lo que es mucho más rápido que iterar elementos.
Ellos también proporcionan emisiones y otros métodos, como reducción y acumulación, que son muy útiles para los cálculos.
Los ufunc también aceptan otros parámetros, como:
where es un array booleano o condición, utilizado para definir dónde se debe realizar la operación.
dtype define el tipo de retorno de los elementos.
El valor devuelto por out debe copiarse en el array de salida.

Algunas funciones comunes de uso general en NumPy
FunciónUso
sqrt()Calcular la raíz cuadrada de una secuencia serializada
sin(), cos()Funciones trigonométricas
abs()Calcular el valor absoluto de una secuencia serializada
dot()Operaciones matriciales
log(), logl(), log2()Función logarítmica
exp()Función exponencial
cumsum(), cumproduct()Suma acumulativa y producto
sum()Sumar una secuencia serializada
mean()Calcular la media
median()Calcular la mediana
std()Calcular la desviación estándar
var()Calcular la varianza
corrcoef()Calcular la correlación

Comparación de rendimiento entre funciones de math y 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 de ejecución:

math.sin: 0.5169950000000005
 numpy.sin: 0.05381199999999886

Por lo tanto, numpy.sin es casi tan rápido como math.sin: 10 Multiplo.

Vectorización

Convertir una instrucción iterativa en una operación basada en vectores se llama vectorización.
Dado que los CPU modernos ya están optimizados para este tipo de operaciones, son más rápidos.
Sumar los elementos de dos listas:
list 1: [1, 2, 3, 4]
list 2: [4, 5, 6, 7]
Un método es recorrer dos listas y sumar cada elemento.

Si no hay ufunc, podemos usar el método内置的 zip() de 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 de ejecución:

[5, 7, 9, 11]

Para esto, NumPy tiene una ufunc, llamada add(x, y), que produce el mismo resultado, a través de ufunc, podemos usar la función add():

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

Resultados de ejecución:

[5, 7, 9, 11]

Comparación entre bucles y operaciones vectorizadas

Utilice al máximo las funciones integradas del paquete NumPy de Python (Built-in)-utilizando funciones integradas del paquete NumPy de Python (Built-in), se puede lograr la vectorización de cálculos, lo que puede mejorar significativamente la velocidad de ejecución. Las funciones integradas del paquete NumPy utilizan instrucciones SIMD. El uso de vectorización aquí es mucho más rápido que el cálculo usando bucles. Si se utiliza GPU, el rendimiento será aún más potente, aunque NumPy no admite GPU.
Vea el siguiente código:

import time
 import numpy as np
 x1 = np.random.rand(1000000)
 x2 = np.random.rand(1000000)
 ## Cálculo del producto escalar de vectores usando bucle
 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) + ## Bucle for-----Tiempo de cálculo = " + str(1000*(toc - tic)) + "ms")
 ## Uso de funciones de numpy para calcular el producto escalar
 tic = time.process_time()
 dot = 0
 dot = np.dot(x1,x2)
 toc = time.process_time()
 print("dot = " + str(dot) + "\nVersión de Verctor---- Tiempo de cálculo = " + str(1000*(toc - tic)) + "ms")

Resultados de ejecución:

 dot = 250215.601995
 bucle for-----Tiempo de cálculo = 798.3389819999998ms
 dot = 250215.601995
 Versión de Verctor---- Tiempo de cálculo = 1.885051999999554ms