实现的方法可以不止一种:
- rejection sampling
- invert the cdf
- Metropolis Algorithm (MCMC)
本篇介绍根据累积概率分布函数的逆函数(2:invert the CDF)生成的方法。
原参考网站:https://blog.demofox.org/2017/08/05/generating-random-numbers-from-a-specific-distribution-by-inverting-the-cdf/
自己的理解不一定正确,有错误望指正。
目标:
已知 y=pdf(x),现想由给定的pdf, 生成对应分布的x
PDF是概率分布函数,对其积分或者求和可以得到CDF(累积概率分布函数),PDF积分或求和的结果始终为1
步骤(具体解释后面会说):
1、根据pdf得到cdf
2、由cdf得到inverse of the cdf
3、对于给定的均匀分布[0,1),带入inverse cdf,得到的结果即是我们需要的x
求cdf逆函数的具体方法:
对于上面的第二步,可以分成两类:
1、当CDF的逆函数好求时,直接根据公式求取,
2、反之当CDF的逆函数不好求时,用数值模拟方法
自己的理解:为什么需要根据cdf的逆去获得x?
原因一:
因为cdf是单调函数因此一定存在逆函数(cdf是s型函数,而pdf则不一定,例如正态分布,不单调,对于给定的y,可能存在两个对应的x,就不可逆)
原因二:
这仅是我自己的直观理解,根据下图所示(左上为pdf,右上为cdf)
由步骤3可知,我们首先生成[0,1)的均匀随机数,此随机数作为cdf的y,去映射到cdf的x(若用cdf的逆函数表示则是由x映射到y),可以参考上图的右上,既然cdf的y是均匀随机的,那么对于cdf中同样范围的x,斜率大的部分将会有更大的机会被映射,因为对应的y范围更大(而y是随即均匀分布的),那么,cdf的斜率也就等同于pdf的值,这正好符合若x的pdf较大,那么有更大的概率出现(即重复很多次后,该x会出现的次数最多)
代码实现——方法一,公式法
import numpy as np
import math
import random
import matplotlib.pyplot as plt
import collections
count_dict = dict()
bin_count = 20
def inverseCDF():
"""
return the x value in PDF
"""
uniform_random = random.random()
return inverse_cdf(uniform_random)
def pdf(x):
return 2 * x
# cdf = x^2, 其逆函数很好求,因此直接用公式法
def inverse_cdf(x):
return math.sqrt(x)
def draw_pdf(D):
global bin_count
D = collections.OrderedDict(sorted(D.items()))
plt.bar(range(len(D)), list