哈密​​顿蒙特卡洛如何工作?

机器算法验证 贝叶斯 马尔可夫链蒙特卡罗 微分方程 汉密尔顿-蒙特卡罗
2022-03-27 20:33:58

我制作了下图来解释我目前是如何理解 HMC 算法的。如果这种理解正确或不正确,我希望得到主题专家的验证。下面幻灯片中的文本复制如下,以便于访问:


哈密​​顿蒙特卡洛:卫星绕行星运行。卫星离地球越近,重力的影响就越大。这意味着,(A)更高的势能和(B)维持轨道所需的更高动能。在离地球更远的地方,同样的动能会将卫星从轨道上弹出。该卫星的任务是收集特定地理区域的照片。卫星绕地球运行的距离越近,它在轨道上的移动速度就越快,它越过该区域的次数越多,它收集的照片就越多。相反,卫星离地球越远,它在轨道上移动的速度越慢,它越过该区域的次数越少,它收集的照片就越少。在采样的上下文中,与行星的距离表示与分布期望的距离。一个低可能性的区域远非预期;当“环绕这种可能性”时,较低的动能意味着在固定时间间隔内收集的样本较少,而当环绕较高的可能性时,意味着在相同的固定时间间隔内收集的样本更多。在给定的轨道上,总能量、动能和势能是恒定的;然而,两者的关系并不简单。哈密​​顿方程将一个变化与另一个变化联系起来。也就是说,位置相对于时间的梯度等于动量。并且动量相对于时间的梯度等于势能相对于位置的梯度。为了计算卫星将沿着其轨道路径行进多远,必须使用越级积分,迭代更新动量和位置向量。在抽样的背景下,可能性类似于与行星的距离,势能相对于位置的梯度是概率密度函数相对于其输入参数 x 的梯度。该信息允许探索对应于相同可能性 y 的各种输入 X 的轨道路径。
然而,我们不仅仅对探索一种可能性感兴趣,我们还必须探索多条轨道路径。要做到这一点,必须随机增加动量,使卫星离地球更近或更远。这些随机的“动量踢”允许不同的可能性被环绕。幸运的是,汉密尔顿方程确保无论可能性如何,收集的样本数量与可能性成正比,因此收集的样本遵循目标分布的形状。


我的问题是 - 这是思考哈密顿蒙特卡洛如何工作的准确方法吗?

HMC_更新

编辑:

根据我对算法的理解,我已经在一些代码中实现了。它适用于 mu=0,sigma=1 的高斯。但是,如果我更改 sigma,它就会中断。任何见解将不胜感激。

import numpy as np
import random
import scipy.stats as st
import matplotlib.pyplot as plt
from autograd import grad

def normal(x,mu,sigma):
    numerator = np.exp((-(x-mu)**2)/(2*sigma**2))
    denominator = sigma * np.sqrt(2*np.pi)
    return numerator/denominator

def neg_log_prob(x,mu,sigma):
    num = np.exp(-1*((x-mu)**2)/2*sigma**2)
    den = sigma*np.sqrt(np.pi*2)
    return -1*np.log(num/den)

def HMC(mu=0.0,sigma=1.0,path_len=1,step_size=0.25,initial_position=0.0,epochs=1_000):
    # setup
    steps = int(path_len/step_size) -1 # path_len and step_size are tricky parameters to tune...
    samples = [initial_position]
    momentum_dist = st.norm(0, 1) 
    # generate samples
    for e in range(epochs):
        q0 = np.copy(samples[-1])
        q1 = np.copy(q0)
        p0 = momentum_dist.rvs()        
        p1 = np.copy(p0) 
        dVdQ = -1*(q0-mu)/(sigma**2) # gradient of PDF wrt position (q0) aka momentum wrt position

        # leapfrog integration begin
        for s in range(steps):
            p1 += step_size*dVdQ/2 # as potential energy increases, kinetic energy decreases
            q1 += step_size*p1 # position increases as function of momentum 
            p1 += step_size*dVdQ/2 # second half "leapfrog" update to momentum    
        # leapfrog integration end        
        p1 = -1*p1 #flip momentum for reversibility    
        
        #metropolis acceptance
        q0_nlp = neg_log_prob(x=q0,mu=mu,sigma=sigma)
        q1_nlp = neg_log_prob(x=q1,mu=mu,sigma=sigma)        

        p0_nlp = neg_log_prob(x=p0,mu=0,sigma=1)
        p1_nlp = neg_log_prob(x=p1,mu=0,sigma=1)
        
        # Account for negatives AND log(probabiltiies)...
        target = q0_nlp - q1_nlp # P(q1)/P(q0)
        adjustment = p1_nlp - p0_nlp # P(p1)/P(p0)
        acceptance = target + adjustment 
        
        event = np.log(random.uniform(0,1))
        if event <= acceptance:
            samples.append(q1)
        else:
            samples.append(q0)
    
    return samples

