如何在pytorch中创建一个正常的二维分布
How to create a normal 2d distribution in pytorch
给定一个包含 N 个点的张量,用 [x,y] 表示,我想围绕每个点创建一个二维高斯分布,将它们绘制在一个空的特征图上。
例如,左图显示了一个给定的点(在特征图上注册为一个像素,其值设置为1)。右图在其周围添加了 2D 高斯分布。
如何为每个点添加这样的分布? pytorch 中有 API 吗?
从多元正态分布中抽样
您可以使用 MultivariateNormal
从多元正态样本中抽样。
>>> h, w = 200, 200
>>> fmap = torch.zeros(h, w)
用原点填充fmap
:
>>> pts = torch.rand(20, 2)
>>> pts *= torch.tensor([h, w])
>>> x, y = pts.T.long()
>>> x, y = x.clip(0, h), y.clip(0, w)
>>> fmap[x, y] = 1
在此之后,我们可以从以下分布中采样(您可以相应地调整协方差矩阵):
>>> sampler = MultivariateNormal(pts.T, 10*torch.eye(len(pts)))
>>> for x in range(10):
... x, y = sampler.sample()
... x, y = x.clip(0, h).long(), y.clip(0, w).long()
... fmap[x, y] = 1
因此,您可能会得到如下结果:
Origin points
Normal sampling
这没有很好地记录,但您可以将样本形状传递给 sample
函数。这允许您在每次调用中采样多个点,即您只需要一个来填充您的canvas。
这是一个从MultivariateNormal
:
中提取的函数
def multivariate_normal_sampler(mean, cov, k):
sampler = MultivariateNormal(mean, cov)
return sampler.sample((k,)).swapaxes(0,1).flatten(1)
那么你可以这样称呼它:
>>> x, y = multivariate_normal_sampler(mean=pts.T, cov=50*torch.eye(len(pts)), k=1000)
剪辑示例:
>>> x, y = x.clip(0, h-1).long(), y.clip(0, w-1).long()
最后插入fmap并绘制:
>>> fmap[x, y] += .1
这是一个示例预览:
k=1,000
k=50,000
效用函数可用 torch.distributions.multivariate_normal.MultivariateNormal
使用 pdf
计算密度图
或者,您可以根据概率密度函数 (pdf) 计算密度值,而不是从正态分布中抽样:
A particular example of a two-dimensional Gaussian function is:
原点:
>>> h, w = 50, 50
>>> x0, y0 = torch.rand(2, 20)
>>> origins = torch.stack((x0*h, y0*w)).T
定义 gaussian 2D pdf:
def gaussian_2d(x=0, y=0, mx=0, my=0, sx=1, sy=1):
return 1 / (2*math.pi*sx*sy) * \
torch.exp(-((x - mx)**2 / (2*sx**2) + (y - my)**2 / (2*sy**2)))
构造网格并从每个原点累积高斯:
x = torch.linspace(0, h, h)
y = torch.linspace(0, w, w)
x, y = torch.meshgrid(x, y)
z = torch.zeros(h, w)
for x0, y0 in origins:
z += gaussian_2d(x, y, mx=x0, my=y0, sx=h/10, sy=w/10)
Multivariate normal distributions
绘制值网格的代码只是使用 matplotlib.pyplot.pcolormesh
:plt.pcolormesh(x, y, z)
.
给定一个包含 N 个点的张量,用 [x,y] 表示,我想围绕每个点创建一个二维高斯分布,将它们绘制在一个空的特征图上。
例如,左图显示了一个给定的点(在特征图上注册为一个像素,其值设置为1)。右图在其周围添加了 2D 高斯分布。
如何为每个点添加这样的分布? pytorch 中有 API 吗?
从多元正态分布中抽样
您可以使用 MultivariateNormal
从多元正态样本中抽样。
>>> h, w = 200, 200
>>> fmap = torch.zeros(h, w)
用原点填充fmap
:
>>> pts = torch.rand(20, 2)
>>> pts *= torch.tensor([h, w])
>>> x, y = pts.T.long()
>>> x, y = x.clip(0, h), y.clip(0, w)
>>> fmap[x, y] = 1
在此之后,我们可以从以下分布中采样(您可以相应地调整协方差矩阵):
>>> sampler = MultivariateNormal(pts.T, 10*torch.eye(len(pts)))
>>> for x in range(10):
... x, y = sampler.sample()
... x, y = x.clip(0, h).long(), y.clip(0, w).long()
... fmap[x, y] = 1
因此,您可能会得到如下结果:
Origin points | Normal sampling |
---|---|
这没有很好地记录,但您可以将样本形状传递给 sample
函数。这允许您在每次调用中采样多个点,即您只需要一个来填充您的canvas。
这是一个从MultivariateNormal
:
def multivariate_normal_sampler(mean, cov, k):
sampler = MultivariateNormal(mean, cov)
return sampler.sample((k,)).swapaxes(0,1).flatten(1)
那么你可以这样称呼它:
>>> x, y = multivariate_normal_sampler(mean=pts.T, cov=50*torch.eye(len(pts)), k=1000)
剪辑示例:
>>> x, y = x.clip(0, h-1).long(), y.clip(0, w-1).long()
最后插入fmap并绘制:
>>> fmap[x, y] += .1
这是一个示例预览:
k=1,000 |
k=50,000 |
---|---|
效用函数可用 torch.distributions.multivariate_normal.MultivariateNormal
使用 pdf
计算密度图或者,您可以根据概率密度函数 (pdf) 计算密度值,而不是从正态分布中抽样:
A particular example of a two-dimensional Gaussian function is:
原点:
>>> h, w = 50, 50
>>> x0, y0 = torch.rand(2, 20)
>>> origins = torch.stack((x0*h, y0*w)).T
定义 gaussian 2D pdf:
def gaussian_2d(x=0, y=0, mx=0, my=0, sx=1, sy=1):
return 1 / (2*math.pi*sx*sy) * \
torch.exp(-((x - mx)**2 / (2*sx**2) + (y - my)**2 / (2*sy**2)))
构造网格并从每个原点累积高斯:
x = torch.linspace(0, h, h)
y = torch.linspace(0, w, w)
x, y = torch.meshgrid(x, y)
z = torch.zeros(h, w)
for x0, y0 in origins:
z += gaussian_2d(x, y, mx=x0, my=y0, sx=h/10, sy=w/10)
Multivariate normal distributions |
---|
绘制值网格的代码只是使用 matplotlib.pyplot.pcolormesh
:plt.pcolormesh(x, y, z)
.