[关闭]
@zsh-o 2018-12-16T11:36:13.000000Z 字数 6298 阅读 1146

番外 - MCMC

机器学习 《统计学习方法》


  1. %matplotlib inline
  2. import numpy as np
  3. from matplotlib import pyplot as plt

蒙特卡洛 均值方法 求积分

利用一个容易进行抽样的分布,根据大数定理可以对函数积分进行估计

  1. def f(x):
  2. return 0.3 * np.exp(-(x - 0.3) ** 2) + 0.7 * np.exp(- (x - 2.) ** 2 / 0.3)
  1. ## 蒙特卡洛 均值法 求f的积分
  2. def MC(f, low, high, size):
  3. z = np.random.uniform(low=low, high=high, size=size)
  4. return np.sum(f(z) * (high - low)) / size
  1. Int_f = MC(f, -2, 4, 10**6)
  2. Int_f
1.211298965791444

拒绝采样

img_20180807_234659.753.png-119.1kB

相当于在所围成的区域里面进行抽样,只返回在所围成区域内部的采样点,这样在所围成的区域进行抽样每个抽样点的概率为表示点处的概率,表示上面的表示在均匀分布进行采样,每个点的概率均是,故这样得到的每个采样点的概率均相同并且等于,相当于的积分,然后根据蒙特卡洛思想,根据判断该点是否应该保留,则被保留的概率为均匀分布中的部分则保留概率为,然后再由点的概率为,故经过该拒绝操作之后点并且被接受的概率为

接受的概率为

因此,总的迭代次数大致为所要样本点数的
最后在接受的条件下每个点的概率为

  1. size = 10**4
  2. mean = 1.4
  3. sigma = 1.2
  4. k = 3
  1. ## 为了能够使后面的可视化对其曲线,对f(x)进行归一化,用的上面的均值方法
  2. def p(x):
  3. return f(x) / Int_f
  4. def q(x):
  5. return 1 / (sigma * np.sqrt(2 * np.pi)) * np.exp(- (x - mean) ** 2 / (2 * sigma ** 2))
  6. def sample_q():
  7. return np.random.normal(loc=mean, scale=sigma)
  1. def reject_sampling(p, q, sample_q, k, size):
  2. res = []
  3. it = 0
  4. ti = 0
  5. while(it < size):
  6. z = sample_q()
  7. qz = q(z)
  8. u = np.random.uniform(low=0,high=k*qz)
  9. pz = p(z)
  10. if u < pz:
  11. res.append(z)
  12. it += 1
  13. ti += 1
  14. return np.array(res), ti
  1. sample, ti = reject_sampling(p, q, sample_q, k, size)
  2. ti
30031
  1. count, bins, ignored = plt.hist(sample, bins=300,density=True)
  2. plt.plot(bins, p(bins))
  3. plt.plot(bins, k * q(bins))
[<matplotlib.lines.Line2D at 0x15bbd3a0518>]

output_11_1.png-15.7kB

MCMC

这部分《LDA数学八卦》写的非常好了,这里只提一下
上面比较麻烦的是的选择,如何消除,MCMC的方法通过消除了
MCMC用了马尔科夫的平稳分布的性质,无论初始概率分布是多少,通过转移矩阵的有限次状态转移后,最终都会收敛到平稳分布,也即

而且

此时有马氏链的状态转移过程表示如下,

先只考虑,由马氏链有的联合概率为,因而的边缘概率为

由此,当初始分布为平稳分布,故是独立同分布的,即使每一步均是从转移矩阵组成的概率里面进行抽样,抽样的边缘概率仍然满足平稳分布,也即每一个抽样点均满足抽样分布,而且当该过程持续到,同理

,当初始为平稳分布时,故只需要有了平稳分布为要抽样分布的转移矩阵之后,就可以利用每次抽样状态转移的方法得到所要的抽样样本,而且即使初始分布不是平稳分布,由于任意初始分布经过有限步骤状态转移后均变成平稳分布,故抽样时可以是任意初始状态,在一定步骤之后就变成了所要的抽样

