在概率密度函数(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,我希望得到标准偏差(即比例参数)。
我可以实现的是一种数值方法:在逐步增加scale-parameter的情况下多次创建stats.norm.pdf,并使结果尽可能接近结果。
在我的情况下,我将值30指定为5%标记。所以我需要解决这个“等式”:
stats.norm.pdf(30, loc=40, scale=X) = 0.05
有一个名为“ppf”的scipy函数,它是PDF的反函数,因此它将返回特定概率密度的值,但我还没有找到一个函数来返回 scale参数
实现迭代会花费太多时间(创建和计算)。我的脚本将是巨大的,所以我应该节省计算时间。在这种情况下,lambda函数能帮助吗?我大致知道它在做什么,但到目前为止我还没有使用它。关于这个的任何想法?
谢谢!
答案 0 :(得分:2)
normal probability density函数f
由
我们希望为f
解决x
和。让我们问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来查找给定x
和y
的数值结果,但是
也许用数字工作会更快
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
的实值解决方案感兴趣。 Per the
docs,
在special.lambertw
和k=0
时,k=1
有两个部分真实的分支。所以
上面的代码检查返回的值(对于那两个分支)是否真实,以及
返回任何真实解决方案的列表(如果存在)。如果没有真正的解决方案,
然后返回一个空列表。如果pdf值y
不是,则会发生这种情况
达到西格玛的任何实际价值(对于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()
所以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,有两种解决方案。
答案 1 :(得分:0)
这将是两个解决方案,因为普通PDF是围绕均值对称的。
就目前而言,你有一个单变量方程可以解决。 它不会有封闭式解决方案,所以你可以使用例如scipy.optimize.fsolve
解决它。