我是个脾气暴躁的新手。
我想创建一个具有一百万个数字的数组,该数组具有一个正弦波,其振幅呈指数衰减。
换句话说,我希望每个单元格n
的值为sin(n) * 2 ** (-n * factor)
。
最有效的方法是什么?
答案 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)
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]