2017-05-31 76 views
1

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

目标是能够添加许多这样的数组,并检索像直方图,我可以看到二维高斯峰。

我发现了很多方法来对一个分布进行采样(读取:get back(x,y)对,其中更接近(mu_x,mu_y)的坐标更可能),但没有简单的方法来填充数组。在numpy/scipy中是否有内置函数可以做到这一点,或者我必须手动完成它(例如迭代数组,如果f(x,y) > threshold将元素设置为1)?

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

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

任何方式为高斯做到这一点?

回答

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,elseway 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