python中均匀随机变量和的概率密度估计
我有两个随机变量X和Y,它们均匀分布在单纯形上: 我想计算它们总和的密度: 在计算上述积分后,我的最终目标是计算以下积分: 为了计算第一个积分,我在单纯形中生成均匀分布的点,然后检查它们是否属于上述积分中的所需区域,并取点的分数来计算上述密度 一旦我计算了上面的密度,我就按照一个类似的程序来计算上面的对数积分来计算它的值。然而,这是非常低效的,需要很多时间,比如3-4个小时。有人能给我推荐一种用Python解决这个问题的有效方法吗?我正在使用Numpy软件包 这是密码python中均匀随机变量和的概率密度估计,python,numpy,statistics,distribution,montecarlo,Python,Numpy,Statistics,Distribution,Montecarlo,我有两个随机变量X和Y,它们均匀分布在单纯形上: 我想计算它们总和的密度: 在计算上述积分后,我的最终目标是计算以下积分: 为了计算第一个积分,我在单纯形中生成均匀分布的点,然后检查它们是否属于上述积分中的所需区域,并取点的分数来计算上述密度 一旦我计算了上面的密度,我就按照一个类似的程序来计算上面的对数积分来计算它的值。然而,这是非常低效的,需要很多时间,比如3-4个小时。有人能给我推荐一种用Python解决这个问题的有效方法吗?我正在使用Numpy软件包 这是密码 import nump
import numpy as np
import math
import random
import numpy.random as nprnd
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
#This function checks if the point x lies the simplex and the negative simplex shifted by z
def InreqSumSimplex(x,z):
dim=len(x)
testShiftSimpl= all(z[i]-1 <= x[i] <= z[i] for i in range(0,dim)) and (sum(x) >= sum(z)-1)
return int(testShiftSimpl)
def InreqDiffSimplex(x,z):
dim=len(x)
testShiftSimpl= all(z[i] <= x[i] <= z[i]+1 for i in range(0,dim)) and (sum(x) <= sum(z)+1)
return int(testShiftSimpl)
#This is for the density X+Y
def DensityEvalSum(z,UniformCube):
dim=len(z)
Sum=0
for gen in UniformCube:
Exponential=[-math.log(i) for i in gen] #This is exponentially distributed
x=[i/sum(Exponential) for i in Exponential[0:dim]] #x is now uniformly distributed on simplex
Sum+=InreqSumSimplex(x,z)
Sum=Sum/numsample
FunVal=(math.factorial(dim))*Sum;
if FunVal<0.00001:
return 0.0
else:
return -math.log(FunVal)
#This is for the density X-Y
def DensityEvalDiff(z,UniformCube):
dim=len(z)
Sum=0
for gen in UniformCube:
Exponential=[-math.log(i) for i in gen]
x=[i/sum(Exponential) for i in Exponential[0:dim]]
Sum+=InreqDiffSimplex(x,z)
Sum=Sum/numsample
FunVal=(math.factorial(dim))*Sum;
if FunVal<0.00001:
return 0.0
else:
return -math.log(FunVal)
def EntropyRatio(dim):
UniformCube1=np.random.random((numsample,dim+1));
UniformCube2=np.random.random((numsample,dim+1))
IntegralSum=0; IntegralDiff=0
for gen1,gen2 in zip(UniformCube1,UniformCube2):
Expo1=[-math.log(i) for i in gen1]; Expo2=[-math.log(i) for i in gen2]
Sumz=[ (i/sum(Expo1)) + j/sum(Expo2) for i,j in zip(Expo1[0:dim],Expo2[0:dim])] #Sumz is now disbtributed as X+Y
Diffz=[ (i/sum(Expo1)) - j/sum(Expo2) for i,j in zip(Expo1[0:dim],Expo2[0:dim])] #Diffz is now distributed as X-Y
UniformCube=np.random.random((numsample,dim+1))
IntegralSum+=DensityEvalSum(Sumz,UniformCube) ; IntegralDiff+=DensityEvalDiff(Diffz,UniformCube)
IntegralSum= IntegralSum/numsample; IntegralDiff=IntegralDiff/numsample
return ( (IntegralDiff +math.log(math.factorial(dim)))/ ((IntegralSum +math.log(math.factorial(dim)))) )
Maxdim=11
dimlist=range(2,Maxdim)
Ratio=len(dimlist)*[0]
numsample=10000
for i in range(len(dimlist)):
Ratio[i]=EntropyRatio(dimlist[i])
将numpy导入为np
输入数学
随机输入
将numpy.random作为nprnd导入
将matplotlib.pyplot作为plt导入
从matplotlib.backends.backend\u pdf导入PdfPages
#此函数检查点x是否位于单纯形上,负单纯形是否移动z
单纯形(x,z)中的def:
尺寸=透镜(x)
testShiftSimpl=all(z[i]-1不确定这是否是您问题的答案,但让我们开始吧
首先,这里是一些代码示例,并讨论了如何通过gammavariate()
或通过-log(U)
正确地从Dirichlet(n)(又称单纯形)采样,就像您所做的那样,但对潜在的角点情况有正确的处理
正如我所看到的,您的代码的问题是,比如说,对于采样维度=2
你得到了三个(!)统一的数字,但在对x
进行列表理解时跳过了一个。这是错误的。要对n维Dirichlet进行采样,你应该精确地得到n
U(0,1),然后进行变换(或n
gammavariate的采样)
但是,最好的解决方案可能只是使用numpy.random.dirichlet()
,它是用C编写的,可能是最快的,请参阅
最后一个,依我的拙见,你没有正确估计log(PDF(X+Z))
。好吧,你发现有些是,但是现在PDF(X+Z)
是什么
是这样吗
testShiftSimpl= all(z[i]-1 <= x[i] <= z[i] for i in range(0,dim)) and (sum(x) >= sum(z)-1)
return int(testShiftSimpl)
你能给你看一下当前的代码吗?你对n
的哪种值感兴趣?@MarkDickinson:我实际上对更高的n值感兴趣,比如100200等等。但是我需要绘制从n=2到200的所有值。这就是为什么我想让它更有效率。@MaxNoe:大约有100行python代码。我如何上传代码?Did你分析代码?实际需要多长时间?你可以使用profilehooks
模块来分析。上述条件确保z-x位于单纯形区域,这是我们进行密度评估所需的。因此,我正在计算单纯形中满足上述条件的点的分数,这是pdf的估计值。同样,对于在单纯形中生成点,我并没有像你指出的那样使用Dirichlet分布过程。但我的过程是,如果U1,…,U_n+1以1的速率呈指数分布,那么(U1/U_1+…U_n+1,…,U_n/U_1+…+U_n+1)在单纯形上是一致的。这就是为什么我在理解列表时跳过一个。
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import math
import random
def simplex_sampling(d):
"""
Sample one d-dim point from Dirichet distribution
"""
r = []
sum = 0.0
for k in range(0, d):
x = random.random()
if x == 0.0:
return make_corner_sample(d, k)
t = -math.log(x)
r.append(t)
sum += t
norm = 1.0 / sum
for k in range(0, d):
r[k] *= norm
return r
def make_corner_sample(d, k):
"""
U(0,1) number k is zero, it is a corner point in simplex
"""
r = []
for i in range(0, d):
if i == k:
r.append(1.0)
else:
r.append(0.0)
return r
N = 500 # numer of points to plot
d = 3 # dimension of the space, 2 or 3
x = []
y = []
z = []
for k in range(0, N):
pt = simplex_sampling(d)
x.append(pt[0])
y.append(pt[1])
if d > 2:
z.append(pt[2])
if d == 2:
plt.scatter(x, y, alpha=0.1)
else:
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x, y, z, alpha=0.1)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()