当一个函数在大部分域上为零时,数值计算卷积
numerically computing convolution when one function is zero over large part of domain
我正在尝试计算与 LogNormal 卷积的高斯概率密度函数。与 LogNormal 的宽度相比,Gaussian 的宽度非常小,因此对于大部分积分域 (0, np.inf).
,Gaussian 约为 0
from scipy.integrate import quad
import numpy as np
def _gaussian(x, mu, sigma):
return 1/np.sqrt(2*np.pi*sigma**2)*np.exp(-1*(x - mu)**2/(2*sigma**2))
def _lognormal(x, mu_log, sigma_log):
return 1/(x*sigma_log)*1/np.sqrt(2*np.pi)*np.exp(-1*(np.log(x) - mu_log)**2/(2*sigma_log**2) )
def _gauss_log(t, x0, mu, sigma, mu_log, sigma_log):
return _lognormal(t, mu_log, sigma_log) * _gaussian(x0-t, mu, sigma)
def gauss_log(x, mu, sigma, mu_log, sigma_log):
return [quad(_gauss_log, 0, np.inf, args=(x0, mu, sigma, mu_log, sigma_log))[0] for x0 in x]
x = [ 0.06898463, 0.12137053, 0.21353749, 0.37569469, 0.66099163,
1.16293883, 2.04605725, 3.59980263, 6.33343911, 11.14295839,
19.60475495]
y = [0.00000000e+00, 8.31638354e-02, 1.65440428e-01, 4.02998983e-01,
5.42100908e-01, 4.16612321e-01, 1.72662493e-01, 5.60788435e-02,
1.43433519e-02, 5.43498669e-03, 2.57428324e-04]
x00 = np.linspace(0.01, 20, 100)
plt.loglog(x, y, 'o')
plt.ylim([0.0001, 10])
plt.plot(x00, gauss_log(x00, 0, 0.05, 0.1, 0.9))
plt.show()
如您所见,对于高斯 (x) ~ 0 的某些部分,积分从正确计算的值跳到 ~0。阅读此文:Discontinuity in results when using scipy.integrate.quad 我的想法是我通过以下方式帮助数值积分通过更改变量 t
从 (0, 1) 而不是 (0, inf) 映射集成域。
------ 编辑:最初的问题是我的数学错误引起的。 -----
因此卷积积分必须改为:
PDF(x) = INT_0^inf F(x,t)dt = INT_0^1 F(x, s/(1-s)) /(1-s)^2 ds
其中 F(x,t)
是卷积被积函数,c.f @Juan Carlos Ramirez 回答。
函数_gauss_log
变为:
def _gauss_log(t, x0, mu, sigma, mu_log, sigma_log):
return _lognormal(s/(s-1), mu_log, sigma_log) * _gaussian(x0 - s/(s-1), mu, sigma)/(1-s)**2
此修复改善了这种情况(见下图:顶部图像未转换边界,底部图像有转换),但是,集成仍然不令人满意。我该如何解决这个问题?
您的陈述:
PDF(x) = INT_0^inf F(x,t)dt = INT_0^1 F(x, s) (1+s)^2 ds
不太正确,因为您需要将 t 替换为 F(x,t) 中 s 的函数。请注意
t = 1/(1-s) - 1 = s/(1-s)
因此
dt = 1/(1-s)^2 ds
所以你转换后的积分应该是
INT_0^1 F(x, s/(1-s))/(1-s)^2 ds
quad 函数非常强大,但由于它基本上尝试了一堆不同的数值积分技术,因此可能缺乏透明度。如果您使用梯形规则通过将 [-a,a] 划分为 N 个点的均匀网格来计算从 -a 到 lognormal(x-t)gauss(t) 的 a 的积分会怎么样?由于高斯分布以超指数方式衰减,您可以通过将区间限制为 [-a,a] 来控制误差,同样地,您可以通过查看误差公式(按二次比例缩放,你可以绑定高斯*对数正态的二阶导数)。
https://en.wikipedia.org/wiki/Trapezoidal_rule#Uniform_grid
这将是手波式的,但梯形法则在快速衰减函数上可以有非常好的行为,例如参见 [=15=]。
我正在尝试计算与 LogNormal 卷积的高斯概率密度函数。与 LogNormal 的宽度相比,Gaussian 的宽度非常小,因此对于大部分积分域 (0, np.inf).
,Gaussian 约为 0from scipy.integrate import quad
import numpy as np
def _gaussian(x, mu, sigma):
return 1/np.sqrt(2*np.pi*sigma**2)*np.exp(-1*(x - mu)**2/(2*sigma**2))
def _lognormal(x, mu_log, sigma_log):
return 1/(x*sigma_log)*1/np.sqrt(2*np.pi)*np.exp(-1*(np.log(x) - mu_log)**2/(2*sigma_log**2) )
def _gauss_log(t, x0, mu, sigma, mu_log, sigma_log):
return _lognormal(t, mu_log, sigma_log) * _gaussian(x0-t, mu, sigma)
def gauss_log(x, mu, sigma, mu_log, sigma_log):
return [quad(_gauss_log, 0, np.inf, args=(x0, mu, sigma, mu_log, sigma_log))[0] for x0 in x]
x = [ 0.06898463, 0.12137053, 0.21353749, 0.37569469, 0.66099163,
1.16293883, 2.04605725, 3.59980263, 6.33343911, 11.14295839,
19.60475495]
y = [0.00000000e+00, 8.31638354e-02, 1.65440428e-01, 4.02998983e-01,
5.42100908e-01, 4.16612321e-01, 1.72662493e-01, 5.60788435e-02,
1.43433519e-02, 5.43498669e-03, 2.57428324e-04]
x00 = np.linspace(0.01, 20, 100)
plt.loglog(x, y, 'o')
plt.ylim([0.0001, 10])
plt.plot(x00, gauss_log(x00, 0, 0.05, 0.1, 0.9))
plt.show()
如您所见,对于高斯 (x) ~ 0 的某些部分,积分从正确计算的值跳到 ~0。阅读此文:Discontinuity in results when using scipy.integrate.quad 我的想法是我通过以下方式帮助数值积分通过更改变量 t
从 (0, 1) 而不是 (0, inf) 映射集成域。
------ 编辑:最初的问题是我的数学错误引起的。 -----
因此卷积积分必须改为:
PDF(x) = INT_0^inf F(x,t)dt = INT_0^1 F(x, s/(1-s)) /(1-s)^2 ds
其中 F(x,t)
是卷积被积函数,c.f @Juan Carlos Ramirez 回答。
函数_gauss_log
变为:
def _gauss_log(t, x0, mu, sigma, mu_log, sigma_log):
return _lognormal(s/(s-1), mu_log, sigma_log) * _gaussian(x0 - s/(s-1), mu, sigma)/(1-s)**2
此修复改善了这种情况(见下图:顶部图像未转换边界,底部图像有转换),但是,集成仍然不令人满意。我该如何解决这个问题?
您的陈述:
PDF(x) = INT_0^inf F(x,t)dt = INT_0^1 F(x, s) (1+s)^2 ds
不太正确,因为您需要将 t 替换为 F(x,t) 中 s 的函数。请注意
t = 1/(1-s) - 1 = s/(1-s)
因此
dt = 1/(1-s)^2 ds
所以你转换后的积分应该是
INT_0^1 F(x, s/(1-s))/(1-s)^2 ds
quad 函数非常强大,但由于它基本上尝试了一堆不同的数值积分技术,因此可能缺乏透明度。如果您使用梯形规则通过将 [-a,a] 划分为 N 个点的均匀网格来计算从 -a 到 lognormal(x-t)gauss(t) 的 a 的积分会怎么样?由于高斯分布以超指数方式衰减,您可以通过将区间限制为 [-a,a] 来控制误差,同样地,您可以通过查看误差公式(按二次比例缩放,你可以绑定高斯*对数正态的二阶导数)。 https://en.wikipedia.org/wiki/Trapezoidal_rule#Uniform_grid 这将是手波式的,但梯形法则在快速衰减函数上可以有非常好的行为,例如参见 [=15=]。