Python中的向量化重复数学函数
我有一个数学函数,它的形式是Python中的向量化重复数学函数,python,numpy,vectorization,mathematical-expressions,Python,Numpy,Vectorization,Mathematical Expressions,我有一个数学函数,它的形式是$f(x)=\sum{j=0}^nx^j*\sin(j*x)$,我想用Python高效地计算它。N的数量级为~100。对于一个巨大矩阵的所有条目x,该函数f被求值数千次,因此我想提高性能(探查器表明,f的计算占用了大部分时间)。为了避免函数f定义中的循环,我写了: def f(x) J=np.arange(0,N+1) return sum(x**J*np.sin(j*x)) 问题是,如果我想为矩阵的所有条目计算此函数,我需要首先使用numpy.ve
$f(x)=\sum{j=0}^nx^j*\sin(j*x)$
,我想用Python
高效地计算它。N的数量级为~100。对于一个巨大矩阵的所有条目x,该函数f被求值数千次,因此我想提高性能(探查器表明,f的计算占用了大部分时间)。为了避免函数f定义中的循环,我写了:
def f(x)
J=np.arange(0,N+1)
return sum(x**J*np.sin(j*x))
问题是,如果我想为矩阵的所有条目计算此函数,我需要首先使用numpy.vectorize
,但据我所知,这并不一定比for循环快
有没有一种有效的方法来执行这种类型的计算?欢迎使用Sack Overflow^^ 嗯,计算某物**100是一件严肃的事情。但是请注意,当您声明数组
J
时,您是如何强制函数独立地计算x、x^2、x^3、x^4、
(等等)
让我们以该函数为例(您正在使用该函数):
现在还有一个函数,它甚至不使用NumPy:
def power(x, n):
result = [1., x]
aux = x
for i in range(2, n):
aux *= x
result.append(aux)
return result
现在,让我们验证一下,它们都计算了相同的东西:
In []: sum(powervector(1.1, 10))
Out[]: 15.937424601000005
In []: sum(power(1.1, 10))
Out[]: 15.937424601000009
很酷,现在让我们比较一下这两种方法的性能(在iPython中):
它更快,因为您没有计算x
的所有幂,因为您知道x^N==(x^N-1)*x
,您可以利用它
你可以用这个来看看你的表现是否有所改善。当然,您可以更改power()
以使用NumPy向量作为输出。您还可以看一看,这很容易尝试,也可以稍微提高性能
正如您所看到的,这只是一个提示,说明如何改进问题的某些方面。我打赌还有其他几种方法可以进一步改进您的代码!:-)
编辑
看来麻木可能不是个坏主意。。。只需添加@numba.jit
装饰器:
@numba.jit
def powernumba(x, n):
result = [1., x]
aux = x
for i in range(2, n):
aux *= x
result.append(aux)
return result
然后:
似乎麻麻可以在那里施展魔法 对于标量
x
:
>>> import numpy as np
>>> x = 0.5
>>> jj = np.arange(10)
>>> x**jj
array([ 1. , 0.5 , 0.25 , 0.125 , 0.0625 ,
0.03125 , 0.015625 , 0.0078125 , 0.00390625, 0.00195312])
>>> np.sin(jj*x)
array([ 0. , 0.47942554, 0.84147098, 0.99749499, 0.90929743,
0.59847214, 0.14112001, -0.35078323, -0.7568025 , -0.97753012])
>>> (x**jj * np.sin(jj*x)).sum()
0.64489974041068521
注意numpy数组的sum
方法的使用(等效地,使用np.sum
不是内置的sum
)
如果x
本身是一个数组,请使用广播:
>>> a = x[:, None]**jj
>>> a.shape
(3, 10)
>>> x[0]**jj == a[0]
array([ True, True, True, True, True, True, True, True, True, True], dtype=bool)
然后在第二个轴上求和:
>>> res = a * np.sin(jj * x[:, None])
>>> res.shape
(3, 10)
>>> res.sum(axis=1)
array([ 0.01230993, 0.0613201 , 0.17154859])
这是一个好主意,我一定会按照这些思路实施一些东西。然而,在将来,对于某些函数g,我希望用类似sum_{j=0}^N g(x,C)的东西来替换表达式,因此我试图寻找一种更通用的方法来改进代码,而不管函数g如何。@PythonBeginner:Numba仍然适用于这种情况。看看那个项目,你不会后悔的!;-)我第一次听说麻麻,我会看一看:)
>>> import numpy as np
>>> x = 0.5
>>> jj = np.arange(10)
>>> x**jj
array([ 1. , 0.5 , 0.25 , 0.125 , 0.0625 ,
0.03125 , 0.015625 , 0.0078125 , 0.00390625, 0.00195312])
>>> np.sin(jj*x)
array([ 0. , 0.47942554, 0.84147098, 0.99749499, 0.90929743,
0.59847214, 0.14112001, -0.35078323, -0.7568025 , -0.97753012])
>>> (x**jj * np.sin(jj*x)).sum()
0.64489974041068521
>>> a = x[:, None]**jj
>>> a.shape
(3, 10)
>>> x[0]**jj == a[0]
array([ True, True, True, True, True, True, True, True, True, True], dtype=bool)
>>> res = a * np.sin(jj * x[:, None])
>>> res.shape
(3, 10)
>>> res.sum(axis=1)
array([ 0.01230993, 0.0613201 , 0.17154859])