MCMC蒙特卡罗方法

MCMC(一)蒙特卡罗方法

作为一种随机采样方法,马尔科夫链蒙特卡罗(Markov Chain Monte Carlo,以下简称MCMC)在机器学习,深度学习以及自然语言处理等领域都有广泛的应用,是很多复杂算法求解的基础。比如我们前面讲到的分解机(Factorization Machines)推荐算法,还有前面讲到的受限玻尔兹曼机(RBM)原理总结,都用到了MCMC来做一些复杂运算的近似求解。下面我们就对MCMC的原理做一个总结。

1.1 MCMC概述

从名字我们可以看出,MCMC由两个MC组成,即蒙特卡罗方法(Monte Carlo Simulation,简称MC)和马尔科夫链(Markov Chain ,也简称MC)。要弄懂MCMC的原理我们首先得搞清楚蒙特卡罗方法和马尔科夫链的原理。我们将用三篇来完整学习MCMC。在本篇,我们关注于蒙特卡罗方法。

1.2 蒙特卡罗方法引入

在这里插入图片描述
在这里插入图片描述

1.3 概率分布采样

上一节我们讲到蒙特卡罗方法的关键是得到x的概率分布。如果求出了x的概率分布,我们可以基于概率分布去采样基于这个概率分布的n个x的样本集,带入蒙特卡罗求和的式子即可求解。但是还有一个关键的问题需要解决,即如何基于概率分布去采样基于这个概率分布的n个x的样本集。

在这里插入图片描述

其他一些常见的连续分布,比如t分布,F分布,Beta分布,Gamma分布等,都可以通过类似的方式从uniform(0,1)得到的采样样本转化得到。在python的numpy,scikit-learn等类库中,都有生成这些常用分布样本的函数可以使用。

不过很多时候,我们的x的概率分布不是常见的分布,这意味着我们没法方便的得到这些非常见的概率分布的样本集。那这个问题怎么解决呢?

1.4 接受-拒绝采样

对于概率分布不是常见的分布,一个可行的办法是采用接受-拒绝采样来得到该分布的样本。既然 p(x) 太复杂在程序中没法直接采样,那么我设定一个程序可采样的分布 q(x) 比如高斯分布,然后按照一定的方法拒绝某些样本,以达到接近 p(x) 分布的目的,其中q(x)叫做 proposal distribution。
在这里插入图片描述
在这里插入图片描述

整个过程中,我们通过一系列的接受拒绝决策来达到用q(x)模拟p(x)概率分布的目的。

1.5 蒙特卡罗方法小结

使用接受-拒绝采样,我们可以解决一些概率分布不是常见的分布的时候,得到其采样集并用蒙特卡罗方法求和的目的。但是接受-拒绝采样也只能部分满足我们的需求,在很多时候我们还是很难得到我们的概率分布的样本集。比如:

1)对于一些二维分布p(x,y),有时候我们只能得到条件分布p(x|y)和p(y|x)和,却很难得到二维分布p(x,y)一般形式,这时我们无法用接受-拒绝采样得到其样本集。

2)对于一些高维的复杂非常见分布p(x1,x2,…,xn),我们要找到一个合适的q(x)和k
非常困难。

从上面可以看出,要想将蒙特卡罗方法作为一个通用的采样模拟求和的方法,必须解决如何方便得到各种复杂概率分布的对应的采样样本集的问题。而我们下一篇要讲到的马尔科夫链就是帮助找到这些复杂概率分布的对应的采样样本集的白衣骑士。下一篇我们来总结马尔科夫链的原理。

MCMC(二)马尔科夫链

在MCMC(一)蒙特卡罗方法中,我们讲到了如何用蒙特卡罗方法来随机模拟求解一些复杂的连续积分或者离散求和的方法,但是这个方法需要得到对应的概率分布的样本集,而想得到这样的样本集很困难。因此我们需要本篇讲到的马尔科夫链来帮忙。

2.1 马尔科夫链概述

马尔科夫链定义本身比较简单,它假设某一时刻状态转移的概率只依赖于它的前一个状态。举个形象的比喻,假如每天的天气是一个状态的话,那个今天是不是晴天只依赖于昨天的天气,而和前天的天气没有任何关系。当然这么说可能有些武断,但是这样做可以大大简化模型的复杂度,因此马尔科夫链在很多时间序列模型中得到广泛的应用,比如循环神经网络RNN,隐式马尔科夫模型HMM等,当然MCMC也需要它。
在这里插入图片描述
讲了这么多,那么马尔科夫链模型的状态转移矩阵和我们蒙特卡罗方法需要的概率分布样本集有什么关系呢?这需要从马尔科夫链模型的状态转移矩阵的性质讲起。

