如何生成服从指定概率密度函数f(x)的随机数?
生成符合自定义概率密度函数f(x)的随机数
你的尝试问题分析
你写的拒绝采样逻辑有两个核心问题:
- 判断条件完全搞反了:正确的逻辑应该是当随机生成的阈值小于等于f(a)时接受a,而不是大于;
- 没有处理f(x)取值超过1的情况:当f(a)>1时,b∈[0,1]永远小于f(a),按你的逻辑会直接拒绝a,但实际上这些点是目标分布中概率更高的区域,应该更容易被接受才对。
方法1:修正后的拒绝采样法(通用,无需求积分)
这是最常用的通用方法,只要能找到f(x)的上界就可以用:
- 确定常数M:找到一个正数M,使得在目标随机数的取值区间内,所有x都满足
f(x) ≤ M(因为f是归一化的概率密度,这个M一定存在,比如取f(x)的最大值)。 - 循环采样:
- 生成取值区间内的均匀随机数
a(比如取值区间是[L,R],就生成a ~ Uniform(L,R)); - 生成[0, M]范围内的均匀随机数
b(等价于生成u ~ Uniform(0,1),计算b = u * M); - 如果
b ≤ f(a),直接返回a;否则重复上述步骤。
- 生成取值区间内的均匀随机数
举个简单例子:假设f(x)=3x²,x∈[0,1](积分是1),f(x)的最大值M=3。采样时:
- 生成
a∈[0,1],u∈[0,1],计算b=3u; - 如果
3u ≤ 3a²→u ≤ a²,就接受a,否则重新采样。
方法2:逆变换采样法(效率更高,需可求CDF逆函数)
如果f(x)的累积分布函数(CDF)可以解析求解,并且其逆函数存在,这个方法效率比拒绝采样高:
- 计算累积分布函数F(x):F(x)是f(x)的积分,即
F(x) = ∫_{x_min}^x f(t)dt(x_min是取值区间左端点),题目中已说明取值范围内积分是1,所以F(x_max)=1。 - 求F(x)的逆函数F⁻¹:找到函数
x=F⁻¹(u),满足F(x)=u。 - 采样生成:生成
u ~ Uniform(0,1),返回F⁻¹(u)即可。
例子:还是f(x)=3x²,x∈[0,1],CDF是F(x)=x³,逆函数是F⁻¹(u)=u^(1/3)。生成u∈[0,1],返回u的三次方根,就符合f(x)的分布。
内容的提问来源于stack exchange,提问作者JavaGamesJAR
相关产品推荐
相关产品推荐

