【发布时间】:2020-06-09 17:54:32
【问题描述】:
我是社区的新手,如果我没有按预期提供信息,请原谅我。
我正在尝试学习 python,来自 Matlab。我有一个非常简单的代码用于启动目的:
from numpy import vectorize
from scipy import integrate
from scipy.special import j1
from math import sqrt, exp, pi, log
import matplotlib.pyplot as plt
import numpy as np
def plot_hc(radius, pd):
q = np.linspace(0.008, 1.0, num=500)
y = hc(q, radius, pd)
plt.loglog(q, y)
plt.show()
def hc_formfactor(q, radius):
y = (1.0 / q) * (radius * j1(q * radius))
y = y ** 2
return y
def g_distribution(z, radius, pd):
return (1 / (sqrt(2 * pi) * pd)) * exp(
-((z - radius) / (sqrt(
2) * pd)) ** 2)
def ln_distribution(z, radius, pd):
return (1 / (sqrt(2 * pi) * pd * z / radius)) * exp(
-(log(z / radius) / (sqrt(2) * pd)) ** 2)
# Dist=1(for G_Distribution)
# Dist=2(for LN Distribution)
Dist = 1
@vectorize
def hc(x, radius, pd):
global d
if Dist == 1:
nmpts = 4
va = radius - nmpts * pd
vb = radius + nmpts * pd
if va < 0:
va = 0
d = integrate.quad(lambda z: g_distribution(z, radius, pd), va, vb)
elif Dist == 2:
nmpts = 4
va = radius - nmpts * pd
vb = radius + nmpts * pd
if va < 0:
va = 0
d = integrate.quad(lambda z: ln_distribution(z, radius, pd), va, vb)
else:
d = 1
def fun(z, x, radius, pd):
if Dist == 1:
return hc_formfactor(x, z) * g_distribution(z, radius, pd)
elif Dist == 2:
return hc_formfactor(x, z) * ln_distribution(z, radius, pd)
else:
return hc_formfactor(x, z)
y = integrate.quad(lambda z: fun(z, x, radius, pd), va, vb)[0]
return y/d[0]
if __name__ == '__main__':
plot_hc(radius=40, pd=0.5)
正如一些人所建议的,我应该使用 for 循环,但这会进一步降低速度。使用for循环的代码如下:
from numpy import vectorize
from scipy import integrate
from scipy.special import j1
from math import sqrt, exp, pi, log
import matplotlib.pyplot as plt
import numpy as np
def plot_hc(radius, pd):
q = np.linspace(0.008, 1.0, num=500)
y = hc(q, radius, pd)
plt.loglog(q, y)
plt.show()
def hc_formfactor(q, radius):
y = (1.0 / q) * (radius * j1(q * radius))
y = y ** 2
return y
def g_distribution(z, radius, pd):
return (1 / (sqrt(2 * pi) * pd)) * exp(
-((z - radius) / (sqrt(
2) * pd)) ** 2)
def ln_distribution(z, radius, pd):
return (1 / (sqrt(2 * pi) * pd * z / radius)) * exp(
-(log(z / radius) / (sqrt(2) * pd)) ** 2)
# Dist=1(for G_Distribution)
# Dist=2(for LN Distribution)
Dist = 1
def hc(q, radius, pd):
if Dist == 1:
nmpts = 4
va = radius - nmpts * pd
vb = radius + nmpts * pd
if va < 0:
va = 0
d = integrate.quad(lambda z: g_distribution(z, radius, pd), va,vb)
elif Dist == 2:
nmpts = 4
va = radius - nmpts * pd
vb = radius + nmpts * pd
if va < 0:
va = 0
d = integrate.quad(lambda z: ln_distribution(z, radius, pd), va, vb)
else:
d = 1
def fun(z, q, radius, pd):
if Dist == 1:
return hc_formfactor(q, z) * g_distribution(z, radius, pd)
elif Dist == 2:
return hc_formfactor(q, z) * ln_distribution(z, radius, pd)
else:
return hc_formfactor(q, z)
y = empty([len(q)])
for n in range(len(q)):
y[n] = integrate.quad(lambda z: fun(z, q[n], radius, pd), va, vb)[0]
return y / d[0]
if __name__ == '__main__':
plot_hc(radius=40, pd=0.5)
如果我在 Matlab 中为相同的值运行相同的程序,它会非常非常快。我不知道我在这里犯了什么错误。请帮忙:)
【问题讨论】:
-
慢是什么意思?
-
您没有阅读documentation 吗?它明确指出“提供矢量化功能主要是为了方便,而不是为了性能。实现本质上是一个 for 循环。”
-
非常感谢@juanpa.arrivillaga 的回复。我之前确实阅读过文档,但问题是当我使用 for 循环时它变得更慢。这就是我使用矢量化的唯一原因,如代码所示。我已经编辑了我的问题以使用 for 循环发布代码。我可能犯了一个错误。
-
@EdekiOkoh,我所说的慢是指与其他程序相比,评估函数所花费的时间更多:)
-
您可以使用 Numba 来加速您的功能(很容易做到,但调用开销保持不变)或使用 cfunc(可以用 C、Cython、Numba 等编写),例如。 stackoverflow.com/a/49732825/4045774
标签: python matlab scipy vectorization integration