2.2 马尔科夫链模型状态转移矩阵的性质

得到了马尔科夫链模型的状态转移矩阵,我们来看看马尔科夫链模型的状态转移矩阵的性质。

完整代码参见github: https://github.com/ljpzzz/machinelearning/blob/master/mathematics/mcmc_2.ipynb

仍然以上面的这个状态转移矩阵为例。假设我们当前股市的概率分布为:[0.3,0.4,0.3],即30%概率的牛市,40%概率的熊盘与30%的横盘。然后这个状态作为序列概率分布的初始状态t0,将其带入这个状态转移矩阵计算t1,t2,t3…的状态。代码如下:

import numpy as np
matrix = np.matrix([[0.9,0.075,0.025],[0.15,0.8,0.05],[0.25,0.25,0.5]], dtype=float)
vector1 = np.matrix([[0.3,0.4,0.3]], dtype=float)
for i in range(100):
    vector1 = vector1*matrix
    print "Current round:" , i+1
    print vector1

部分输出结果如下:

Current round: 1
[[ 0.405   0.4175  0.1775]]
Current round: 2
[[ 0.4715   0.40875  0.11975]]
Current round: 3
[[ 0.5156  0.3923  0.0921]]
Current round: 4
[[ 0.54591   0.375535  0.078555]]
。。。。。。
Current round: 58
[[ 0.62499999  0.31250001  0.0625    ]]
Current round: 59
[[ 0.62499999  0.3125      0.0625    ]]
Current round: 60
[[ 0.625   0.3125  0.0625]]
。。。。。。
Current round: 99
[[ 0.625   0.3125  0.0625]]
Current round: 100
[[ 0.625   0.3125  0.0625]]

可以发现,从第60轮开始,我们的状态概率分布就不变了,一直保持在[0.625 0.3125 0.0625],即62.5%的牛市,31.25%的熊市与6.25%的横盘。那么这个是巧合吗?

我们现在换一个初始概率分布试一试,现在我们用[0.7,0.1,0.2]作为初始概率分布,然后这个状态作为序列概率分布的初始状态t0,将其带入这个状态转移矩阵计算t1,t2,t3…的状态。代码如下:

matrix = np.matrix([[0.9,0.075,0.025],[0.15,0.8,0.05],[0.25,0.25,0.5]], dtype=float)
vector1 = np.matrix([[0.7,0.1,0.2]], dtype=float)
for i in range(100):
    vector1 = vector1*matrix
    print "Current round:" , i+1
    print vector1

部分输出结果如下:

Current round: 1
[[ 0.695   0.1825  0.1225]]
Current round: 2
[[ 0.6835   0.22875  0.08775]]
Current round: 3
[[ 0.6714  0.2562  0.0724]]
Current round: 4
[[ 0.66079   0.273415  0.065795]]
。。。。。。。
Current round: 55
[[ 0.62500001  0.31249999  0.0625    ]]
Current round: 56
[[ 0.62500001  0.31249999  0.0625    ]]
Current round: 57
[[ 0.625   0.3125  0.0625]]
。。。。。。。
Current round: 99
[[ 0.625   0.3125  0.0625]]
Current round: 100
[[ 0.625   0.3125  0.0625]]

可以看出,尽管这次我们采用了不同初始概率分布,最终状态的概率分布趋于同一个稳定的概率分布[0.625 0.3125 0.0625], 也就是说我们的马尔科夫链模型的状态转移矩阵收敛到的稳定概率分布与我们的初始状态概率分布无关。这是一个非常好的性质,也就是说,如果我们得到了这个稳定概率分布对应的马尔科夫链模型的状态转移矩阵,则我们可以用任意的概率分布样本开始,带入马尔科夫链模型的状态转移矩阵,这样经过一些序列的转换,最终就可以得到符合对应稳定概率分布的样本。

这个性质不光对我们上面的状态转移矩阵有效,对于绝大多数的其他的马尔科夫链模型的状态转移矩阵也有效。同时不光是离散状态,连续状态时也成立。

同时,对于一个确定的状态转移矩阵P,它的n次幂 P n P^n Pn在当n大于一定的值的时候也可以发现是确定的,我们还是以上面的例子为例,计算代码如下:

