当前位置:  开发笔记 > 编程语言 > 正文

二维高斯分布不等于一吗?

如何解决《二维高斯分布不等于一吗?》经验,为你挑选了1个好方法。

我使用此处给出的公式在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()

另一方面,使用注释行来调整内核大小会得出以下错误图:



1> Praveen..:

当前,您的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 // 2U // 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-可能是最好的选择。

推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有