Social LSTM论文中有一张展示行人运动轨迹概率分布的效果图,今天抽空研究下如何用Python可视化二维高斯分布(Gauss Distribution)。
可视化二维高斯分布(Gauss Distribution)本质上是以2D方式展示3D数据(第三维是概率密度),Python中四个matplotlib函数(plt.contour()、plt.contourf()、plt.imshow()、plt.pcolormesh())可以帮助我们完成这一目标。
先引入必要的python依赖文件。
%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use('seaborn-white')
import numpy as np
目标函数将平面坐标(x,y)映射为z值输出。
def f(x, y):
return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
plt.contour()函数有三个参数:grid of x values, grid of y values 和 grid of z values, 其中,x和y表示在plot上的位置,z表示Contour Levels。一般使用np.meshgrid()函数生成x,y数据。
x = np.linspace(0, 5, 50)
y = np.linspace(0, 5, 40)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
绘制Contour数据:
plt.contour(X, Y, Z, colors='black');
当使用Single Color绘制Contour时,虚线表示Z为负数;还可以为不同的Line指定不同的颜色。
plt.contour(X, Y, Z, 20, cmap='RdGy');
plt.contourf(X, Y, Z, 20, cmap='RdGy')
plt.colorbar();
有时候按照不同的颜色展示Contour是不够的,plt.contourf()函数可以为Contour填充颜色。
plt.contourf(X, Y, Z, 20, cmap='RdGy')
plt.colorbar();
图中黑色区域是"Peaks",红色区域是“Valleys”。
有时我们需要平滑的过渡效果,plt.imshow()函数可以将二维网格数据插值为平滑的图像。
plt.imshow(Z, extent=[0, 5, 0, 5], origin='lower',
cmap='RdGy')
plt.colorbar()
plt.axis(aspect='image');
plt.imshow()函数不接受Grid X和Grid Y参数,所以必须通过extend=[xmin, xmax, ymin, ymax]指定image的大小;
plt.imshow()缺省的Origin在左上角,所以需要通过指定Origin="lower"将图像原点设置到左下角。
plt.imshow()会自动调整axis aspect ratio来适配输入数据,所以需要指定aspect='image'使得x和y的Unit匹配。
除了plt.imshow()函数,plt.pcolormesh()函数也可以用来绘制平滑的图像效果。
plt.pcolormesh(X, Y, Z, cmap='RdBu')
plt.colorbar()
有时需要同时展示Contour和Filled Contour。
contours = plt.contour(X, Y, Z, 3, colors='black')
plt.clabel(contours, inline=True, fontsize=8)
plt.imshow(Z, extent=[0, 5, 0, 5], origin='lower',
cmap='RdGy', alpha=0.5)
plt.colorbar();
contours = plt.contour(X, Y, Z, 3, colors='black')
plt.clabel(contours, inline=True, fontsize=8)
plt.pcolormesh(X, Y, Z, cmap='RdBu')
plt.colorbar()
把上例中的f(x, y)替换为Guass Distribution(x,y),就可以绘制二维高斯分布的效果了。这里展示了多个高斯分布的叠加效果,当我们预测了行人位置的高斯分布之后,就可以用类似的方法可视化网络的训练效果了。
from scipy.stats import multivariate_normal
def gauss_fun(X, Y):
mux = [2.0, 2.5, 3.0, 3.5, 4.0, 4.5]
muy = [1.2, 1.7, 2.2, 2.7, 3.2, 3.7]
sx = [0.5, 0.6, 0.65, 0.55, 0.7, 0.8]
sy = [1.0, 1.2, 1.2, 1.15, 0.9, 0.8]
rho = [0.1, 0.2, 0.2, 0.19, 0.2, 0.2]
d = np.dstack([X, Y])
z = None
for i in range(len(mux)):
mean = [mux[i], muy[i]]
# Extract covariance matrix
cov = [[sx[i] * sx[i], rho[i] * sx[i] * sy[i]], [rho[i] * sx[i] * sy[i], sy[i] * sy[i]]]
gaussian = multivariate_normal(mean = mean, cov = cov)
z_ret = gaussian.pdf(d)
if z is None:
z = z_ret
else:
z += z_ret
return z
其余的步骤与前面的例子相同,得到如下的效果: