Bootstrap

第19章 马尔可夫链蒙特卡罗法(MH算法、吉布斯抽样)

本章学习使用书籍:李航老师的《机器学习方法》

配合观看视频:蒙特卡洛(Monte Carlo, MCMC)方法的原理和应用P1、P2机器学习-白板推导系列(十三)-MCMC(Markov Chain Monte Carlo)

其他博客链接:

https://cosx.org/2013/01/lda-math-mcmc-and-gibbs-sampling

https://www.cnblogs.com/pinard/p/6638955.html

https://zhuanlan.zhihu.com/p/37121528

把以上都看完就无敌了孩子。

本章概要:

  1. 蒙特卡罗法是通过基于概率模型的抽样进行数值近似计算的方法,蒙特卡罗法可以用于概率分布的抽样、概率分布数学期望的估计、定积分的近似计算

随机抽样是蒙特卡罗法的一种应用,有直接抽样法、接受拒绝抽样法等。接受拒绝法的基本想法是,找一个容易抽样的建议分布,其密度函数的数倍大于等于想要抽样的概率分布的密度函数。按照建议分布随机抽样得到样本,再按要抽样的概率分布与建议分布的倍数的比例随机决定接受或拒绝该样本,循环执行以上过程。

马尔可夫链蒙特卡罗法数学期望估计是蒙特卡罗法的另一种应用,按照概率分布 p ( x ) p(x) p(x)抽取随机变量 x x x n n n个独立样本,根据大数定律可知,当样本容量增大时,函数的样本均值以概率1收敛于函数的数学期望

f ^ n → E p ( x ) [ f ( x ) ] , n → ∞ \hat { f } _ { n } \rightarrow E _ { p ( x ) } [ {f ( x )} ] , \quad n \rightarrow \infty f^nEp(x)[f(x)],n

计算样本均值 f ^ n \hat { f } _ { n } f^n,作为数学期望 E p ( x ) [ f ( x ) ] E _ { p ( x ) } [ {f ( x )} ] Ep(x)[f(x)]的估计值。

  1. 马尔可夫链是具有马尔可夫性的随机过程 P ( X t ∣ X 0 X 1 ⋯ X t − 1 ) = P ( X t ∣ X t − 1 ) , t = 1 , 2 , ⋯ P ( X _ { t } | X _ { 0 } X _ { 1 } \cdots X _ { t - 1 } ) = P ( X _ { t } | X _ { t - 1 } ) , \quad t = 1,2 , \cdots P(XtX0X1Xt1)=P(XtXt1),t=1,2,
    通常考虑时间齐次马尔可夫链。有离散状态马尔可夫链和连续状态马尔可夫链,分别由概率转移矩阵 P P P和概率转移核 p ( x , y ) p(x,y) p(x,y)定义。

满足 π = P π \pi = P \pi π=Pπ π ( y ) = ∫ p ( x , y ) π ( x ) d x \pi ( y ) = \int p ( x , y ) \pi ( x ) d x π(y)=p(x,y)π(x)dx的状态分布称为马尔可夫链的平稳分布。

马尔可夫链有不可约性、非周期性、正常返等性质。一个马尔可夫链若是不可约、非周期、正常返的,则该马尔可夫链满足遍历定理。当时间趋于无穷时,马尔可夫链的状态分布趋近于平稳分布,函数的样本平均依概率收敛于该函数的数学期望。

lim ⁡ t → ∞ P ( X t = i ∣ X 0 = j ) = π i , i = 1 , 2 , ⋯   ; j = 1 , 2 \operatorname { lim } _ { t \rightarrow \infty } P ( X _ { t } = i | X _ { 0 } = j ) = \pi _ { i } , \quad i = 1,2 , \cdots ; \quad j = 1,2 limtP(Xt=iX0=j)=πi,i=1,2,;j=1,2
f ^ t → E π [ f ( X ) ] , t → ∞ \hat { f } _ { t } \rightarrow E _ { \pi } [ {f ( X )} ] , \quad t \rightarrow \infty f^tEπ[f(X)],t
可逆马尔可夫链是满足遍历定理的充分条件。

  1. 马尔可夫链蒙特卡罗法是以马尔可夫链为概率模型的蒙特卡罗积分方法,其基本想法如下:

