我正在为学校做任务,我应该计算一个集成函数的python实现以及同样的numpy实现。我通常希望numpy比python实现更好,但事实并非如此。与numpy数组相比,我使用python中的list comprehension获得大约4倍的速度。从N = 1000到N = 100 000都是如此。没有测试任何更高的值,因为N = 100 000是我需要在估计中得到可接受误差的地方。
常规python代码:
f是要集成的函数,a和b是限制,N是要集成的点数
def integrate(f, a, b, N):
x_val = [a + (i*b) / N for i in range(N+1)]
return sum([f(x_val[i]) * (x_val[i] - x_val[i-1]) for i in range(1, len(x_val))])
Numpy代码:
def numpy_integrate(f, a, b, N):
x_val = numpy.zeros(N+1)
x_val[0] = a
res = 0
for i in numpy.arange(1, len(x_val)):
x_val[i] = a + (i*b)/N
res += f(x_val[i]) * (x_val[i] - x_val[i - 1])
return res
我的numpy实现可能正在做一些可怕的错误,或者这种规模的常规列表理解是否快得多?
答案 0 :(得分:0)
首先,您的代码中存在错误,它只为a=0
提供了正确的结果。您需要将a + (i*b)/N
替换为a + i*(b - a)/N
。
正如COLDSPEED在评论中所说,你没有通过使用for循环来充分利用numpy功能。这是使用数组切片的更高效版本:
def numpy_integrate2(f, a, b, N):
x_val = a + numpy.arange(N+1)*(b - a)/N
return (f(x_val[1:]) * (x_val[1:] - x_val[:-1])).sum()
当我使用平方函数a = 1,b = 2和N = 100000进行测试时,此版本比intergrate
函数快50倍。
编辑:我注意到定义x_val
的速度更快:
x_val = numpy.arange(a, b + (b - a)/N, (b - a)/N)
备注:仅当函数f
可以应用于数组时,此答案才有效。
答案 1 :(得分:0)
这取决于您的f
,如果它允许处理数组,那么您可以使用:
import numpy as np
def integrate(f, a, b, N):
x_val = a + b / N * np.arange(N+1)
return (f(x_val[1:]) * np.diff(x_val)).sum()
这是使用矢量化和广播操作使其(更快)更快。
如果你的f
无法按元素处理数组,你应该使它成为进程数组,或者你需要在那里创建另一个数组:
def integrate(f, a, b, N):
x_val = a + b / N * np.arange(N+1)
return (np.array([f(val) for val in x_val[1:].tolist()]) * np.diff(x_val)).sum()
请注意,您还可以更快地制作列表方法。这是因为迭代元素通常比迭代元素更快,并且你不需要sum
的列表理解,生成器也会做得很好(并且更多的内存 - 有效):
from itertools import tee
def pairwise(iterable):
# taken from https://docs.python.org/3/library/itertools.html#itertools-recipes
a, b = tee(iterable)
next(b, None)
return zip(a, b)
def integrate(f, a, b, N):
x_val = [a + (i*b) / N for i in range(N+1)]
return sum(f(nxt) * (nxt - prev) for prev, nxt in pairwise(x_val))