【问题标题】:2D gaussian distribution does not sum to one?二维高斯分布总和不等于一?
【发布时间】:2016-04-15 11:55:58
【问题描述】:

我使用此处给出的等式在 Python 中构建了一个包裹的二元高斯分布: http://www.aos.wisc.edu/~dvimont/aos575/Handouts/bivariate_notes.pdf 但是,我不明白为什么我的分布尽管包含了一个归一化常数,但总和却不能为 1。

对于 U x U 晶格,

import numpy as np
from math import *

U = 60
m = np.arange(U)
i = m.reshape(U,1)
j = m.reshape(1,U)

sigma = 0.1
ii = np.minimum(i, U-i)
jj = np.minimum(j, U-j)
norm_constant = 1/(2*pi*sigma**2)
xmu = (ii-0)/sigma; ymu = (jj-0)/sigma
rhs = np.exp(-.5 * (xmu**2 + ymu**2))
ker = norm_constant * rhs

>> ker.sum() # area of each grid is 1 
15.915494309189533

我确信我的思考方式从根本上缺失,并怀疑需要进行某种额外的规范化,尽管我无法绕过它。

更新:

感谢其他人有见地的建议,我重写了我的代码以将 L1 规范化应用于内核。但是,似乎在通过 FFt 进行 2D 卷积的情况下,将范围保持为 [0, U] 仍然能够返回令人信服的结果:

U = 100
Ukern = np.copy(U)
#Ukern = 15

m = np.arange(U)
i = m.reshape(U,1)
j = m.reshape(1,U)

sigma = 2.
ii = np.minimum(i, Ukern-i)
jj = np.minimum(j, Ukern-j)
xmu = (ii-0)/sigma; ymu = (jj-0)/sigma
ker = np.exp(-.5 * (xmu**2 + ymu**2))
ker /= np.abs(ker).sum()

''' Point Density '''
ido = np.random.randint(U, size=(10,2)).astype(np.int)
og = np.zeros((U,U))
np.add.at(og, (ido[:,0], ido[:,1]), 1)

''' Convolution via FFT and inverse-FFT '''
v1 = np.fft.fft2(ker)
v2 = np.fft.fft2(og)
v0 = np.fft.ifft2(v2*v1)
dd = np.abs(v0)

plt.plot(ido[:,1], ido[:,0], 'ko', alpha=.3)
plt.imshow(dd, origin='origin')
plt.show()

另一方面,使用注释掉的行调整内核大小会给出这个错误的图:

【问题讨论】:

  • 我不完全明白您为什么需要np.minimum(i, U-i)。你想在那里实现什么目标?
  • 另外,你能在这里定义一下“包装”是什么意思吗?
  • @Praveen imaluengo 在怀疑我正在尝试构建一个高斯核时是正确的——它代表了个体的运动范围,我将它与离散的人口分布进行卷积以估计人口密度表面。 minimum 函数将内核的峰值设置在原点,内核值随着到原点的距离而减小。因此,“包裹”意味着内核“包裹”在 UxU 晶格边缘周围,从而产生四个角的半圆图。

标签: python numpy distribution gaussian probability-density


【解决方案1】:

注意:如下面的 cmets 所述,此解决方案仅在您尝试构建高斯卷积核(或高斯滤波器)用于图像处理时才有效。它不是一个适当归一化的高斯密度函数,但它是用于从图像中去除高斯噪声的形式。


您缺少 L1 标准化:

ker /= np.abs(ker).sum()

这将使您的内核表现得像一个实际的密度函数。由于您拥有的网格的值大小可能会有很大差异,因此需要上述标准化步骤。

事实上,你可以省略高斯归一化常数,只使用上面的 L1 范数。如果我没穿,你正在尝试创建一个高斯卷积,上面是应用于它的常用归一化技术。