(1)在随机变量 x x x的状态空间 χ \chi χ上构造一个满足遍历定理条件的马尔可夫链,其平稳分布为目标分布 p ( x ) p(x) p(x)

(2)由状态空间的某一点 X 0 X_0 X0出发,用所构造的马尔可夫链进行随机游走,产生样本序列 X 1 , X 2 , ⋯   , X t , ⋯ X _ { 1 } , X _ { 2 } , \cdots , X _ { t } , \cdots X1,X2,,Xt,

(3)应用马尔可夫链遍历定理,确定正整数 m m m n ( m < n ) n(m<n) n(m<n),得到样本集合 { x m + 1 , x m + 2 , ⋯   , x n } \{ x _ { m + 1 } , x _ { m + 2 } , \cdots , x _ { n } \} {xm+1,xm+2,,xn},进行函数 f ( x ) f(x) f(x)的均值(遍历均值)估计:
E ^ f = 1 n − m ∑ i = m + 1 n f ( x i ) \hat { E } f = \frac { 1 } { n - m } \sum _ { i = m + 1 } ^ { n } {f ( x _ { i } )} E^f=nm1i=m+1nf(xi)

  1. Metropolis-Hastings算法是最基本的马尔可夫链蒙特卡罗法。假设目标是对概率分布 p ( x ) p ( x ) p(x)进行抽样,构造建议分布 q ( x , x ′ ) q ( x , x ^ { \prime } ) q(x,x),定义接受分布 α ( x , x ′ ) \alpha ( x , x ^ { \prime } ) α(x,x)进行随机游走,假设当前处于状态 x x x,按照建议分布 q ( x , x ′ ) q ( x , x ^ { \prime } ) q(x,x)机抽样,按照概率 α ( x , x ′ ) \alpha ( x , x ^ { \prime } ) α(x,x)接受抽样,转移到状态 x ′ x ^ { \prime } x,按照概率 1 − α ( x , x ′ ) 1- \alpha ( x , x ^ { \prime } ) 1α(x,x)拒绝抽样,停留在状态 x x x,持续以上操作,得到一系列样本。这样的随机游走是根据转移核为 p ( x , x ′ ) = q ( x , x ′ ) α ( x , x ′ ) p ( x , x ^ { \prime } ) = q ( x , x ^ { \prime } ) \alpha ( x , x ^ { \prime } ) p(x,x)=q(x,x)α(x,x)的可逆马尔可夫链(满足遍历定理条件)进行的,其平稳分布就是要抽样的目标分布 p ( x ) p ( x ) p(x)

  2. 吉布斯抽样(Gibbs sampling)用于多元联合分布的抽样和估计吉布斯抽样是单分量 Metropolis-Hastings-算法的特殊情况。这时建议分布为满条件概率分布 q ( x , x ′ ) = p ( x j ′ ∣ x − j ) q ( x , x ^ { \prime } ) = p ( x _ { j } ^ { \prime } | x _ { - j } ) q(x,x)=p(xjxj)
    吉布斯抽样的基本做法是,从联合分布定义满条件概率分布,依次从满条件概率分布进行抽样,得到联合分布的随机样本。假设多元联合概率分布为 p ( x ) = p ( x 1 , x 2 , ⋯   , x k ) p ( x ) = p ( x _ { 1 } , x _ { 2 } , \cdots , x _ { k } ) p(x)=p(x1,x2,,xk),吉布斯抽样从一个初始样本 x ( 0 ) = ( x 1 ( 0 ) , x 2 ( 0 ) , ⋯   , x k ( 0 ) ) T x ^ { ( 0 ) } = ( x _ { 1 } ^ { ( 0 ) } , x _ { 2 } ^ { ( 0 ) } , \cdots , x _ { k } ^ { ( 0 ) } ) ^ { T } x(0)=(x1(0),x2(0),,xk(0))T出发,不断进行迭代,每一次迭代得到联合分布的一个样本 x ( i ) = ( x 1 ( i ) , x 2 ( i ) , ⋯   , x k ( i ) ) T x ^ { ( i ) } = ( x _ { 1 } ^ { ( i ) } , x _ { 2 } ^ { ( i ) } , \cdots , x _ { k } ^ { ( i ) } ) ^ { T } x(i)=(x1(i),x2(i),,xk(i))T,在第 i i i次迭代中,依次对第 j j j个变量按照满条件概率分布随机抽样 p ( x j ∣ x 1 ( i ) , ⋯   , x j − 1 ( i ) , x j + 1 ( i − 1 ) , ⋯   , x k ( i − 1 ) ) , j = 1 , 2 , ⋯   , k p ( x _ { j } | x _ { 1 } ^ { ( i ) } , \cdots , x _ { j - 1 } ^ { ( i ) },x _ { j + 1 } ^ { ( i - 1 ) } , \cdots , x _ { k } ^ { ( i - 1 ) } ) , j = 1,2 , \cdots , k p(xjx1(i),,xj1(i),xj+1(i1),,xk(i1)),j=1,2,,k,得到 x j ( i ) x _ { j } ^ { ( i ) } xj(i)最终得到样本序列 { x ( 0 ) , x ( 1 ) , ⋯   , x ( n ) } \{ x ^ { ( 0 ) } , x ^ { ( 1 ) } , \cdots , x ^ { ( n ) } \} {x(0),x(1),,x(n)}

