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

时间:2019-07-20 12:01:45

标签: python numpy trigonometry

我是个脾气暴躁的新手。

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

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

最有效的方法是什么?

3 个答案:

答案 0 :(得分:2)

Numpy具有其自己的sin函数,可以有效地完成您想完成的任务。效率低下的主要原因是求幂2 ** (-n * factor)

但是,numpy在其exp函数中确实具有有效的幂运算。因此,我们可以通过使用

将基数转换为e以使用exp
exp(-n * factor * log(2))

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

newfactor = -np.log(2) * factor

并使用x或类似方法设置x = np.linspace(0, 10, 1000000)数组。然后用{p>​​创建您的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来执行,几乎是其三倍。 (@ComplicatedPhenomenon的提示指出了我的代码中的错误-我已更正了该错误,并且现在看来效果不错。)

答案 1 :(得分:1)

您可以使用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)

答案 2 :(得分:0)

定义n的范围,并用numpy转换公式。 n是具有相等间隔的点的数组。赚一百万分有一种关系,numberOfPoints=(end-start)/interval

nsample = np.arange(start,end ,(end-start)*pow(10,-6)) 
y = [np.dot(np.sin(n),np.power(2, np.dot(-n, factor))) for n in nsample]