我正在尝试使用numpy评估多项式(3度)。我发现通过更简单的python代码执行此操作将更加高效。
import numpy as np
import timeit
m = [3,7,1,2]
f = lambda m,x: m[0]*x**3 + m[1]*x**2 + m[2]*x + m[3]
np_poly = np.poly1d(m)
np_polyval = lambda m,x: np.polyval(m,x)
np_pow = lambda m,x: np.power(x,[3,2,1,0]).dot(m)
print 'result={}, timeit={}'.format(f(m,12),timeit.Timer('f(m,12)', 'from __main__ import f,m').timeit(10000))
result=6206, timeit=0.0036780834198
print 'result={}, timeit={}'.format(np_poly(12),timeit.Timer('np_poly(12)', 'from __main__ import np_poly').timeit(10000))
result=6206, timeit=0.180546045303
print 'result={}, timeit={}'.format(np_polyval(m,12),timeit.Timer('np_polyval(m,12)', 'from __main__ import np_polyval,m').timeit(10000))
result=6206, timeit=0.227771043777
print 'result={}, timeit={}'.format(np_pow(m,12),timeit.Timer('np_pow(m,12)', 'from __main__ import np_pow,m').timeit(10000))
result=6206, timeit=0.168987989426
我错过了什么?
numpy中还有另一种方法来评估多项式吗?
好吧,看一下polyval
(当评估一个poly1d时最终会调用的函数)的实现,看来实现者决定包含一个显式循环很奇怪……从numpy 1.6.2的源头开始:
def polyval(p, x):
p = NX.asarray(p)
if isinstance(x, poly1d):
y = 0
else:
x = NX.asarray(x)
y = NX.zeros_like(x)
for i in range(len(p)):
y = x * y + p[i]
return y
一方面,避免电源操作在速度方面应该是有利的,另一方面,python级别的循环几乎把事情搞砸了。
这是另一种numpy-ish实现:
POW = np.arange(100)[::-1]
def g(m, x):
return np.dot(m, x ** POW[m.size : ])
为了提高速度,我避免在每次调用时重新创建电源阵列。同样,为公平起见,在对numpy进行基准测试时,您应该从numpy数组而不是列表开始,以避免在每次调用时将列表转换为numpy的麻烦。
因此,添加时m = np.array(m)
,我的g
运行速度仅比您的慢50%f
。
尽管在您发布的示例中速度较慢,但要对标量上的低次多项式求值x
,您确实不能比显式实现(例如f
)快得多(当然可以,但是可以,但是如果不采取措施,可能不会做得太多)编写较低级别的代码)。但是,对于更高的度数(必须将您的显式表达式替换为某种循环),g
随着度数的增加,numpy方法(例如)会证明快得多,并且对于矢量化求值(即何时x
是向量)也将得到证明。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句