本文只挑几个课后习题。

习题19.1

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

import numpy as np


class MonteCarloIntegration:
    def __init__(self, func_f, func_p):
        # 所求期望的函数
        self.func_f = func_f
        # 抽样分布的概率密度函数
        self.func_p = func_p

    def solve(self, num_samples):
        """
        蒙特卡罗积分法
        :param num_samples: 抽样样本数量
        :return: 样本的函数均值
        """
        samples = self.func_p(num_samples)
        y = self.func_f(samples)
        return np.sum(y) / num_samples


def func_f(x):
    """定义函数f"""
    return x**2 * np.sqrt(2 * np.pi)  # 即h(x)/p(x)得到的函数表达式


def func_p(n):
    """p(x)是标准正态分布,随机抽样n个观测"""
    return np.random.standard_normal(int(n))


# 设置样本数量
num_samples = 1e6

# 使用蒙特卡罗积分法进行求解
monte_carlo_integration = MonteCarloIntegration(func_f, func_p)
result = monte_carlo_integration.solve(num_samples)
print("抽样样本数量:", num_samples)
print("近似解:", result)
抽样样本数量: 1000000.0
近似解: 2.508167414386113

习题19.6

 从一般的Metropolis-Hastings算法推导出单分量Metropolis-Hastings算法。

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

习题19.7

 假设进行伯努利实验,后验概率为 P ( θ ∣ y ) P(\theta | y) P(θy),其中变量 y ∈ { 0 , 1 } y \in \{ 0, 1 \} y{0,1} 表示实验可能的结果,变量 θ \theta θ 表示结果为 1 的概率。再假设先验概率 P ( θ ) P(\theta) P(θ) 遵循 Beta 分布 B ( α , β ) B(\alpha, \beta) B(α,β),其中 α = 1 , β = 1 \alpha = 1, \beta = 1 α=1,β=1;似然函数 P ( y ∣ θ ) P(y | \theta) P(yθ) 遵循二项分布 Bin ( n , k , θ ) \text{Bin}(n, k, \theta) Bin(n,k,θ),其中 n = 10 , k = 4 n = 10, k = 4 n=10,k=4,即实验进行 10 次其中结果为 1 的次数为 4。试用 Metropolis-Hastings 算法求后验概率分布 P ( θ ∣ y ) ∝ P ( θ ) P ( y ∣ θ ) P(\theta | y) \propto P(\theta) P(y | \theta) P(θy)P(θ)P(yθ) 的均值和方差。(提示:可采用 Metropolis 选择,即假设建议分布是对称的。)

