我有一个基本上读取的双倍数
sum = exp(x ^ 2 + y ^ 2)
当然,我可以简单地使用两个嵌套的for
循环,但这对于大数字而言往往是耗时的。我可以使用一个列表推导来替换内部for
循环,请参见此处:
import numpy as np
N_x = 100
N_y = 100
# straight forward way
result_1 = .0
for x in xrange(N_x):
for y in xrange(N_y):
result_1 += np.exp( (float(x)/N_x)**2 + ( (float(y)/N_y)**2 )
# using one list comprehension
result_2 = .0
for x in xrange(N_x):
inner_loop = [ np.exp( (float(y)/N_y)**2 ) for y in range(N_y) ]
result_2 += np.exp( (float(x)/N_x)**2 ) * sum(inner_loop)
但是如何用列表理解(我期望更快)替换外部for
循环,任何提示?
答案 0 :(得分:4)
为什么不以笨拙的方式做到......没有for循环:
x = np.arange(N_x)
y = np.arange(N_y)
xx, yy = np.meshgrid(x, y)
result = np.sum(np.exp((xx/N_x)**2 + (yy/N_y)**2))
答案 1 :(得分:2)
你快到了。完整的总和可以写成两个1D总和的乘积,即(sum exp x^2) * (sum exp y^2)
:
>>> import numpy as np
>>>
>>> N_x = N_y = 100
>>>
# brute force
>>> result_1 = .0
>>> for x in xrange(N_x):
... for y in xrange(N_y):
... result_1 += np.exp( (float(x)/N_x)**2 + (float(y)/N_y)**2 )
...
>>> result_1
21144.232143358553
>>>
# single product method
>>> from __future__ import division
>>>
>>> x, y = np.arange(N_x) / N_x, np.arange(N_y) / N_y
>>> np.exp(x*x).sum() * np.exp(y*y).sum()
21144.232143358469
我的猜测是你甚至可以使用list comp并击败蛮力numpy方法:
>> rx, ry = 1.0 / (N_x*N_x), 1.0 / (N_y*N_y)
>>> sum([np.exp(rx*x*x) for x in xrange(N_x)]) * sum([np.exp(ry*y*y) for y in xrange(N_y)])
21144.232143358469
确实,在Python3中完成的时间因为我不知道如何在Python2中使用timeit
:
>>> from timeit import repeat
>>>
>>> kwds = dict(globals=globals(), number=100)
>>>
# single product - list comp
>>> repeat('sum(np.exp(rx*x*x) for x in range(N_x)) * sum(np.exp(ry*y*y) for y in range(N_y))', **kwds)
[0.0166887859813869, 0.016465034103021026, 0.016357041895389557]
>>>
# numpy brute force
>>> repeat('np.exp(np.add.outer(x*x, y*y)).sum()', **kwds)
[0.07063774298876524, 0.0348161740694195, 0.02283189189620316]
显然,numpy单品更快
>>> repeat('np.exp(x*x).sum() * np.exp(y*y).sum()', **kwds)
[0.0031406711786985397, 0.0031003099866211414, 0.0031157969497144222]
答案 2 :(得分:1)
result = sum(np.exp(x**2 + y**2) for x in range(N_x) for y in range(N_y))