[英]How to plot a 2d gaussian with different sigma?
I am trying to make and plot a 2d gaussian with two different standard deviations.我正在尝试制作和绘制具有两个不同标准差的二维高斯。 They give the equation on mathworld: http://mathworld.wolfram.com/GaussianFunction.html but I can't seem to get a proper 2D array which centers it around zero.他们给出了关于 mathworld 的方程: http ://mathworld.wolfram.com/GaussianFunction.html 但我似乎无法得到一个以零为中心的正确二维数组。
I got this, but it does not quite work.我得到了这个,但它并不完全有效。
x = np.array([np.arange(size)])
y = np.transpose(np.array([np.arange(size)]))
psf = 1/(2*np.pi*sigma_x*sigma_y) * np.exp(-(x**2/(2*sigma_x**2) + y**2/(2*sigma_y**2)))
Your function is centred on zero but your coordinate vectors are not.您的函数以零为中心,但您的坐标向量不是。 Try:尝试:
size = 100
sigma_x = 6.
sigma_y = 2.
x = np.linspace(-10, 10, size)
y = np.linspace(-10, 10, size)
x, y = np.meshgrid(x, y)
z = (1/(2*np.pi*sigma_x*sigma_y) * np.exp(-(x**2/(2*sigma_x**2)
+ y**2/(2*sigma_y**2))))
plt.contourf(x, y, z, cmap='Blues')
plt.colorbar()
plt.show()
Probably this answer is too late for @Coolcrab , but I would like to leave it here for future reference.可能这个答案对@Coolcrab 来说太晚了,但我想把它留在这里以备将来参考。
You can use a multivariate Gaussian formula as follows您可以使用多元高斯公式如下
changing the mean elements changes the origin, while changing the covariance elements changes the shape (from circle to ellipse).改变平均元素会改变原点,而改变协方差元素会改变形状(从圆形到椭圆形)。
Here is the code:这是代码:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
# Our 2-dimensional distribution will be over variables X and Y
N = 40
X = np.linspace(-2, 2, N)
Y = np.linspace(-2, 2, N)
X, Y = np.meshgrid(X, Y)
# Mean vector and covariance matrix
mu = np.array([0., 0.])
Sigma = np.array([[ 1. , -0.5], [-0.5, 1.]])
# Pack X and Y into a single 3-dimensional array
pos = np.empty(X.shape + (2,))
pos[:, :, 0] = X
pos[:, :, 1] = Y
def multivariate_gaussian(pos, mu, Sigma):
"""Return the multivariate Gaussian distribution on array pos."""
n = mu.shape[0]
Sigma_det = np.linalg.det(Sigma)
Sigma_inv = np.linalg.inv(Sigma)
N = np.sqrt((2*np.pi)**n * Sigma_det)
# This einsum call calculates (x-mu)T.Sigma-1.(x-mu) in a vectorized
# way across all the input variables.
fac = np.einsum('...k,kl,...l->...', pos-mu, Sigma_inv, pos-mu)
return np.exp(-fac / 2) / N
# The distribution on the variables X, Y packed into pos.
Z = multivariate_gaussian(pos, mu, Sigma)
# plot using subplots
fig = plt.figure()
ax1 = fig.add_subplot(2,1,1,projection='3d')
ax1.plot_surface(X, Y, Z, rstride=3, cstride=3, linewidth=1, antialiased=True,
cmap=cm.viridis)
ax1.view_init(55,-70)
ax1.set_xticks([])
ax1.set_yticks([])
ax1.set_zticks([])
ax1.set_xlabel(r'$x_1$')
ax1.set_ylabel(r'$x_2$')
ax2 = fig.add_subplot(2,1,2,projection='3d')
ax2.contourf(X, Y, Z, zdir='z', offset=0, cmap=cm.viridis)
ax2.view_init(90, 270)
ax2.grid(False)
ax2.set_xticks([])
ax2.set_yticks([])
ax2.set_zticks([])
ax2.set_xlabel(r'$x_1$')
ax2.set_ylabel(r'$x_2$')
plt.show()
For that you can use the multivariate_normal() from the scipy package like this:为此,您可以使用 scipy 包中的multivariate_normal() ,如下所示:
# Imports
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import multivariate_normal
from mpl_toolkits.mplot3d import Axes3D
# Data
x = np.linspace(-10, 10, 500)
y = np.linspace(-10, 10, 500)
X, Y = np.meshgrid(x,y)
# Multivariate Normal
mu_x = np.mean(x)
sigma_x = np.std(x)
mu_y = np.mean(y)
sigma_y = np.std(y)
rv = multivariate_normal([mu_x, mu_y], [[sigma_x, 0], [0, sigma_y]])
# Probability Density
pos = np.empty(X.shape + (2,))
pos[:, :, 0] = X
pos[:, :, 1] = Y
pd = rv.pdf(pos)
# Plot
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(X, Y, pd, cmap='viridis', linewidth=0)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Probability Density')
plt.title("Multivariate Normal Distribution")
plt.show()
Your Gaussian is centered on (0,0) so set up the axes around this origin.你的高斯以 (0,0) 为中心,所以围绕这个原点设置轴。 For example,例如,
In [40]: size = 200
In [41]: sigma_x,sigma_y = 50, 20
In [42]: x = np.array([np.arange(size)]) - size/2
In [43]: y = np.transpose(np.array([np.arange(size)])) - size /2
In [44]: psf = 1/(2*np.pi*sigma_x*sigma_y) *
np.exp(-(x**2/(2*sigma_x**2) + y**2/(2*sigma_y**2)))
In [45]: pylab.imshow(psf)
Out[45]: <matplotlib.image.AxesImage at 0x10bc07f10>
In [46]: pylab.show()
I think this is indeed not very friendly.我觉得这确实不是很友好。 I will write here the code and explain why it works.我将在这里编写代码并解释它为什么起作用。
The equation of a multivariate gaussian is as follows:多元高斯方程如下:
In the 2D case,在二维情况下, and和 are 2D column vectors,是二维列向量, is a 2x2 covariance matrix and n=2 .是一个 2x2 协方差矩阵且n=2 。
So in the 2D case, the vector所以在二维情况下,向量 is actually a point (x,y) , for which we want to compute function value, given the 2D mean vector实际上是一个点(x,y) ,我们想要计算函数值,给定 2D 均值向量 , which we can also write as (mX, mY) , and the covariance matrix ,我们也可以写成(mX, mY) ,以及协方差矩阵 . .
To make it more friendly to implement, let's compute the result of为了更友好地实现,让我们计算结果 : :
So所以 is the column vector (x - mX, y - mY) .是列向量(x - mX, y - mY) 。 Therefore, the result of computing因此,计算结果 is the 2D row vector:是二维行向量:
(CI[0,0] * (x - mX) + CI[1,0] * (y - mY) , CI[0,1] * (x - mX) + CI[1,1] * (y - mY)) , where CI is the inverse of the covariance matrix, shown in the equation as (CI[0,0] * (x - mX) + CI[1,0] * (y - mY) , CI[0,1] * (x - mX) + CI[1,1] * (y - mY)) ,其中CI是协方差矩阵的逆矩阵,在等式中显示为 , which is a 2x2 matrix, like ,这是一个 2x2 矩阵,如 is.是。
Then, the current result, which is a 2D row vector, is multiplied (inner product) by the column vector然后,当前结果,即二维行向量,乘以列向量(内积) , which finally gives us the scalar : ,这最终给了我们标量:
CI[0,0](x - mX)^2 + (CI[1,0] + CI[0,1])(y - mY)(x - mX) + CI[1,1](y - mY)^2 CI[0,0](x - mX)^2 + (CI[1,0] + CI[0,1])(y - mY)(x - mX) + CI[1,1](y - mY )^2
This is going to be easier to implement this expression using NumPy, in comparison to与使用 NumPy 相比,使用 NumPy 实现这个表达式会更容易 , even though they have the same value. ,即使它们具有相同的值。
>>> m = np.array([[0.2],[0.6]]) # defining the mean of the Gaussian (mX = 0.2, mY=0.6)
>>> cov = np.array([[0.7, 0.4], [0.4, 0.25]]) # defining the covariance matrix
>>> cov_inv = np.linalg.inv(cov) # inverse of covariance matrix
>>> cov_det = np.linalg.det(cov) # determinant of covariance matrix
# Plotting
>>> x = np.linspace(-2, 2)
>>> y = np.linspace(-2, 2)
>>> X,Y = np.meshgrid(x,y)
>>> coe = 1.0 / ((2 * np.pi)**2 * cov_det)**0.5
>>> Z = coe * np.e ** (-0.5 * (cov_inv[0,0]*(X-m[0])**2 + (cov_inv[0,1] + cov_inv[1,0])*(X-m[0])*(Y-m[1]) + cov_inv[1,1]*(Y-m[1])**2))
>>> plt.contour(X,Y,Z)
<matplotlib.contour.QuadContourSet object at 0x00000252C55773C8>
>>> plt.show()
The result:结果:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.