解答:
为了使用 Metropolis-Hastings 算法求后验概率分布 P ( θ ∣ y ) P(\theta | y) P(θy),需要进行以下几个步骤:

  1. 定义先验分布和似然函数

    • 先验分布 P ( θ ) P(\theta) P(θ) 遵循 Beta 分布 B ( α , β ) B(\alpha, \beta) B(α,β),其中 α = 1 , β = 1 \alpha = 1, \beta = 1 α=1,β=1,即均匀分布。
    • 似然函数 P ( y ∣ θ ) P(y | \theta) P(yθ) 是二项分布 Bin ( n , k , θ ) \text{Bin}(n, k, \theta) Bin(n,k,θ),其中 n = 10 , k = 4 n = 10, k = 4 n=10,k=4
  2. 定义后验分布
    P ( θ ∣ y ) ∝ P ( θ ) P ( y ∣ θ ) P(\theta | y) \propto P(\theta) P(y | \theta) P(θy)P(θ)P(yθ)

  3. 选择提议分布
    使用对称的提议分布,例如正态分布。

  4. 实现 Metropolis-Hastings 算法

    • 初始化 θ \theta θ 值。
    • 迭代执行以下步骤:
      • 从提议分布中采样一个新的 θ ′ \theta' θ
      • 计算接受率:
        α = min ⁡ ( 1 , P ( θ ′ ∣ y ) P ( θ ∣ y ) ) \alpha = \min \left(1, \frac{P(\theta' | y)}{P(\theta | y)}\right) α=min(1,P(θy)P(θy))
      • 根据接受率决定是否接受新的 θ ′ \theta' θ
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import beta, binom

# 定义先验分布的参数
alpha_prior = 1
beta_prior = 1

# 定义似然函数的参数
n = 10
k = 4

# 定义后验分布
def posterior(theta):
    if 0 <= theta <= 1:
        prior = beta.pdf(theta, alpha_prior, beta_prior)
        likelihood = binom.pmf(k, n, theta)
        return prior * likelihood
    else:
        return 0

# Metropolis-Hastings 算法
def metropolis_hastings(posterior, initial_theta, num_samples, proposal_width):
    samples = []
    theta_current = initial_theta
    for _ in range(num_samples):
        theta_proposed = np.random.normal(theta_current, proposal_width)
        acceptance_ratio = posterior(theta_proposed) / posterior(theta_current)
        if np.random.rand() < acceptance_ratio:
            theta_current = theta_proposed
        samples.append(theta_current)
    return np.array(samples)

# 设置算法参数
initial_theta = 0.5
num_samples = 10000
proposal_width = 0.1

# 运行 Metropolis-Hastings 算法
samples = metropolis_hastings(posterior, initial_theta, num_samples, proposal_width)

# 后验分布的均值和方差
half=int(num_samples/2)
mean_theta = np.mean(samples[half:])
var_theta = np.var(samples[half:])

print(f'后验分布均值: {mean_theta}')
print(f'后验分布方差: {var_theta}')

# 绘制后验分布的样本直方图
plt.hist(samples[half:], bins=50, density=True, alpha=0.75, label='MCMC samples')
plt.xlabel('Theta')
plt.ylabel('Density')
plt.title('Posterior distribution of Theta')
plt.legend()
plt.show()
后验分布均值: 0.4127077514777162
后验分布方差: 0.019117645067499734

在这里插入图片描述

习题19.8

 设某试验可能有五种结果,其出现的概率分别为
θ 4 + 1 8 , θ 4 , η 4 , η 4 + 3 8 , 1 2 ( 1 − θ − η ) \frac{\theta}{4}+\frac{1}{8}, \quad \frac{\theta}{4}, \quad \frac{\eta}{4}, \quad \frac{\eta}{4}+\frac{3}{8}, \quad \frac{1}{2}(1-\theta-\eta) 4θ+81,4θ,4η,4η+83,21(1θη)
模型含有两个参数 θ \theta θ η \eta η,都介于 0 和 1 之间。现有 22 次试验结果的观测值为
y = ( y 1 , y 2 , y 3 , y 4 , y 5 ) = ( 14 , 1 , 1 , 1 , 5 ) y = (y_1, y_2, y_3, y_4, y_5) = (14, 1, 1, 1, 5) y=(y1,y2,y3,y4,y5)=(14,1,1,1,5)
其中 y i y_i yi 表示 22 次试验中第 i i i 个结果出现的次数, i = 1 , 2 , ⋯   , 5 i = 1,2,\cdots,5 i=1,2,,5。试用吉布斯抽样估计参数 θ \theta θ η \eta η 的均值和方差。

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

为了使用吉布斯抽样估计参数 θ \theta θ η \eta η 的均值和方差,我们需要以下几个步骤:

  1. 定义似然函数和联合后验分布
  2. 选择初始值
  3. 迭代进行吉布斯抽样
    • 依次从条件后验分布 P ( θ ∣ η , y ) P(\theta | \eta, y) P(θη,y) P ( η ∣ θ , y ) P(\eta | \theta, y) P(ηθ,y) 中抽样。
似然函数和联合后验分布

首先,给定观测数据 y = ( y 1 , y 2 , y 3 , y 4 , y 5 ) = ( 14 , 1 , 1 , 1 , 5 ) y = (y_1, y_2, y_3, y_4, y_5) = (14, 1, 1, 1, 5) y=(y1,y2,y3,y4,y5)=(14,1,1,1,5),似然函数为:
P ( y ∣ θ , η ) = ( θ 4 + 1 8 ) y 1 ( θ 4 ) y 2 ( η 4 ) y 3 ( η 4 + 3 8 ) y 4 ( 1 2 ( 1 − θ − η ) ) y 5 P(y | \theta, \eta) = \left(\frac{\theta}{4} + \frac{1}{8}\right)^{y_1} \left(\frac{\theta}{4}\right)^{y_2} \left(\frac{\eta}{4}\right)^{y_3} \left(\frac{\eta}{4} + \frac{3}{8}\right)^{y_4} \left(\frac{1}{2}(1 - \theta - \eta)\right)^{y_5} P(yθ,η)=(4θ+81)y1(4θ)y2(4η)y3(4η+83)y4(21(1θη))y5

为了简化计算,我们假设先验分布为均匀分布 P ( θ ) = 1 P(\theta) = 1 P(θ)=1 P ( η ) = 1 P(\eta) = 1 P(η)=1,因此后验分布正比于似然函数。

P ( θ , η ∣ y ) ∝ P ( y ∣ θ , η ) ⋅ P ( θ ) ⋅ P ( η ) P(\theta, \eta | y) \propto P(y | \theta, \eta) \cdot P(\theta) \cdot P(\eta) P(θ,ηy)P(yθ,η)P(θ)P(η)

吉布斯抽样

吉布斯抽样是一个马尔可夫链蒙特卡罗(MCMC)算法,用于从高维联合分布中抽样。它通过依次从每个条件分布中抽样来实现。对于参数 θ \theta θ η \eta η,我们需要知道它们的条件后验分布。

  1. P ( θ ∣ η , y ) P(\theta | \eta, y) P(θη,y) 抽样
    P ( θ ∣ η , y ) ∝ ( θ 4 + 1 8 ) 14 ( θ 4 ) ( 1 2 ( 1 − θ − η ) ) 5 P(\theta | \eta, y) \propto \left(\frac{\theta}{4} + \frac{1}{8}\right)^{14} \left(\frac{\theta}{4}\right) \left(\frac{1}{2}(1 - \theta - \eta)\right)^{5} P(θη,y)(4θ+81)14(4θ)(21(1θη))5

  2. P ( η ∣ θ , y ) P(\eta | \theta, y) P(ηθ,y) 抽样
    P ( η ∣ θ , y ) ∝ ( η 4 ) ( η 4 + 3 8 ) ( 1 2 ( 1 − θ − η ) ) 5 P(\eta | \theta, y) \propto \left(\frac{\eta}{4}\right) \left(\frac{\eta}{4} + \frac{3}{8}\right) \left(\frac{1}{2}(1 - \theta - \eta)\right)^{5} P(ηθ,y)(4η)(4η+83)(21(1θη))5

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import beta

# 观测值
y = np.array([14, 1, 1, 1, 5])
n_iter = 10000  # 迭代次数
burn_in = 1000  # 烧入(收敛)步数

# 初始化参数
theta_samples = np.zeros(n_iter)
eta_samples = np.zeros(n_iter)
theta_samples[0] = np.random.rand()
eta_samples[0] = np.random.rand()


# 定义抽样函数
def sample_theta(eta, y):
    a = y[0] + y[1] + 1
    b = y[4] + 1
    return beta.rvs(a, b) * (1 - eta) # 贝塔分布产生的值为[0,1]之间,乘以(1-eta)以确保theta+eta<1


def sample_eta(theta, y):
    a = y[2] + y[3] + 1
    b = y[4] + 1
    return beta.rvs(a, b) * (1 - theta)


# 吉布斯抽样
for i in range(1, n_iter):
    theta_samples[i] = sample_theta(eta_samples[i - 1], y)
    eta_samples[i] = sample_eta(theta_samples[i], y)

# 去掉烧入阶段的样本
theta_samples_post_burn_in = theta_samples[burn_in:]
eta_samples_post_burn_in = eta_samples[burn_in:]

# 计算均值和方差
mean_theta = np.mean(theta_samples_post_burn_in)
var_theta = np.var(theta_samples_post_burn_in)
mean_eta = np.mean(eta_samples_post_burn_in)
var_eta = np.var(eta_samples_post_burn_in)

print(f'θ 的均值: {mean_theta}, 方差: {var_theta}')
print(f'η 的均值: {mean_eta}, 方差: {var_eta}')

# 绘制样本直方图
plt.figure(figsize=(10, 6))

plt.hist(theta_samples_post_burn_in,
         bins=50,
         density=True,
         alpha=0.5,
         label='$\\theta$ samples',
         color='blue')
plt.hist(eta_samples_post_burn_in,
         bins=50,
         density=True,
         alpha=0.5,
         label='$\\eta$ samples',
         color='red')

plt.xlabel('Parameter value')
plt.ylabel('Density')
plt.title('Posterior distributions of Theta and Eta')
plt.legend()
plt.show()
θ 的均值: 0.6393311463493639, 方差: 0.009050636891319451
η 的均值: 0.11999694894828164, 方差: 0.004142201497725771

在这里插入图片描述

代码解释:

  1. 初始化参数和样本数组

    • theta_sampleseta_samples 用于存储每次迭代的抽样结果。
    • 随机初始化参数 θ \theta θ η \eta η
  2. 定义条件抽样函数

    • sample_theta 函数根据当前的 η \eta η 和观测值 y y y 抽样新的 θ \theta θ 值。
    • sample_eta 函数根据当前的 θ \theta θ 和观测值 y y y 抽样新的 η \eta η 值。
  3. 吉布斯抽样迭代

    • 依次从条件分布 P ( θ ∣ η , y ) P(\theta | \eta, y) P(θη,y) P ( η ∣ θ , y ) P(\eta | \theta, y) P(ηθ,y) 中抽样新的 θ \theta θ η \eta η,并将结果存储到样本数组中。
  4. 计算结果

    • 计算 θ \theta θ η \eta η 样本的均值和方差。
    • 绘制 θ \theta θ η \eta η 样本的后验分布直方图。

通过执行以上代码,可以得到 θ \theta θ η \eta η 的后验分布的样本,并估计它们的均值和方差。

附:本来想安装关于MCMC的库pymc3,可死活安装不成功,整憔悴了!
习题参考: https://datawhalechina.github.io/statistical-learning-method-solutions-manual/#/chapter19/ch19

;