matrix = np.matrix([[0.9,0.075,0.025],[0.15,0.8,0.05],[0.25,0.25,0.5]], dtype=float)
for i in range(10):
    matrix = matrix*matrix
    print "Current round:" , i+1
    print matrix

输出结果如下:

Current round: 1
[[ 0.8275   0.13375  0.03875]
 [ 0.2675   0.66375  0.06875]
 [ 0.3875   0.34375  0.26875]]
Current round: 2
[[ 0.73555   0.212775  0.051675]
 [ 0.42555   0.499975  0.074475]
 [ 0.51675   0.372375  0.110875]]
。。。。。。
Current round: 5
[[ 0.62502532  0.31247685  0.06249783]
 [ 0.6249537   0.31254233  0.06250397]
 [ 0.62497828  0.31251986  0.06250186]]
Current round: 6
[[ 0.625   0.3125  0.0625]
 [ 0.625   0.3125  0.0625]
 [ 0.625   0.3125  0.0625]]
Current round: 7
[[ 0.625   0.3125  0.0625]
 [ 0.625   0.3125  0.0625]
 [ 0.625   0.3125  0.0625]]
。。。。。。
Current round: 9
[[ 0.625   0.3125  0.0625]
 [ 0.625   0.3125  0.0625]
 [ 0.625   0.3125  0.0625]]
Current round: 10
[[ 0.625   0.3125  0.0625]
 [ 0.625   0.3125  0.0625]
 [ 0.625   0.3125  0.0625]]  

我们可以发现,在n≥6以后,Pn的值稳定不再变化,而且每一行都为[0.625 0.3125 0.0625],这和我们前面的稳定分布是一致的。这个性质同样不光是离散状态,连续状态时也成立。

在这里插入图片描述

上面的性质中需要解释的有:

1)非周期的马尔科夫链:这个主要是指马尔科夫链的状态转化不是循环的,如果是循环的则永远不会收敛。幸运的是我们遇到的马尔科夫链一般都是非周期性的。用数学方式表述则是:对于任意某一状态i,d为集合 n ∣ n ≥ 1 , P i i n > 0 {n∣n≥1,P^n_{ii}>0} nn1,Piin>0 的最大公约数,如果 d=1 ,则该状态为非周期的

2)任何两个状态是连通的:这个指的是从任意一个状态可以通过有限步到达其他的任意一个状态,不会出现条件概率一直为0导致不可达的情况。

3)马尔科夫链的状态数可以是有限的,也可以是无限的。因此可以用于连续概率分布和离散概率分布。

4)π通常称为马尔科夫链的平稳分布。

2.3 基于马尔科夫链采样

如果我们得到了某个平稳分布所对应的马尔科夫链状态转移矩阵,我们就很容易采用出这个平稳分布的样本集。
在这里插入图片描述

2.4 马尔科夫链采样小结

如果假定我们可以得到我们需要采样样本的平稳分布所对应的马尔科夫链状态转移矩阵,那么我们就可以用马尔科夫链采样得到我们需要的样本集,进而进行蒙特卡罗模拟。但是一个重要的问题是,随意给定一个平稳分布π,如何得到它所对应的马尔科夫链状态转移矩阵P呢?这是个大问题。我们绕了一圈似乎还是没有解决任意概率分布采样样本集的问题。

幸运的是,MCMC采样通过迂回的方式解决了上面这个大问题,我们在下一篇来讨论MCMC的采样,以及它的使用改进版采样: M-H采样和Gibbs采样

MCMC(三)MCMC采样和M-H采样

在MCMC(二)马尔科夫链中我们讲到给定一个概率平稳分布π, 很难直接找到对应的马尔科夫链状态转移矩阵P。而只要解决这个问题,我们就可以找到一种通用的概率分布采样方法,进而用于蒙特卡罗模拟。本篇我们就讨论解决这个问题的办法:MCMC采样和它的易用版M-H采样。

3.1 马尔科夫链的细致平稳条件

在这里插入图片描述

那么如何使这个等式满足呢?下面我们来看MCMC采样如何解决这个问题。

3.2 MCMC采样

在这里插入图片描述
好了,现在我们来总结下MCMC的采样过程。

