在多维环中均匀采样而不会被拒绝 [英] Sample uniformly in a multidimensional ring without rejection

查看:212
本文介绍了在多维环中均匀采样而不会被拒绝的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题中的算法告诉我们如何有效地从多维球中抽样。有没有一种方法可以有效地从多维环中进行抽样,即有 r1



我希望那个缩放函数
r *(gammainc(s2 / 2,n / 2)。^(1 / n))./ sqrt(s2)是可能的。 (Mediocrity免责声明:还没有计算出原始缩放函数的代数/几何)。

原始matlab代码copypasted:

 函数X = randsphere(m,n,r)

%这个函数返回一个m乘n的数组X,其中
%中的每一行具有n个笛卡尔坐标
%均匀分布在具有
%radius r的n维超球体的
%内部的随机点,并且居中起源。函数
%'randn'最初用于生成m组具有独立多元
%正态分布的n
%随机变量,均值为0,方差为1.
%Then不完全伽马函数'gammainc',
%被用于径向映射这些点,以适应具有统一的%空间分布的有限半径r的
%超球面。
%Roger Stafford - 12/23/05

X = randn(m,n);
s2 = sum(X. ^ 2,2);
X = X. * repmat(r *(gammainc(s2 / 2,n / 2)。^(1 / n))./ sqrt(s2),1,n)。

来自 Daniel's answer

  import numpy as np 
from scipy.special import gammainc
from matplotlib import pyplot as plt
def sample(center,radius,n_per_sphere):
r = radius
ndim = center.size
x = np.random.normal(大小=(n_per_sphere,ndim))
ssq = np.sum(x ** 2,axis = 1)
fr = r * gammainc(ndim / 2,ssq / 2)**(1 / ndim)/np.sqrt(ssq)
frtiled = np.tile(fr.reshape(n_per_sphere,1),(1,ndim))
p = center + np.multiply(x,frtiled)
返回p

fig1 = plt.figure(1)
ax1 = fig1.gca()
center = np.array([0,0])
$ radius = 1
p = sample(center,radius,10000)
ax1.scatter(p [:,0],p [:,1],s = 0.5)
ax1。 add_artist(plt.Circle(center,radius,fill = False,color ='0.5'))
ax1.set_xlim(-1.5,1.5)
ax1.set_ylim(-1.5,1.5)
ax1.set_aspect('equal')


解决方案

最后一种方法这里 (1)适用于任何维度球体:

指向一个球体:

- 生成N个高斯随机变量 x1,x2..xN

- 得到x的范数[ i]
$ pre $ L $ S $ S $ = x1 / L
ux2 = x2 / L
...

然后向量ux [i]的分布在曲面上是均匀的S >
- 在范围内生成均匀随机数

R_NPow = RandomUniform(R_Inner N

sup> ,R_Outer N



并得到半径(如 $ b $ R = R_NPow 1 / N

然后计算结果点坐标:

  res_x1 = R * ux1 
res_x2 = R * ux2
...
res_xn = R * uxn

(1)Muller,ME关于在点上均匀生成点的方法的注意点。通讯。协会。 COMPUT。马赫。 2,19-20,1959年4月。

The algorithm in this question tells us how to efficiently sample from a multidimensional ball. Is there a way to similarly efficiently sample from a multidimensional ring , i.e. have r1<r<r2

I hope that a not too complex modification of that scaling function r*(gammainc(s2/2,n/2).^(1/n))./sqrt(s2) is possible. (Mediocrity disclaimer: haven't even figured the algebra/geometry for the original scaling function yet).

Original matlab code copypasted:

function X = randsphere(m,n,r)

% This function returns an m by n array, X, in which 
% each of the m rows has the n Cartesian coordinates 
% of a random point uniformly-distributed over the 
% interior of an n-dimensional hypersphere with 
% radius r and center at the origin.  The function 
% 'randn' is initially used to generate m sets of n 
% random variables with independent multivariate 
% normal distribution, with mean 0 and variance 1.
% Then the incomplete gamma function, 'gammainc', 
% is used to map these points radially to fit in the 
% hypersphere of finite radius r with a uniform % spatial distribution.
% Roger Stafford - 12/23/05

X = randn(m,n);
s2 = sum(X.^2,2);
X = X.*repmat(r*(gammainc(s2/2,n/2).^(1/n))./sqrt(s2),1,n);

Equivalent python code with demo from Daniel's answer:

import numpy as np
from scipy.special import gammainc
from matplotlib import pyplot as plt
def sample(center,radius,n_per_sphere):
    r = radius
    ndim = center.size
    x = np.random.normal(size=(n_per_sphere, ndim))
    ssq = np.sum(x**2,axis=1)
    fr = r*gammainc(ndim/2,ssq/2)**(1/ndim)/np.sqrt(ssq)
    frtiled = np.tile(fr.reshape(n_per_sphere,1),(1,ndim))
    p = center + np.multiply(x,frtiled)
    return p

fig1 = plt.figure(1)
ax1 = fig1.gca()
center = np.array([0,0])
radius = 1
p = sample(center,radius,10000)
ax1.scatter(p[:,0],p[:,1],s=0.5)
ax1.add_artist(plt.Circle(center,radius,fill=False,color='0.5'))
ax1.set_xlim(-1.5,1.5)
ax1.set_ylim(-1.5,1.5)
ax1.set_aspect('equal')

解决方案

The last method here(1) is suitable for any dimensional sphere:

To pick a random point on a sphere:
- generate N Gaussian random variables x1,x2..xN
- get norm of x[i]

 L = Sqrt(x1*x1 + x2*x2 + .. + xn*xn)
 ux1 = x1 / L
 ux2 = x2 / L
 ...

Then the distribution of the vectors ux[i] is uniform over the surface SN-1

To provide uniform distribution in the ring:
- generate uniform random in range

R_NPow = RandomUniform(R_InnerN, R_OuterN)

and get radius (like this 2D case)

R = R_NPow1/N

then calculate resulting point coordinates:

res_x1 = R * ux1
res_x2 = R * ux2
...
res_xn = R * uxn

(1) Muller, M. E. "A Note on a Method for Generating Points Uniformly on -Dimensional Spheres." Comm. Assoc. Comput. Mach. 2, 19-20, Apr. 1959.

这篇关于在多维环中均匀采样而不会被拒绝的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