接下来问题变成了如何得到平稳分布是所要分布的转移矩阵,直接根据平稳分布构造转移矩阵是非常困难的,大哥们为平稳分布的转移矩阵添加了一个约束使其变得容易构造,该约束就是细致平稳条件

如果非周期马氏链的转移矩阵和分布满足

是马氏链的平稳分布,上式被称为细致平稳条件

满足细致平稳条件肯定是平稳分布

接下来是如何利用该细致平稳条件构造满足条件的转移矩阵,现有任意分布和任意转移矩阵为状态,我们来构造

使其满足细致平稳条件,很容易可以得到

此时的平稳分布即为转移矩阵为

再根据上面的抽样过程,当前状态为,我们要从转移矩阵中抽样得到下一个状态,相当于我们要在分布中抽样,但该分布是不规则的无法直接抽样,但转移概率是任意的,可以选其为合适的容易抽样的概率分布,按照上面拒绝采样的方法就相当于,首先在抽样出状态,然后有的概率接受该样本,应该如何证明在中抽样等价于在,然后再以概率接受该抽样,并且,设抽样为,接受率为,则

这时如果确实是一个关于的概率分布的话,那么,这个地方有点问题。。。


以下面代码中例子为例,,则

故实际迭代次数大致为所求样本个数的
同样

  1. def q(y, x): # q(y|x)
  2. return 1/(5. - (-2.5))
  3. def sample_q(x):
  4. return np.random.uniform(low=-2.5, high=5.)
  1. def mcmc(p, q, sample_q, size, base_iter=10**2):
  2. res = []
  3. it = 0
  4. x = 0.
  5. ti = 0
  6. while it < size + base_iter:
  7. y = sample_q(x)
  8. u = np.random.uniform(low=0, high=1)
  9. if u <= p(y)*q(x, y):
  10. x = y
  11. it += 1
  12. res.append(x)
  13. ti += 1
  14. return np.array(res)[base_iter:], ti
  1. x = np.linspace(-2, 4, 10000)
  2. y = p(x)
  1. sample, ti = mcmc(p, q, sample_q, 10**4)
  2. count, bins, ignored = plt.hist(sample, bins=300,density=True)
  3. plt.plot(bins, p(bins))
[<matplotlib.lines.Line2D at 0x15bbf406940>]

image.png-12kB

  1. ti
561925

Metropolis Hastings

由细致平稳条件

两边同乘以一个系数不改变平稳条件,但却使得每次抽样的接受率变大,故Metropolis Hastings算法的思想是,在方程两边同乘以一个系数使得两边的接受率的较大值扩展到1,于是

  1. def Metropolis_Hastings(p, q, sample_q, size, base_iter=10**2):
  2. res = []
  3. it = 0
  4. x = 0.
  5. ti = 0
  6. while it < size + base_iter:
  7. y = sample_q(x)
  8. u = np.random.uniform(low=0., high=1)
  9. a = min(p(y) / p(x) * q(y, x) / q(x, y), 1)
  10. if u < a:
  11. x = y
  12. it += 1
  13. res.append(x)
  14. ti += 1
  15. return np.array(res)[base_iter:], ti
  1. sample, ti = Metropolis_Hastings(p, q, sample_q, 10**4)
  2. count, bins, ignored = plt.hist(sample, bins=300,density=True)
  3. plt.plot(bins, p(bins))
[<matplotlib.lines.Line2D at 0x15bbf76eb70>]

image.png-11.8kB

  1. ti
27495

这个地方需要注意,原始写的有点问题,每次抽样出来的样本都需要加入到总体样本中,这样的话,其跟拒绝采样的不同点在于MCMC不抛弃样本,只根据当前状态判断是否跳转

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注