#python #numpy #scipy
#python #numpy #scipy
Вопрос:
Я могу быстро применить функцию cos следующим образом к массиву numpy с плавающей точкой 32:
cos_f = np.vectorize(lambda x: math.cos(2 * math.pi * x))
signal = square_f(integral)
Однако, если я попробую это:
square_f = np.vectorize(lambda x: sig.square(2 * math.pi * x))
signal = square_f(integral)
для 60 000 выборок требуется 15 секунд. integral
имеет длину 1024 и используется в качестве буфера.
Как я должен применять квадратную волну к своему сигналу?
Комментарии:
1. Откуда
sig.square()
берется? Это код, который вы написали или импортировали из другой библиотеки?2. пожалуйста, укажите все переменные, которые вы используете в своем коде
3.
signal
одинаково в обеих попытках. Это опечатка?
Ответ №1:
Я не уверен, что вам np.vectorize
вообще нужно здесь:
import numpy as np
from scipy import signal as sig
integral = np.linspace(0, 10, 1024)
signal1 = np.cos(2*np.pi * integral)
signal2 = sig.square(2*np.pi * integral)
Вы, конечно, также можете создать функцию, а затем вызвать ее с
помощью массива в качестве входных данных:
def cos2pi(x):
return np.cos(2*np.pi * x)
signal1 = cos2pi(integral)
И можно пойти еще дальше и вызвать функцию только один раз для всех выборок одновременно.
samples = np.random.random((60000, 1024))
signal1 = cos2pi(samples)
Комментарии:
1. Есть ли какие-либо случаи, когда
np.vectorize
стоит использовать вообще?
Ответ №2:
sig.square(2*np.pi * x)
в три раза медленнее, чем np.cos(2*np.pi * x)
, однако, это не является узким местом здесь. Это красивое np.vectorize
оформление на самом деле стоит 120-кратного замедления! Причина, по которой это происходит, заключается в том, что square_f
применяется scipy.signal.square
к итеративным элементам, что представляет собой набор алгоритмов, предназначенных для работы с массивами (в отличие math.cos
от). Это пример арифметики, выполняемой внутри scipy.signal.square
:
def example(x, w=0.5):
return (1 - (w > 1) | (w < 0)) amp; (np.mod(x, 2 * pi) < w * 2 * np.pi)
Предполагая arr
, что это большой массив, это, очевидно, более эффективно вызывать example(arr)
вместо
ex = np.vectorize(lambda x: example(x))
ex(arr)
Тайминги также показывают это:
arr = np.linspace(0,1,1000000)
%timeit ex(arr)
%timeit example(arr)
8.13 s ± 208 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
18.5 ms ± 1.14 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)