正如@Praveen 所说,您的第二个错误是您需要从[-U//2, U//2] 中采样网格。你可以这样做:

i, j = np.mgrid[-U//2:U//2+1, -U//2:U//2+1]

最后,如果您要做的是构建一个高斯滤波器,内核的大小通常从 sigma 估计(以避免远离中心的零)为U//2 <= t * sigma,其中t 是截断参数通常设置t=3t=4

【讨论】:

  • 我认为这不是一个好主意。 OP 似乎正在尝试创建概率分布(根据所遵循的注释)。盲目地对内核进行归一化会产生有效的概率密度,但会破坏其大部分统计特性。
  • @Praveen 然而,在图像处理中使用 L1 归一化高斯核来从图像中去除高斯噪声。我确实同意它不能正确保留统计属性,但如果我没记错并且 OP 想要的是高斯滤波器(而不是高斯模型),那么它就是要走的路。
  • @Praveen,感谢 cmets。你帮我说得更清楚(针对特定情况)。你也有我的,因为你的答案实际上是一个真正的高斯模型(我们还不知道 :p 之后的 OP 是什么)。这种讨论非常有帮助,因为人们总能学到一些已知的东西。谢谢!
  • @imaluengo 我确实在为卷积创建一个高斯核。你读懂了我的意图! :) 感谢您的持续输入和编辑!但是,我对您提出的后两点仍然有些困惑:为什么有必要从 [-U//2, U//2] 对网格进行采样,以及为什么以我的方式从 [ 0, U]?
  • @neither-not 不,它适用于 python。结果完全没问题。您只是在傅立叶域中进行卷积,而不是在图像域中进行卷积(通过一次错误点击,我删除了我的旧评论)。我现在不在电脑前(平板电脑),明天我会用 2 个傅立叶卷积和滑动窗口卷积的例子来更新帖子。
【解决方案2】:

目前,ker 的(放大很多)等值线图如下所示:

如您所见,这看起来一点也不像高斯核。您的大多数函数从 0 到 1 消失。查看内核本身会发现所有值确实真的很快消失:

>>> ker[0:5, 0:5]
array([[  1.592e+001,   3.070e-021,   2.203e-086,   5.879e-195,   0.000e+000],
       [  3.070e-021,   5.921e-043,   4.248e-108,   1.134e-216,   0.000e+000],
       [  2.203e-086,   4.248e-108,   3.048e-173,   8.136e-282,   0.000e+000],
       [  5.879e-195,   1.134e-216,   8.136e-282,   0.000e+000,   0.000e+000],
       [  0.000e+000,   0.000e+000,   0.000e+000,   0.000e+000,   0.000e+000]])

你得到的 15.915 的总和值基本上就是 ker[0, 0]。这一切都告诉你,你没有正确地构建你的网格。

请记住,在计算机上创建内核时,您必须在适当的位置对其进行采样。采样太粗会导致你的总和不正确。

首先,如果您想要以mu=0 为中心的全密度,您必须将ij-U // 2 带到U // 2。但要解决您的分辨率问题,我建议将U 的点数取在-0.5 到0.5 之间。

import numpy as np
import matplotlib.pyplot as plt

U = 60
m = np.linspace(-0.5, 0.5, U)    # 60 points between -1 and 1
delta = m[1] - m[0]              # delta^2 is the area of each grid cell
(x, y) = np.meshgrid(m, m)       # Create the mesh

sigma = 0.1
norm_constant = 1 / (2 * np.pi * sigma**2)

rhs = np.exp(-.5 * (x**2 + y**2) / sigma**2)
ker = norm_constant * rhs
print(ker.sum() * delta**2)

plt.contour(x, y, ker)
plt.axis('equal')
plt.show()

这会产生接近 1.0 的总和,并且内核以mu=0 为中心,正如预期的那样。

在这种情况下,了解选择的范围(-0.5 到 0.5)取决于您的功能。例如,如果您现在采用sigma = 2,您会发现您的总和不会再次计算出来,因为现在您的采样太精细了。将范围设置为参数的函数(例如 -5 * sigma5 * sigma)可能是最好的选择。

【讨论】:

  • 如果您愿意,可以添加plt.axis('equal') 行,这样图片的宽高比为 1:1
  • @heltonbiker 是的。我只是没有考虑。那让我稍微改进一下。
  • @Praveen 尽管我没有在这里创建统计上有效的概率密度,但您的输入非常有帮助,而且肯定很快就会对我有用!
猜你喜欢
  • 2015-07-21
  • 2013-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-14
  • 1970-01-01
相关资源
最近更新 更多