python-2.7 - Python(Scipy): Finding the scale parameter (standard deviation) of a gaussian distribution

标签 python-2.7 scipy statistics

计算概率密度函数 (PDF) 中某个值的概率密度是很常见的。假设我们有一个均值为 40、标准差为 5 的高斯分布,现在想要获得值为 32 的概率密度。我们会这样:

In [1]: import scipy.stats as stats
In [2]: print stats.norm.pdf(32, loc=40, scale=5)
Out [2]: 0.022

--> 概率密度为 2.2%。

但是现在,让我们考虑逆问题。我有平均值,我有概率密度为 0.05 的值,我想获得标准差(即尺度参数)。

我可以实现的是一种数值方法:创建 stats.norm.pdf 几次,并逐步增加比例参数,并采用该方法,使结果尽可能接近。

在我的例子中,我将值 30 指定为 5% 标记。所以我需要解这个“方程”:

stats.norm.pdf(30, loc=40, scale=X) = 0.05

有一个名为“ppf”的 scipy 函数,它是 PDF 的逆函数,因此它将返回特定概率密度的值,但我还没有找到返回比例参数的函数 em>.

实现迭代会花费太多时间(创建和计算)。我的脚本将会很大,所以我应该节省计算时间。在这种情况下 lambda 函数有帮助吗?我大概知道它是做什么的,但到目前为止我还没有使用过它。对此有什么想法吗?

谢谢!

最佳答案

normal probability density函数,f 由下式给出

enter image description here

给定fx,我们希望求解𝞼。来问一下sympy如果它能解方程:

import sympy as sy
from sympy.abc import x, y, sigma

expr = (1/(sy.sqrt(2*sy.pi)*sigma) * sy.exp(-x**2/(2*sigma**2))) - y
ans = sy.solve(expr, sigma)[0]
print(ans)
# sqrt(2)*exp(LambertW(-2*pi*x**2*y**2)/2)/(2*sqrt(pi)*y)

所以看来 LambertW function 存在一个封闭式的解决方案。 ,W,满足

z = W(z) * exp(W(z))

对于所有复值z

我们还可以使用 sympy 来查找给定 xy 的数值结果,但是 也许用以下方法进行数值计算会更快 scipy.special.lambertw :

import numpy as np
import scipy.special as special

def sigma_func(x, y):
    results = set([np.real_if_close(
        np.sqrt(2)*np.exp(special.lambertw(-2*np.pi*x**2*y**2, k=k)/2)
        /(2*np.sqrt(np.pi)*y)).item() for k in (0, -1)])
    results = [s for s in results if np.isreal(s)]
    return results

一般来说,LambertW 函数返回复数值,但我们只是 对 sigma 的实际值(value)解决方案感兴趣。 Per the docs , 当k=0k=1 时,special.lambertw 有两个部分实数分支。所以 上面的代码检查返回值(对于这两个分支)是否为实数,并且 返回任何实际解决方案的列表(如果存在)。如果不存在真正的解决方案, 然后返回一个空列表。如果 pdf 值 y 不是,就会发生这种情况 对于 sigma 的任何实际值(对于给定的 x 值)所获得的值。


你可以像这样使用它:

x = 30.0
loc = 40.0
y = 0.02
s = sigma_func(loc-x, y)
print(s)
# [16.65817044316178, 6.830458938511113]

import scipy.stats as stats
for si in s:
    assert np.allclose(stats.norm.pdf(x, loc=loc, scale=si), y)

在您给出的示例中,y = 0.025,没有 sigma 的解:

import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt

x = 30.0
loc = 40.0
y = 0.025
s = np.linspace(5, 20, 100)
plt.plot(s, stats.norm.pdf(x, loc=loc, scale=s))
plt.hlines(y, 4, 20, color='red')  # the horizontal line y = 0.025
plt.ylabel('pdf')
plt.xlabel('sigma')
plt.show()

enter image description here

因此 sigma_func(40-30, 0.025) 返回一个空列表:

In [93]: sigma_func(40-30, 0.025)
Out [93]: []

上面的图是典型的,当 y 太大时,为零 解,在曲线的最大值处(我们称之为y_max)有一个 解决方案

In [199]: y_max = np.nextafter(np.sqrt(1/(np.exp(1)*2*np.pi*(10)**2)), -np.inf)

In [200]: y_max
Out[200]: 0.024197072451914336

In [201]: sigma_func(40-30, y_max)
Out[201]: [9.9999999776424]

对于小于 y_max 的 y,有两种解决方案。

关于python-2.7 - Python(Scipy): Finding the scale parameter (standard deviation) of a gaussian distribution,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36159067/

相关文章:

python - 重新排序簇号以实现正确对应

Python 自定义异常类应该允许在引发后继续执行程序

python - 使用 numpy 进行下采样

python - 了解显式添加 () 以获得评估的必要性

python - 如何从文本文件计算 python 2.7 中的平均单词和句子长度

python - 边界处的插值掩码

python - 使用 scipy.optimize.minimize() 进行 Ineq 和 eq 约束

python : Any use of this assignment to an empty list?

matlab - 在 MATLAB 中向量化线性方程组的解

machine-learning - 特征归一化