通过采样PDF创建数组

时间:2017-05-31 09:46:07

标签: python numpy

我想用numpy创建一个2D数组,其中(x,y)的每个条目都是0或1,得到1的概率是由PDF定义的,例如2D高斯。

目标是能够添加许多这样的数组,并检索像直方图这样的东西,在那里我可以看到2D高斯峰。

我找到了许多方法来对分布进行采样(读取:返回(x,y)对,其中更接近(mu_x,mu_y)的坐标更有可能),但没有简单的方法来填充数组。在numpy / scipy中是否有任何内置函数来执行此操作,或者我必须手动执行此操作(例如,通过迭代数组,如果f(x,y) > threshold将元素设置为1)?

对于均匀概率分布,我可以这样做:

np.random.randint(2, size=(30,30))

任何以高斯为目的的方法吗?

1 个答案:

答案 0 :(得分:2)

我认为没有内置功能,但正如您已经建议的那样,通过将随机数与阈值进行比较,您可以轻松实现所需的功能。你不应该使用类似for循环的东西进行迭代,因为它们相当慢。我建议使用np.where进行比较。这是一个例子:

首先,我们设置一个网格,计算每个网格点的阈值并绘制结果以供参考:

import numpy as np
import scipy.stats as st
import matplotlib.pyplot as plt

xEdges = np.linspace(0, 10, 31)
yEdges = np.linspace(0, 10, 31)
xMids = (xEdges[:-1]+xEdges[1:])/2.
yMids = (yEdges[:-1]+yEdges[1:])/2.
xMesh, yMesh = np.meshgrid(xMids, yMids)

rv = st.multivariate_normal(mean=[5, 5], cov=[[2,0],[0,2]])
threshold = rv.pdf(np.stack((xMesh, yMesh), axis=2))

plt.axes().set_aspect('equal')
plt.pcolormesh(xMesh, yMesh, threshold)
plt.colorbar()
plt.xlabel("x")
plt.ylabel("y")
plt.show()

输出(具有任意归一化的双变量高斯分布。我真的不明白你想要的规范化与你的例子相比,但因为这只是一个因素,我只是保持原样。):

enter image description here

现在我们可以使用np.where将网格形状的0到1之间均匀分布的随机数阵列与阈值进行比较。满足条件时,结果中的相应条目设置为1,否则设置为0:

hist = np.where(np.random.rand(30, 30)<threshold, 1, 0)
plt.axes().set_aspect('equal')
plt.pcolormesh(xMesh, yMesh, hist)
plt.colorbar()
plt.xlabel("x")
plt.ylabel("y")
plt.show()

现在经过1次尝试后,您无法真正看到它正常工作,但hist包含您想要的内容:

enter image description here

for _ in range(9999):
    hist += np.where(np.random.rand(30, 30)<threshold, 1, 0)
plt.axes().set_aspect('equal')
plt.pcolormesh(xMesh, yMesh, hist/10000.)
plt.colorbar()
plt.xlabel("x")
plt.ylabel("y")
plt.show()

经过10000次尝试后,您已经可以很好地看到分布形成:

enter image description here

for _ in range(90000):
    hist += np.where(np.random.rand(30, 30)<threshold, 1, 0)
plt.axes().set_aspect('equal')
plt.pcolormesh(xMesh, yMesh, hist/100000.)
plt.colorbar()
plt.xlabel("x")
plt.ylabel("y")
plt.show()

平均超过100000次尝试,分布几乎与分析分布函数无法区分:

enter image description here