1)输入我们任意选定的马尔科夫链状态转移矩阵Q,平稳分布π(x),设定状态转移次数阈值n1
,需要的样本个数n2
    2)从任意简单概率分布采样得到初始状态值 x 0 x_0 x0
    3)for t=0 to n 1 n_1 n1+ n 2 n_2 n2−1:
      a) 从条件概率分布 Q ( x ∣ x t ) Q(x|x_t) Q(xxt)中采样得到样本 x ∗ x_∗ x
      b) 从均匀分布采样u∼uniform[0,1]
      c) 如果 u < α ( x t , x ∗ ) = π ( x ∗ ) Q ( x ∗ , x t ) u<α(x_t,x_∗)=π(x∗)Q(x_∗,x_t) u<α(xt,x)=π(x)Q(x,xt), 则接受转移 x t → x ∗ x_t→x_∗ xtx,即 x t + 1 = x ∗ x_t+1=x_∗ xt+1=x
      d) 否则不接受转移,即 x t + 1 = x t x_t+1=x_t xt+1=xt
    样本集 ( x n 1 , x n 1 + 1 , , . . . , x n 1 + n 2 − 1 (x_{n1},x_{n1+1},,...,x_{n1+n2-1} (xn1,xn1+1,,...,xn1+n21即为我们需要的平稳分布对应的样本集。

上面这个过程基本上就是MCMC采样的完整采样理论了,但是这个采样算法还是比较难在实际中应用,为什么呢?问题在上面第三步的c步骤,接受率这儿。由于 α ( x t , x ∗ ) = α(x_t,x_∗)= α(xt,x)=可能非常的小,比如0.1,导致我们大部分的采样值都被拒绝转移,采样效率很低。有可能我们采样了上百万次马尔可夫链还没有收敛,也就是上面这个 n 1 n_1 n1要非常非常的大,这让人难以接受,怎么办呢?这时就轮到我们的M-H采样出场了。

3.3 M-H采样

M-H采样是Metropolis-Hastings采样的简称,这个算法首先由Metropolis提出,被Hastings改进,因此被称之为Metropolis-Hastings采样或M-H采样

M-H采样解决了我们上一节MCMC采样接受率过低的问题

在这里插入图片描述

3.4 M-H采样实例

为了更容易理解,这里给出一个M-H采样的实例。

完整代码参见我的github: https://github.com/ljpzzz/machinelearning/blob/master/mathematics/mcmc_3_4.ipynb

在例子里,我们的目标平稳分布是一个均值3,标准差2的正态分布,而选择的马尔可夫链状态转移矩阵 Q ( i , j ) Q(i,j) Q(i,j)的条件转移概率是以i为均值,方差1的正态分布在位置j的值。这个例子仅仅用来让大家加深对M-H采样过程的理解。毕竟一个普通的一维正态分布用不着去用M-H采样来获得样本。

代码如下:

import random
import math
from scipy.stats import norm
import matplotlib.pyplot as plt
%matplotlib inline

def norm_dist_prob(theta):
    y = norm.pdf(theta, loc=3, scale=2)
    return y

T = 5000
pi = [0 for i in range(T)]
sigma = 1
t = 0
while t < T-1:
    t = t + 1
    pi_star = norm.rvs(loc=pi[t - 1], scale=sigma, size=1, random_state=None)
    alpha = min(1, (norm_dist_prob(pi_star[0]) / norm_dist_prob(pi[t - 1])))

    u = random.uniform(0, 1)
    if u < alpha:
        pi[t] = pi_star[0]
    else:
        pi[t] = pi[t - 1]


plt.scatter(pi, norm.pdf(pi, loc=3, scale=2))
num_bins = 50
plt.hist(pi, num_bins, normed=1, facecolor='red', alpha=0.7)
plt.show()

输出的图中可以看到采样值的分布与真实的分布之间的关系如下,采样集还是比较拟合对应分布的。
在这里插入图片描述

3.5 M-H采样总结

M-H采样完整解决了使用蒙特卡罗方法需要的任意概率分布样本集的问题,因此在实际生产环境得到了广泛的应用。

但是在大数据时代,M-H采样面临着两大难题:

1) 我们的数据特征非常的多,M-H采样由于接受率计算式 π ( j ) Q ( j , i ) π ( i ) Q ( i , j ) \frac{π(j)Q(j,i)}{π(i)Q(i,j)} π(i)Q(i,j)π(j)Q(j,i)的存在,在高维时需要的计算时间非常的可观,算法效率很低。同时 α ( i , j ) α(i,j) α(i,j)一般小于1,有时候辛苦计算出来却被拒绝了。能不能做到不拒绝转移呢?

2) 由于特征维度大,很多时候我们甚至很难求出目标的各特征维度联合分布,但是可以方便求出各个特征之间的条件概率分布。这时候我们能不能只有各维度之间条件概率分布的情况下方便的采样呢?

Gibbs采样解决了上面两个问题,因此在大数据时代,MCMC采样基本是Gibbs采样的天下,下一篇我们就来讨论Gibbs采样。

MCMC(四)Gibbs采样

在MCMC(三)MCMC采样和M-H采样中,我们讲到了M-H采样已经可以很好的解决蒙特卡罗方法需要的任意概率分布的样本集的问题。但是M-H采样有两个缺点:一是需要计算接受率,在高维时计算量大。并且由于接受率的原因导致算法收敛时间变长。二是有些高维数据,特征的条件概率分布好求,但是特征的联合分布不好求。因此需要一个好的方法来改进M-H采样,这就是我们下面讲到的Gibbs采样。

4.1 重新寻找合适的细致平稳条件

在这里插入图片描述在这里插入图片描述

4.2 二维Gibbs采样

在这里插入图片描述
用下图可以很直观的看出,采样是在两个坐标轴上不停的轮换的。当然,坐标轴轮换不是必须的,我们也可以每次随机选择一个坐标轴进行采样。不过常用的Gibbs采样的实现都是基于坐标轴轮换的。
在这里插入图片描述

4.3 多维Gibbs采样

在这里插入图片描述
    同样的,轮换坐标轴不是必须的,我们可以随机选择某一个坐标轴进行状态转移,只不过常用的Gibbs采样的实现都是基于坐标轴轮换的。

4.4 二维Gibbs采样实例

这里给出一个Gibbs采样的例子。完整代码参见我的github: https://github.com/ljpzzz/machinelearning/blob/master/mathematics/mcmc_3_4.ipynb

具体的代码如下:

from mpl_toolkits.mplot3d import Axes3D
from scipy.stats import multivariate_normal
samplesource = multivariate_normal(mean=[5,-1], cov=[[1,1],[1,4]])

def p_ygivenx(x, m1, m2, s1, s2):
    return (random.normalvariate(m2 + rho * s2 / s1 * (x - m1), math.sqrt((1 - rho ** 2) * (s2**2))))

def p_xgiveny(y, m1, m2, s1, s2):
    return (random.normalvariate(m1 + rho * s1 / s2 * (y - m2), math.sqrt((1 - rho ** 2) * (s1**2))))

N = 5000
K = 20
x_res = []
y_res = []
z_res = []
m1 = 5
m2 = -1
s1 = 1
s2 = 2

rho = 0.5
y = m2

for i in xrange(N):
    for j in xrange(K):
        x = p_xgiveny(y, m1, m2, s1, s2)
        y = p_ygivenx(x, m1, m2, s1, s2)
        z = samplesource.pdf([x,y])
        x_res.append(x)
        y_res.append(y)
        z_res.append(z)

num_bins = 50
plt.hist(x_res, num_bins, normed=1, facecolor='green', alpha=0.5)
plt.hist(y_res, num_bins, normed=1, facecolor='red', alpha=0.5)
plt.title('Histogram')
plt.show()

输出的两个特征各自的分布如下:
在这里插入图片描述
    然后我们看看样本集生成的二维正态分布,代码如下:

fig = plt.figure()
ax = Axes3D(fig, rect=[0, 0, 1, 1], elev=30, azim=20)
ax.scatter(x_res, y_res, z_res,marker='o')
plt.show()

输出的正态分布图如下:
在这里插入图片描述

4.5 Gibbs采样小结

由于Gibbs采样在高维特征时的优势,目前我们通常意义上的MCMC采样都是用的Gibbs采样。当然Gibbs采样是从M-H采样的基础上的进化而来的,同时Gibbs采样要求数据至少有两个维度,一维概率分布的采样是没法用Gibbs采样的,这时M-H采样仍然成立。

有了Gibbs采样来获取概率分布的样本集,有了蒙特卡罗方法来用样本集模拟求和,他们一起就奠定了MCMC算法在大数据时代高维数据模拟求和时的作用。MCMC系列就在这里结束吧。

(欢迎转载,转载请注明出处 https://www.cnblogs.com/pinard/p/6625739.html。欢迎沟通交流: liujianping-ok@163.com)

  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值