更新标题:Scipy.stats pdf 错误?
Posted
技术标签:
【中文标题】更新标题:Scipy.stats pdf 错误?【英文标题】:Updtated titlle: Scipy.stats pdf bug? 【发布时间】:2020-07-06 09:28:33 【问题描述】:我有一个简单的二维高斯分布图。
from scipy.stats import multivariate_normal
from matplotlib import pyplot as plt
means = [ 1.03872615e+00, -2.66927843e-05]
cov_matrix = [[3.88809050e-03, 3.90737359e-06], [3.90737359e-06, 4.28819569e-09]]
# This works
a_lims = [0.7, 1.3]
b_lims = [-5, 5]
# This does not work
a_lims = [0.700006488869478, 1.2849292618191401]
b_lims =[-5.000288311285968, 5.000099437047633]
dist = multivariate_normal(mean=means, cov=cov_matrix)
a_plot, b_plot = np.mgrid[a_lims[0]:a_lims[1]:1e-2, b_lims[0]:b_lims[1]:0.1]
pos = np.empty(a_plot.shape + (2,))
pos[:, :, 0] = a_plot
pos[:, :, 1] = b_plot
z = dist.pdf(pos)
plt.figure()
plt.contourf(a_plot, b_plot, z, cmap='coolwarm', levels=100)
如果我使用标记为“这有效”的限制,我会得到以下图(正确)。
但是,如果我使用相同的限制,但稍作调整,则绘制完全错误,因为定位在不同的值(如下)。
我猜这是mgrid
中的一个错误。有没有人有任何想法?更具体地说,为什么分布的最大值会移动?
【问题讨论】:
制作pos
的更简单方法:pos = np.dstack(np.mgrid[a_lims[0]:a_lims[1]:1e-2, b_lims[0]:b_lims[1]:0.1])
另外,错误不在mgrid
中,您可以通过显示每次都正确生成网格来验证这一点
该错误似乎出现在 PDF 函数中。不是它的实现,而是你的使用。我认为对于该协方差矩阵,您没有看到高斯椭圆中的任何旋转,这有点令人怀疑
我也不确定第一个情节是否正确。 x-mean 看起来在 1.0 和 1.1 之间接近 1.1,可能是 1.06 或 1.07,绝对不是 1.038。
你的 X 和 Y 被交换了。 A 是行 (y),B 是列 (X)
【参考方案1】:
只关注xaxis
:
In [443]: a_lims = [0.7, 1.3]
In [444]: np.mgrid[a_lims[0]:a_lims[1]:1e-2]
Out[444]:
array([0.7 , 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.8 ,
0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.9 , 0.91,
0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1. , 1.01, 1.02,
1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.09, 1.1 , 1.11, 1.12, 1.13,
1.14, 1.15, 1.16, 1.17, 1.18, 1.19, 1.2 , 1.21, 1.22, 1.23, 1.24,
1.25, 1.26, 1.27, 1.28, 1.29, 1.3 ])
In [445]: a_lims = [0.700006488869478, 1.2849292618191401]
In [446]: np.mgrid[a_lims[0]:a_lims[1]:1e-2]
Out[446]:
array([0.70000649, 0.71000649, 0.72000649, 0.73000649, 0.74000649,
0.75000649, 0.76000649, 0.77000649, 0.78000649, 0.79000649,
0.80000649, 0.81000649, 0.82000649, 0.83000649, 0.84000649,
0.85000649, 0.86000649, 0.87000649, 0.88000649, 0.89000649,
0.90000649, 0.91000649, 0.92000649, 0.93000649, 0.94000649,
0.95000649, 0.96000649, 0.97000649, 0.98000649, 0.99000649,
1.00000649, 1.01000649, 1.02000649, 1.03000649, 1.04000649,
1.05000649, 1.06000649, 1.07000649, 1.08000649, 1.09000649,
1.10000649, 1.11000649, 1.12000649, 1.13000649, 1.14000649,
1.15000649, 1.16000649, 1.17000649, 1.18000649, 1.19000649,
1.20000649, 1.21000649, 1.22000649, 1.23000649, 1.24000649,
1.25000649, 1.26000649, 1.27000649, 1.28000649])
In [447]: _444.shape
Out[447]: (61,)
In [449]: _446.shape
Out[449]: (59,)
mgrid
当给定范围如a:b:c
使用np.arange(a, b, c)
。 arange
当给定的浮点步骤对于终点不可靠时。
mgrid
允许您使用np.linspace
,它更适合浮点步骤。例如第一组限制:
In [453]: a_lims = [0.7, 1.3]
In [454]: np.mgrid[a_lims[0]:a_lims[1]:61j]
Out[454]:
array([0.7 , 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.8 ,
0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.9 , 0.91,
0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1. , 1.01, 1.02,
1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.09, 1.1 , 1.11, 1.12, 1.13,
1.14, 1.15, 1.16, 1.17, 1.18, 1.19, 1.2 , 1.21, 1.22, 1.23, 1.24,
1.25, 1.26, 1.27, 1.28, 1.29, 1.3 ])
===
通过显着缩小b_lims
并生成更精细的网格,我得到了一个漂亮的倾斜椭圆。
means = [ 1, 0]
a_lims = [0.7, 1.3]
b_lims = [-.0002,.0002]
dist = multivariate_normal(mean=means, cov=cov_matrix)
a_plot, b_plot = np.mgrid[ a_lims[0]:a_lims[1]:1001j, b_lims[0]:b_lims[1]:1001j]
所以我认为您的绘图中的差异是垂直方向上过于粗糙的网格的伪影。这可能会影响pdf
的生成和轮廓。
具有原始网格点的高分辨率绘图。只有一个b
级别与高概率值相交。由于椭圆是倾斜的,因此两个网格对不同的部分进行采样,因此看似不同的 pdf。
【讨论】:
好的,谢谢。但是终点与分布的平均值有什么关系呢?只要形状一致,就没有关系,对吧? 我没有尝试遵循 pdf 分发的逻辑。我没用过multivariate_normal
。当然,我不希望改变,但是......
对,但我的问题不是如何制作给定形状的点数组,而是为什么情节看起来不同?您建议的网格仍然是同一间隔内的网格。不过,我同意对您的观点进行更多控制的观点。
我在运行之间使用了一个新的控制台,并且能够重现结果。我不认为means
是问题以上是关于更新标题:Scipy.stats pdf 错误?的主要内容,如果未能解决你的问题,请参考以下文章
关于协方差最小化 scipy.stats.multivariate_normal.logpdf