如何计算非常小的 y 值的积分(SciPy 四边形)

How to calculate integral for very very small y values (SciPy quad)

这是对数正态分布的概率密度函数:

from scipy.stats import lognorm
def f(x): return lognorm.pdf(x, s=0.2, loc=0, scale=np.exp(10))

此函数具有非常小的 y 值 (max ~ 1E-5) 并分布在 ~1E5 的 x 值上。我们知道一个PDF的积分应该是1,但是用下面的代码直接计算积分,由于计算精度不够,答案是1E-66。

from scipy.integrate import quad
import pandas as pd
ans, err = quad(f, -np.inf, np.inf)

你能帮我正确计算这样的积分吗?谢谢。

您使用的值对应于具有均值 mu = 10 和标准差 sigma = 0.2 的基础正态分布。使用这些值,分布模式(即 PDF 最大值的位置)位于 exp(mu - sigma**2) = 21162.795717500194。函数 quad 工作得很好,但它可能会被愚弄。在这种情况下,显然 quad 仅对值极小的函数进行采样——它永远不会“看到”20000 左右的较高值。

您可以通过计算两个区间的积分来解决这个问题,比如 [0, mode][mode, np.inf]。 (不需要计算负轴上的积分,因为那里的 PDF 为 0。)

例如,此脚本打印 1.0000000000000004

import numpy as np
from scipy.stats import lognorm
from scipy.integrate import quad


def f(x, mu=0, sigma=1):
    return lognorm.pdf(x, s=sigma, loc=0, scale=np.exp(mu))


mu = 10
sigma = 0.2

mode = np.exp(mu - sigma**2)

ans1, err1 = quad(f, 0, mode, args=(mu, sigma))
ans2, err2 = quad(f, mode, np.inf, args=(mu, sigma))

integral = ans1 + ans2
print(integral)