随机模拟的基本思想
假设有一个矩形区域S,其内部有一个不规则区域M,怎样求M的面积?
- 将不规则区域M划分成很多规则的小区域,求所有小区域面积之和;
- 随机的在S内部取点,计算点落在M内部的比例,该比例可近似S和M的面积比。
方法2采用的就是随机模拟的方法解决问题,随机模拟的关键在于如何将实际复杂的问题,转化为抽样可以解决的问题。
采样算法
给定统计样本集,如何估计产生这个样本集的随机变量概率密度函数,是我们比较熟悉的概率密度估计问题。求解概率密度估计问题的常用方法是最大似然估计、最大后验估计等。
但是,我们思考概率密度估计问题的逆问题:给定一个概率分布 ,如何让计算机生成满足这个概率分布的样本,这个问题就是统计模拟中研究的重要问题–采样(Sampling)。
计算机可以直接生成均匀分布的样本,现在已经有很多方法,那么我们的核心问题就是如何利用均匀抽样,借助随机模拟的方法,实现满足特定概率分布 的抽样。
接受-拒绝抽样
对于非均匀分布,我们如果想要生成符合其分布的样本,就需要转换思路,利用均匀抽样和随机模拟来达到目的。
对于上图中的
,是较为复杂的概率密度函数,我们通过以下步骤来获得符合其分布的样本:
- 构造一个比较简单的容易抽样的高斯分布 ,满足 ;
- 对高斯分布进行采样,得到一个 ;
- 在 之间进行均匀采样,得到 ;
- 如果 ,则拒绝该采样作为该分布的一个样本,反之则接受;
- 重复2-4直到接受足够多的样本。
Python代码实现:
def rejection_sampling(iter=1000):
samples = []
for i in range(iter):
z = np.random.normal(50, 30)
u = np.random.uniform(0, k*q(z))
if u <= p(z):
samples.append(z)
return np.array(samples)
这里有两个点需要理解,第一个点是 的采样,我们为什么要找一个和复杂分布类似的简单分布?目的就是在采样 的时候取到复杂分布取值范围内的概率比较大,避免过多的无用计算;第二个点是 的采样,也是为了说明为什么拒绝采样是可行的,当 较低时,决绝的概率较大,反之接受的概率较大,大致是符合 的分布的。
这样,通过简单的高斯分布采样以及计算机可以实现的均匀采样,间接实现了复杂的分布的采样。
但是,这种方法在高维情况小的劣势也很明显,我们很难找到合适的 ,不合适的上界造成的结果就是采样的拒绝率会超高,浪费了大量的计算。
马尔科夫链及其平稳分布
马尔科夫链由一个状态空间下的初始状态概率
,和状态转移矩阵
组成,
表示初始状态是状态
的概率,
表示状态
转换为状态
的概率,根据初始状态概率和状态转移矩阵,我们可以得到一个状态序列
:
即当前状态的取值只与上一个状态有关,而跟之前所有的状态无关。
稳定分布
马尔科夫链的稳定分布说的是:对于遍历的马尔可夫链,当其转移次数足够多时,将会进入稳态分布π(x),即各状态的出现概率趋于稳定。换一种说法就是状态转移矩阵的n次方会收敛。进入稳定状态之后满足:
即每个状态流出的概率等于该状态流入的概率,该方程称为全局平衡方程。
细致平稳条件
对于全局平衡方程,我们再加一个更加严格的限制,使得任一个状态
满足如下条件:
即对于任意一对节点
,
到
的概率等于
到
的概率,上述方程称为细致平衡方程,我们可以很容易证明:如果一个分布满足细致平衡条件,那么它也满足全局平衡条件。
MCMC采样算法
对于给定的复杂分布 ,我们希望有一个更便捷的方式生成符合其分布的样本,由于马尔科夫链在多次迭代之后会收敛到一个稳定的分布,一个自然而然的想法是:我们可以构造一个马尔科夫链,使其最终达到的稳定分布是 ,那么我们从任何一个状态出发,根据状态转移矩阵 进行转移,在得到状态序列 之后,达到了稳定分布 ,那么接下来的 都是符合分布 的样本。
这个想法在1953 年被Metropolis想到的,首次提出了基于马氏链的蒙特卡罗方法,即Metropolis算法,并在最早的计算机上编程实现。 Metropolis 算法是首个普适的采样方法,并启发了一系列MCMC方法。Metropolis 的这篇论文被收录在《统计学中的重大突破》中,Metropolis算法也被遴选为二十世纪的十个最重要的算法之一。
上面我们已经得到结论:马尔科夫链最终收敛的稳定分布依赖于其转移矩阵 ,那么我们应该怎么构造转移矩阵使得其最终的稳定分布是 呢?
这时候就需要用到上面的细致平稳条件: ,当转移矩阵满足细致平稳条件的时候马尔科夫链即达到了平稳分布,但是我们随机构造的转移矩阵很显然不满足这个条件,为了使细致平稳条件成立,我们引入一个 ,我们希望:
那么我们如何给 赋值才能使得上式成立呢,一种简单的想法是令:
于是上式成立了,上式中引入的 称为接受率,可以理解为在原来马尔科夫链转移的基础上,以一定的概率接受或者拒绝这个转移,于是从i到j的转移概率变成了 ,整理上述过程就得到了用于采样概率分布 的算法。
上述过程存在一个小的问题,当 较小的时候可能会导致拒绝大量的采样,这样采样过程中就容易原地踏步,使得马尔科夫链收敛到平稳分布的速度太慢。
假设 ,此时满足细致平稳条件,即:
上式两边同时扩大五倍等式仍然成立,也就是说我们按照比例提高接受率不会打破细致平稳条件,这启发我们可以将细致平稳条件中的 等比例方法,使得两者之中较大的那个放大为1,即:
经过了上面的改造,我们就得到了最常见的Metropolis-Hastings采样算法。
Python代码实现:
def metropolis_hastings(p, iter=1000):
x, y = 0., 0.
samples = np.zeros((iter, 2))
for i in range(iter):
# 这里就相当于利用已有的转移矩阵P获得下一个状态
x_star, y_star = np.array([x, y]) + np.random.normal(size=2)
# 根据一定的概率来决定是否接受上面得到的转移状态
if np.random.rand() < p(x_star, y_star) / p(x, y):
x, y = x_star, y_star
# 不管是不是接受上面的状态都不会舍弃这个样本
# 这也是为什么如果接受率过低,采样会一直原地踏步的原因
# 因为初始化的值是不符合要求的分布的,只有经过一段时间的转移才能慢慢靠近要求的分布
samples[i] = np.array([x, y])
return samples
Gibbs Sampling
对于高维的情形,由于接受率 的存在,MCMC采样算法的效率不高,能否找到一个转移矩阵P使得接受率 呢?
重新定义新的细致平稳条件
细致平稳条件描述如下:
从二维数据分布开始,假设
是一个二维联合数据分布,现在有
,A、B的第一维度的取值是一样的,我们可以很容易得到:
两式的右边相等,因此我们有:
也就是:
观察上式,再观察细致平稳条件,我们发现在 这条直线上,如果用 作为转移规律的话,是满足细致平稳条件的。
有了上面这个结论,我们就可以在对高维数据进行采样的时候,依次对每个维度进行转移、采样了。具体算法如下:
- 初始化状态初始值:
- for t to n:
- 从条件概率分布 中采样得到
- 从条件概率分布 中采样得到
- …
- 从条件概率分布 中采样得到
- finish
Python代码实现:
def p_x_given_y(y, mus, sigmas):
mu = mus[0] + sigmas[1, 0] / sigmas[0, 0] * (y - mus[1])
sigma = sigmas[0, 0] - sigmas[1, 0] / sigmas[1, 1] * sigmas[1, 0]
return np.random.normal(mu, sigma)
def p_y_given_x(x, mus, sigmas):
mu = mus[1] + sigmas[0, 1] / sigmas[1, 1] * (x - mus[0])
sigma = sigmas[1, 1] - sigmas[0, 1] / sigmas[0, 0] * sigmas[0, 1]
return np.random.normal(mu, sigma)
def gibbs_sampling(mus, sigmas, iter=10000):
samples = np.zeros((iter, 2))
y = np.random.rand() * 10
for i in range(iter):
x = p_x_given_y(y, mus, sigmas)
y = p_y_given_x(x, mus, sigmas)
samples[i, :] = [x, y]
return samples