现在它在这里工作:

mu, sigma = 0,1
trial = HMC(mu=mu,sigma=sigma,path_len=2,step_size=0.25)

# What the dist should looks like
lines = np.linspace(-6,6,10_000)
normal_curve = [normal(x=l,mu=mu,sigma=sigma) for l in lines]

# Visualize
plt.plot(lines,normal_curve)
plt.hist(trial,density=True,bins=20)
plt.show()

HMC_1

但是当我将 sigma 更改为 2 时它会中断。

# Generate samples
mu, sigma = 0,2
trial = HMC(mu=mu,sigma=sigma,path_len=2,step_size=0.25)

# What the dist should looks like
lines = np.linspace(-6,6,10_000)
normal_curve = [normal(x=l,mu=mu,sigma=sigma) for l in lines]

# Visualize
plt.plot(lines,normal_curve)
plt.hist(trial,density=True,bins=20)
plt.show()

HMC_sampler2

有任何想法吗?我觉得我已经接近“得到它”了。

1个回答

在回答有关以直观方式思考哈密顿蒙特卡洛的问题之前,最好真正牢牢掌握常规 MCMC。让我们暂时搁置卫星比喻。

当您想要从分布中获得无偏样本时, MCMC很有用到 PDF,但不是 PDF 本身。这出现在(例如)物理模拟中:PDF 由玻尔兹曼分布 p ~ exp(-E/kT) 给出,但是您可以为系统的任何配置计算的是 E,而不是 p。比例常数是未知的,因为 exp(-E/kT) 在可能配置的整个空间上的积分通常很难计算。MCMC 通过以特定方式进行随机游走来解决该问题,其中采取(“接受”)每一步的概率与 p 值的比率有关(比例常数抵消)。随着时间的推移,随机游走中接受样本的分布收敛到我们想要的 PDF,而无需显式计算 p。

请注意,在上面,任何采取随机步骤的方法都同样有效,只要随机游走者可以探索整个空间。验收标准保证所选样本收敛到真实 PDF。在实践中,使用当前样本周围的高斯分布(并且可以改变 sigma,以便接受步骤的比例保持相对较高)。从当前样本周围的任何其他连续分布(“跳跃分布”)采取步骤原则上没有错,尽管收敛可能要慢得多。

现在,哈密顿量蒙特卡洛扩展了物理隐喻,特别尝试朝着比高斯步骤容易被接受的方向迈出一步。如果它试图求解势能为 E 的系统的运动,则这些步骤是跳跃式积分器将采取的步骤。这些运动方程还包括动能项,具有(不是字面意义上的物理)“质量”和“势头”。然后,越级积分器在“时间”中采取的步骤作为建议传递给 MCMC 算法。

为什么这行得通?高斯 MC 在每个方向上以相同的概率走相同的距离;唯一使它偏向于 PDF 中人口更密集的区域的是,朝着错误方向的步骤更有可能被拒绝。Hamiltonian MC 提出了 E 梯度方向的步骤,以及最近步骤中累积运动的方向(“动量”的方向和大小)。这可以更快地探索空间,也可以更快地到达人口稠密的地区。

现在,卫星比喻:我认为这不是一个非常有用的思考方式。卫星在精确的轨道上运行;你这里的东西是非常随机的,更像是容器中的一个气体粒子和其他粒子。每一次随机碰撞都会给你一个“台阶”;随着时间的推移,粒子将以相等的概率出现在容器中的任何地方(因为这里的 PDF 在任何地方都是相等的,除了代表非常高能量/实际上为零的 PDF 的墙壁)。高斯 MCMC 就像一个有效的零质量粒子进行随机游走(或相对粘性介质中的非零质量粒子):它将通过布朗运动到达那里,但不一定很快。哈密​​顿量 MC 是一个非零质量的粒子:尽管发生碰撞,它可能会聚集足够的动量以保持相同的方向运动,因此它有时可能会从容器的一端射到另一端(取决于它的质量与碰撞的频率/幅度)。当然,它仍然会从墙壁上反弹,但通常会更快地探索。