Numpy:创建具有指数衰减的正弦波



我是Numpy新手。

我想创建一个包含一百万个数字的数组,该数组具有振幅呈指数衰减的正弦波。

换句话说,我希望每个单元格n的值sin(n) * 2 ** (-n * factor)

最有效的方法是什么?

Numpy 有自己的sin函数,它可以高效地完成你想做的任务。效率低下的主要原因是指数2 ** (-n * factor).

但是,numpy 在其exp函数中确实具有有效的幂。因此,我们可以将基数转换为e以使用exp

exp(-n * factor * log(2))

其中log是另一个 numpy 函数,使用基本e。通过在 numpy 在其矢量化中设置的循环之外进行尽可能多的计算,您可以进一步加快代码速度。换句话说,您首先设置标量

newfactor = -np.log(2) * factor

并使用x = np.linspace(0, 10, 1000000)或类似的东西设置x阵列。然后创建您的y数组

y = np.sin(x) * np.exp(newfactor * x)

现在y是一个数组,其中包含与x数组中的值相对应的所有计算值。

Numpy 自己做循环,对于当前的技术来说非常有效。我的实验表明,以这种方式做幂所需的时间不到np.power(2, -factor * x)2 ** (-x * factor)np.exp2(-x * factor)时间的 1/5。查看整个表达式,对于x长度为一百万的数组,我的代码总共需要29.2 ms才能执行。@ComplicatedPhenomenon的代码看起来不错,总共需要81.3 ms才能执行,这几乎是它的 3 倍。(指出我的代码中的错误@ComplicatedPhenomenon帽子提示 - 我已经纠正了它,现在似乎运行良好。

您可以使用

Numexpr

Numpy 对简单的操作(如 sin(array)、exp(array)具有高效的实现,..问题是每个表达式(sin(n); -n * factor, 2 ** previous_Temp_array)都是使用临时数组单独完成的中间结果。这会导致相当高的内存占用,并且还会对性能产生负面影响。

法典

import numpy as np
import numexpr as ne
def orig(n_max,factor):
n=np.arange(n_max)
return np.sin(n) * 2 ** (-n * factor)
#Rory Daulton's solution
def mod(n_max,factor):
n=np.arange(n_max)
newfactor = -np.log(2) * factor
return np.sin(n) * np.exp(newfactor * n)
def mod_2(n_max,factor):
n=np.arange(n_max)
return ne.evaluate("sin(n) * 2**(-n * factor)")
#Rory Daulton's solution using Numexpr
def mod_3(n_max,factor):
n=np.arange(n_max)
newfactor = -np.log(2) * factor
return ne.evaluate("sin(n) * exp(newfactor * n)")

计时

%timeit res=orig(1e6,0.5)
81 ms ± 4.75 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit res=mod(1e6,0.5)
46.3 ms ± 5.29 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit res=mod_2(1e6,0.5)
16 ms ± 214 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit res=mod_3(1e6,0.5)
11.1 ms ± 48.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

最新更新