Neal R. M. , MCMC Using Hamiltonian Dynamics[J]. arXiv: Computation, 2011: 139-188.
@article{neal2011mcmc,
title={MCMC Using Hamiltonian Dynamics},
author={Neal, Radford M},
journal={arXiv: Computation},
pages={139–188},
year={2011}}
算法
先把算法列一下.
Input: 初始值 q q q, 步长 ϵ \epsilon ϵ与leapfrog迭代次数 L L L.
- 令 q ( 0 ) = q q^{(0)} = q q(0)=q;
- 循环迭代直到停止条件满足(以下第 t t t步):
- 从标准正态分布中抽取 p p p, q = q ( t − 1 ) q = q^{{(t-1)}} q=q(t−1), p ( t − 1 ) = p p^{(t-1)} = p p(t−1)=p.
- p = p − ϵ ∇ q U ( q ) / 2 , (alg.1) \tag{alg.1} p = p- \epsilon \nabla_q U(q) / 2, p=p−ϵ∇qU(q)/2,(alg.1)
- 重复
i
=
1
,
2
,
…
,
L
i=1,2,\ldots, L
i=1,2,…,L:
- q = q + ϵ ∇ p H ( p ) , (alg.2) \tag{alg.2} q = q + \epsilon \nabla_pH(p), q=q+ϵ∇pH(p),(alg.2)
- 如果
i
≠
L
i \not = L
i=L:
p = p − ϵ ∇ q U ( q ) . (alg.3) \tag{alg.3} p = p- \epsilon \nabla_q U(q). p=p−ϵ∇qU(q).(alg.3)
- p = p − ϵ ∇ q U ( q ) / 2 , p ∗ = − p , q ∗ = q . (alg.4) \tag{alg.4} p = p- \epsilon \nabla_q U(q) / 2, \quad p^* = -p, q^*=q. p=p−ϵ∇qU(q)/2,p∗=−p,q∗=q.(alg.4)
- 计算接受概率
α = min { 1 , exp ( − H ( q ∗ , p ∗ ) + H ( q ∗ , p ∗ ) } . (alg.5) \tag{alg.5} \alpha = \min \{ 1, \exp(-H(q^*,p^*) + H(q^*, p^*)\}. α=min{1,exp(−H(q∗,p∗)+H(q∗,p∗)}.(alg.5) - 从均匀分布 U ( 0 , 1 ) U(0,1) U(0,1)中抽取 u u u, 如果 u < α u<\alpha u<α, q ( t ) = q ∗ q^{(t)}=q^* q(t)=q∗, 否则 q ( t ) = q ( t − 1 ) q^{(t)}=q^{(t-1)} q(t)=q(t−1).
output: { p ( t ) , q ( t ) } \{p^{(t)},q^{(t)}\} {p(t),q(t)}.
注: 1中的标准正态分布不是唯一的, 但是文中选的便是这个. 4中的 p ∗ = − p p^*=-p p∗=−p在实际编写程序的时候可以省去.
符号说明
因为作者从物理方程的角度给出几何解释,所以这里给出的符号一般有俩个含义:
符号 | 概率 | 物理 |
---|---|---|
q q q | 随机变量,服从我们所在意的分布 | 冰球的位置 |
p p p | 用以构造马氏链的额外的变量 | 冰球的动量(mv) |
U ( q ) U(q) U(q) | …与我们所在意的分布有关 | 冰球的势能 |
K ( p ) K(p) K(p) | … | 冰球的动能 |
H ( q , p ) H(q, p) H(q,p) | 与我们所在意的分布有关 | H ( q , p ) = U ( q ) + K ( p ) H(q, p) = U(q) + K(p) H(q,p)=U(q)+K(p) |
Hamilton方程
物理解释
Hamilton方程(
i
=
1
,
2
,
…
,
d
i=1,2,\ldots, d
i=1,2,…,d,
d
d
d是维度):
d
q
i
d
t
=
∂
H
∂
p
i
(2.1)
\tag{2.1} \frac{dq_i}{dt} = \frac{\partial H}{\partial p_i}
dtdqi=∂pi∂H(2.1)
d
p
i
d
t
=
−
∂
H
∂
q
i
(2.2)
\tag{2.2} \frac{dp_i}{dt} = -\frac{\partial H}{\partial q_i}
dtdpi=−∂qi∂H(2.2)
这个东西怎么来的, 大概是因为
H
(
q
,
p
)
=
U
(
q
)
+
K
(
p
)
H(q, p) = U(q)+K(p)
H(q,p)=U(q)+K(p), 如果机械能守恒, 那么随着时间
t
t
t的变化
H
(
q
,
p
)
H(q, p)
H(q,p)应该是一个常数, 所以其关于t的导数应该是0.
d
H
d
t
=
∑
i
[
∂
H
∂
p
i
d
p
i
d
t
+
∂
H
∂
q
i
d
q
i
d
t
]
=
(
∇
p
H
)
T
p
˙
+
(
∇
q
H
)
T
q
˙
=
0
,
\frac{dH}{dt} = \sum_i [\frac{\partial H}{\partial p_i} \frac{dp_i}{dt}+\frac{\partial H}{\partial q_i}\frac{dq_i}{dt}] = (\nabla_p H)^T \dot{p}+(\nabla_qH)^T \dot{q} = 0,
dtdH=i∑[∂pi∂Hdtdpi+∂qi∂Hdtdqi]=(∇pH)Tp˙+(∇qH)Tq˙=0,
其中
p
˙
=
(
∂
p
1
/
∂
t
,
…
,
∂
p
d
/
∂
t
)
\dot{p}=(\partial{p_1}/\partial t, \ldots, \partial p_d / \partial t)
p˙=(∂p1/∂t,…,∂pd/∂t).
而
(
2.1
)
(2.1)
(2.1), 左边是速度
q
˙
=
v
\dot{q} = v
q˙=v, 右边
∇
p
H
=
∇
p
K
=
∇
p
∣
p
∣
2
2
m
=
p
m
=
v
=
q
˙
.
\nabla_p H = \nabla_p K = \nabla_p \frac{|p|^2}{2m} = \frac{p}{m} = v=\dot{q}.
∇pH=∇pK=∇p2m∣p∣2=mp=v=q˙.
不过,估计是先有的(2.2)再有的H吧, 就先这么理解吧. 需要一提的是,
K
(
p
)
K(p)
K(p)通常定义为
K
(
p
)
=
p
T
M
−
1
p
/
2
,
K(p)=p^TM^{-1}p/2,
K(p)=pTM−1p/2,
其中
M
M
M是对称正定的, 后面我们可以看到, 这种取法与正态分布相联系起来.
此时:
一些性质
可逆 Reversibility
映射
T
s
:
(
q
(
t
)
,
p
(
t
)
)
↦
(
q
(
t
+
s
)
,
p
(
t
+
s
)
)
T_s: (q(t), p(t)) \mapsto (q(t+s), p(t+s))
Ts:(q(t),p(t))↦(q(t+s),p(t+s))是一一的,这个我感觉只能从物理的解释上理解啊, 一个冰球从一个点到另一个点, 现在H确定, 初值确定, 不就相当于整个轨迹都确定了吗, 那从哪到哪自然是一一的, 也就存在逆
T
−
s
T_{-s}
T−s, 且只需:
d
q
i
d
t
=
−
∂
H
∂
p
i
,
\frac{dq_i}{dt} = -\frac{\partial H}{\partial p_i},
dtdqi=−∂pi∂H,
d
p
i
d
t
=
−
(
−
∂
H
∂
q
i
)
.
\frac{dp_i}{dt} = -(-\frac{\partial H}{\partial q_i}).
dtdpi=−(−∂qi∂H).
H的不变性
即
当然, 因为我们的算法是离散化的, 所以这个性质只是在
ϵ
\epsilon
ϵ比较小的时候近似保持.
保体积 Volume preservation
即假设区域 R = { ( q , p ) } R=\{(q,p)\} R={(q,p)}在映射 T t T_t Tt的作用下为 R t = { ( q ( t ) , p ( t ) } R_t=\{(q(t), p(t)\} Rt={(q(t),p(t)}, 则二者的体积相同, 均为 V V V.
定义
v
(
t
)
=
∫
R
t
d
V
=
∫
R
det
(
∂
T
t
∂
z
)
d
V
,
v(t)= \int_{R_t} dV = \int_{R} \det( \frac{\partial T_t}{\partial z}) dV,
v(t)=∫RtdV=∫Rdet(∂z∂Tt)dV,
其中
z
=
(
q
,
p
)
z = (q, p)
z=(q,p). 又
z
(
t
)
=
T
t
z
=
z
+
t
J
∇
H
(
z
)
+
O
(
t
2
)
,
z(t) = T_tz = z+t J\nabla H(z) + \mathcal{O}(t^2),
z(t)=Ttz=z+tJ∇H(z)+O(t2),
其中
f
:
=
d
z
d
t
=
J
∇
H
(
z
)
,
J
=
(
0
d
×
d
I
d
×
d
−
I
d
×
d
0
d
×
d
)
.
f:=\frac{dz}{dt} = J\nabla H(z), \\ J = \left ( \begin{array}{ll} 0_{d \times d} & I_{d\times d} \\ -I_{d\times d} & 0_{d \times d} \end{array}\right ).
f:=dtdz=J∇H(z),J=(0d×d−Id×dId×d0d×d).
所以
∂
T
t
∂
z
=
I
+
∂
f
∂
z
t
+
O
(
t
2
)
,
\frac{\partial{T_t}}{\partial z} = I + \frac{\partial f}{\partial z}t + \mathcal{O}(t^2),
∂z∂Tt=I+∂z∂ft+O(t2),
又对于任意方阵
A
A
A,
所以
det
(
∂
T
t
∂
z
)
=
1
+
t
r
(
∂
f
/
∂
z
)
t
+
O
(
t
2
)
,
\det (\frac{\partial{T_t}}{\partial z} ) = 1 + \mathrm{tr}(\partial f / \partial z) t + \mathcal{O}(t^2),
det(∂z∂Tt)=1+tr(∂f/∂z)t+O(t2),
且
t
r
(
∂
f
/
∂
z
)
=
d
i
v
f
\mathrm{tr}(\partial f / \partial z)=\mathrm{div} f
tr(∂f/∂z)=divf, 于是
d
v
d
t
∣
t
=
0
=
∫
R
d
i
v
f
d
V
.
\frac{d v}{ d t} |_{t=0} = \int_{R}\mathrm{div} f \: d V.
dtdv∣t=0=∫RdivfdV.
又
d
i
v
f
=
d
i
v
J
∇
H
(
z
)
=
J
d
i
v
∇
H
(
z
)
=
∑
i
=
1
d
[
∂
∂
q
∂
H
∂
p
i
−
∂
∂
p
∂
H
∂
q
i
]
=
0.
\mathrm{div}f = \mathrm{div} J\nabla H(z) = J \mathrm{div} \nabla H(z) = \sum_{i=1}^d [\frac{\partial}{\partial q}\frac{\partial H}{\partial p_i}-\frac{\partial}{\partial p}\frac{\partial H}{\partial q_i}] = 0.
divf=divJ∇H(z)=Jdiv∇H(z)=i=1∑d[∂q∂∂pi∂H−∂p∂∂qi∂H]=0.
对于
t
=
t
0
t=t_0
t=t0, 我们都可以类似的证明
d
v
(
t
0
)
/
d
t
=
0
dv(t_0)/dt=0
dv(t0)/dt=0, 所以
v
(
t
)
v(t)
v(t)是常数.
这部分的证明参考自
辛 Symplecticness
离散化Hamilton方程 leapfrog方法
下面四幅图, 是
U
(
q
)
=
q
2
/
2
,
K
(
p
)
=
p
2
/
2
U(q)=q^2/2, K(p)=p^2/2
U(q)=q2/2,K(p)=p2/2, 起始点为
(
q
,
p
)
=
(
0
,
1
)
(q, p) = (0, 1)
(q,p)=(0,1).
Euler’s method
如果假定
K
(
p
)
=
∑
i
=
1
d
p
i
2
2
m
i
K(p) = \sum_{i=1}^d \frac{p_i^2}{2m_i}
K(p)=∑i=1d2mipi2,
Modified Euler’s method
仅有一个小小的变动,
Leapfrog method
注意到, 在实际编写程序的时候, 除了第一步和最后一步, 我们可以将
p
p
p的俩个半步合并成一步.
另外从右下角的图可以发现, 因为离散化的缘故,
H
(
q
,
p
)
H(q, p)
H(q,p)的值是有偏差的. 但是Leapfrog 方法和 modified Euler方法都是保体积的, 因为每步更新都只改变一个量, 可以验证其雅可比行列式为1.
MCMC
概率与Hamiltonian, 正则(canonical)分布
如何将分布于Hamilton方程联系在一起? 假如, 我们关心的是
q
q
q的分布
P
(
q
)
P(q)
P(q), 则我们构造一个容易采样的分布
P
(
q
)
P(q)
P(q),
P
(
q
,
p
)
=
1
Z
exp
(
−
H
(
q
,
p
)
/
T
)
,
(3.2)
\tag{3.2} P(q, p) = \frac{1}{Z}\exp(-H(q,p)/T),
P(q,p)=Z1exp(−H(q,p)/T),(3.2)
其中
Z
Z
Z是规范化的常数,
T
T
T一般取1. 从(3.2)中容易得到
H
(
q
,
p
)
H(q,p)
H(q,p). 事实上此时
q
,
p
q, p
q,p是独立的(这么写是说明直接构造
P
(
q
,
p
)
P(q, p)
P(q,p)也是可以的), 则可以分别
P
(
q
)
=
1
Z
1
exp
(
−
U
(
q
)
/
T
)
,
P
(
p
)
=
1
Z
2
exp
(
−
K
(
p
)
/
T
)
.
P(q) = \frac{1}{Z_1}\exp(-U(q)/T), \\ P(p) = \frac{1}{Z_2}\exp(-K(p)/T).
P(q)=Z11exp(−U(q)/T),P(p)=Z21exp(−K(p)/T).
在贝叶斯统计中, 有
U
(
q
)
=
−
log
[
π
(
q
)
L
(
D
∣
q
)
]
,
U(q) = -\log [\pi (q) L(D|q)],
U(q)=−log[π(q)L(D∣q)],
其中
D
D
D为数据,
L
L
L为似然函数, 与文章中不同, 文章中是
L
(
q
∣
D
)
L(q|D)
L(q∣D), 应该是笔误.
HMC算法
就是开头提到的算法, 但是其中有一些地方值得思考. (alg.4)我们令 p ∗ = − p p^*=-p p∗=−p, 这一步在实际中是不起作用的, 既然 K ( p ) = K ( − p ) K(p)=K(-p) K(p)=K(−p)而且在下轮中我们重新采样 p p p, 我看网上的解释是为了理论, 取反这一部分使得proposal是对称的, 是建议分布 g ( p ∗ , q ∗ ∣ p , q ) = g ( p , q ∣ p ∗ , q ∗ ) g(p^*, q^*|p, q)=g(p, q| p^*, q^*) g(p∗,q∗∣p,q)=g(p,q∣p∗,q∗)? 不是很懂.
有点明白了, 首先因为Leapfrog是确定的, 所以
P
(
q
∗
,
p
∗
∣
q
,
p
)
P(q^*, p^*|q, p)
P(q∗,p∗∣q,p)非0即1:
P
(
q
∗
,
p
∗
∣
q
,
p
)
=
δ
(
q
∗
,
p
∗
,
q
,
p
)
=
{
1
,
T
L
ϵ
(
q
,
p
)
=
q
∗
,
p
∗
,
0
,
T
L
ϵ
(
q
,
p
)
≠
q
∗
,
p
∗
.
P(q^*, p^*|q, p) = \delta(q^*,p^*,q,p) = \left \{ \begin{array}{ll} 1, & T_{L\epsilon} (q, p) = q^*, p^*, \\ 0, & T_{L\epsilon} (q, p) \not = q^*, p^*. \end{array} \right.
P(q∗,p∗∣q,p)=δ(q∗,p∗,q,p)={1,0,TLϵ(q,p)=q∗,p∗,TLϵ(q,p)=q∗,p∗.
为了
P
(
q
∗
,
p
∗
∣
q
,
p
)
=
P
(
q
,
p
∣
q
∗
,
p
∗
)
P(q^*, p^*|q, p)=P(q, p|q^*, p^*)
P(q∗,p∗∣q,p)=P(q,p∣q∗,p∗), 如果不取反肯定不行, 因为他就会往下走, 取反的操作实际上就是在可逆性里提到的, 在同样的操作下,
q
∗
,
p
∗
q^*, p^*
q∗,p∗会回到
q
,
p
q, p
q,p. 于是MH接受概率就退化成了M接受概率. 但是前文也提到了, 取反的操作, 只有在
K
(
p
)
=
K
(
−
p
)
K(p)=K(-p)
K(p)=K(−p)的情况下是成立的.
HMC保持正则分布不变的证明 detailed balance
假设
{
A
k
}
\{A_k\}
{Ak}是
(
q
,
p
)
∈
R
2
d
(q, p) \in \mathbb{R}^{2d}
(q,p)∈R2d空间的一个分割, 其在L次leapfrog的作用, 及取反的操作下的像为
{
B
k
}
\{B_k\}
{Bk}, 由于可逆性,
{
B
k
}
\{B_k\}
{Bk}也是一个分割, 且有相同的体积
V
V
V(保体积性),则
P
(
A
i
)
T
(
B
j
∣
A
i
)
=
P
(
B
j
)
T
(
A
i
∣
B
j
)
.
P(A_i) T(B_j|A_i) = P(B_j)T(A_i|B_j).
P(Ai)T(Bj∣Ai)=P(Bj)T(Ai∣Bj).
实际上
i
≠
j
i\not =j
i=j是时候是显然的, 因为二者都是0. 因为
H
H
H是连续函数, 当
V
V
V变得很小的时候,
H
H
H在
X
X
X区域上的值相当于常数
H
X
H_X
HX, 于是
所以(3.7)成立.
Detailed balance:
其中
R
(
X
)
R(X)
R(X)是当前状态属于
X
X
X, 拒绝提议的
(
q
∗
,
p
∗
)
(q^*,p^*)
(q∗,p∗)的概率. 注意
∑
i
T
(
A
i
∣
B
k
)
=
T
(
A
k
∣
B
k
)
=
1
−
R
(
B
k
)
\sum_{i} T(A_i|B_k)=T(A_k|B_k)=1-R(B_k)
∑iT(Ai∣Bk)=T(Ak∣Bk)=1−R(Bk). 看上面的连等式可能会有点晕, 注意到, 左端实际上是概率
P
{
q
(
t
)
,
p
(
t
)
)
∈
B
k
}
P\{q^{(t)}, p^{(t)}) \in B_k\}
P{q(t),p(t))∈Bk}, 最右端是
P
{
(
q
(
t
−
1
)
,
p
(
t
−
1
)
)
∈
B
k
}
P\{(q^{(t-1)}, p^{(t-1)}) \in B_k\}
P{(q(t−1),p(t−1))∈Bk}, 这样就能明白啥意思了.
遍历性 Ergodicty
马氏链具有遍历性才会收敛到一个唯一的分布上(这部分不了解), HMC是具有这个性质的, 只要 L L L和 ϵ \epsilon ϵ选的足够好. 但是如果选的不过也会导致坏的结果, 比如上面的图, p 2 + q 2 = 1 p^2+q^2=1 p2+q2=1, 如果我们选择了 L ϵ ≈ 2 π L\epsilon \approx 2\pi Lϵ≈2π, 那么我们的Leapfrog总会带我们回到原点附近, 这就会导致比较差的结果.
HMC的一个例子及优势
下图是:
ϵ
=
0.25
,
L
=
30
,
q
=
[
−
1.5
,
−
1.55
]
T
,
p
=
[
−
1
,
1
T
]
\epsilon=0.25, L=30, q = [-1.5, -1.55]^T, p=[-1, 1^T]
ϵ=0.25,L=30,q=[−1.5,−1.55]T,p=[−1,1T].
相关系数由 0.95 0.95 0.95改为 0.98 0.98 0.98, ϵ = 0.18 , L = 20 \epsilon=0.18, L=20 ϵ=0.18,L=20, 随机游走取的协方差矩阵为对角阵, 标准差为 0.18 0.18 0.18, HMC生成 p p p的为标准正态分布.
文章中提到, HMC较Randomwalk的优势在于,Randomwalk对协方差很敏感, 而且太大会导致接受率很低, 太小俩俩之间的相关性又会太高.
HMC在实际中的应用和理论
线性变换
有些时候, 我们会对变量施加线性映射 q ′ = A q q'=Aq q′=Aq( A A A非奇异方阵), 此时新的密度函数 P ′ ( q ′ ) = P ( A − 1 q ′ ) / ∣ det ( A ) ∣ P'(q') = P(A^{-1}q') / |\det (A)| P′(q′)=P(A−1q′)/∣det(A)∣, 其中 P ( q ) P(q) P(q)是 q q q的密度函数, 相应的我们需要令 U ′ ( q ′ ) = U ( A − 1 q ′ ) U'(q')=U(A^{-1}q') U′(q′)=U(A−1q′).
如果我们希望线性变化前后不会是的情况变得"更糟", 一个选择是
p
′
=
(
A
T
)
−
1
p
p'=(A^T)^{-1}p
p′=(AT)−1p,则
K
′
(
p
′
)
=
K
(
A
T
p
′
)
K'(p')=K(A^Tp')
K′(p′)=K(ATp′), 如果
K
(
p
)
=
p
T
M
−
1
p
/
2
K(p) = p^TM^{-1}p / 2
K(p)=pTM−1p/2, 则
其中
M
′
=
(
A
M
−
1
A
T
)
−
1
=
(
A
−
1
)
T
M
A
−
1
M' = (AM^{-1}A^T)^{-1}=(A^{-1})^TMA^{-1}
M′=(AM−1AT)−1=(A−1)TMA−1. 此时
(
q
′
,
p
′
)
(q', p')
(q′,p′)的更新会使得原先的
(
q
,
p
)
(q,p)
(q,p)的更新保持, 即
所以
(
q
,
p
)
(q, p)
(q,p)本质上按照原来的轨迹发生着变化.
设想, 我们对 q q q的协方差矩阵有一个估计 Σ \Sigma Σ, 且近似服从高斯分布, 我们可以对其做Cholesky分解 Σ = L L T \Sigma=LL^T Σ=LLT, 并且令 q ′ = L − 1 q q'=L^{-1} q q′=L−1q, 则 q ′ q' q′的各分量之间就相互独立了, 那么我们很自然的一个选择是 K ( p ) = p T p / 2 K(p)=p^Tp/2 K(p)=pTp/2, 那么 q ′ q' q′的各分量的独立性能够保持.
另一个做法是, 保持
q
q
q不变, 但是
K
(
p
)
=
p
T
Σ
p
/
2
K(p) = p^T \Sigma p / 2
K(p)=pTΣp/2, 此时
q
′
=
L
−
1
q
,
p
′
=
(
L
T
)
−
1
p
q'=L^{-1}q, p'=(L^{T})^{-1}p
q′=L−1q,p′=(LT)−1p, 则相当于
K
(
p
′
)
=
(
p
′
)
T
M
′
−
1
p
′
,
M
′
=
(
L
−
1
L
L
T
(
L
−
1
)
T
)
−
1
=
I
.
K(p')=(p')^T{M'}^{-1}p', \quad M' = (L^{-1}LL^T(L^{-1})^T)^{-1}=I.
K(p′)=(p′)TM′−1p′,M′=(L−1LLT(L−1)T)−1=I.
所以俩个方法是等价的.
HMC的调整 ϵ , L \epsilon, L ϵ,L
HMC对 ϵ , L \epsilon, L ϵ,L的选择比较严苛.
预先的实验
我们可以对一些 ϵ , L \epsilon,L ϵ,L进行实验, 观察轨迹, 虽然这个做法可能产生误导, 另外在抽样过程中随机选择 ϵ , L \epsilon, L ϵ,L是一个不错的选择.
stepsize ϵ \epsilon ϵ
ϵ \epsilon ϵ的选择很关键, 如果太大, 会导致低的接受率, 如果太小, 不仅会造成大量的计算成本, 且如果此时 L L L也很小, 那么HMC会缺乏足够的探索.
考虑下面的例子:
每一次leapfrog将
(
q
(
t
)
,
p
(
t
)
)
(q(t), p(t))
(q(t),p(t))映射为
(
q
(
t
+
s
)
,
p
(
t
+
s
)
)
(q(t+s), p(t+s))
(q(t+s),p(t+s)), 则
(
q
,
p
)
(q, p)
(q,p)是否稳定, 关键在于系数矩阵的特征值的模(?还是实部)是否小于1, 特征值为
当
ϵ
>
2
σ
\epsilon>2\sigma
ϵ>2σ的时候,(4.6)有一个实的大于1的特征值, 当
ϵ
<
2
σ
\epsilon < 2 \sigma
ϵ<2σ的时候, 特征值是复制, 且模为:
所以, 我们应当选择
ϵ
<
2
σ
\epsilon < 2\sigma
ϵ<2σ.
在多维问题中, K ( p ) = p T p / 2 K(p)=p^Tp/2 K(p)=pTp/2,如果 q < 0 q<0 q<0且协方差矩阵为 Σ \Sigma Σ, 我们可以取协方差矩阵的最小特征值(非零?)作为步长. 如果 K ( p ) = p T M − 1 p / 2 K(p)=p^TM^{-1}p/2 K(p)=pTM−1p/2, 我们可以通过线性变化将其转换再考虑.
tracjectory length L L L
如何选择 L L L也是一个问题, 我们需要足够大的 L L L使得每次的探索的足够的, 以便能够模拟出独立的样本, 但是正如前面所讲, 大的 L L L不仅会带来计算成本, 而且可能会导致最后结果在起点附近(由周期性带来的麻烦). 而且 L L L没法通过轨迹图正确的选择. 一个不错的想法是在一个小的区间内随机选择 L L L, 这样做可能会减少由于周期性带来的麻烦.
多尺度
我们可以利用 q q q的缩放信息, 为不同的 q i q_i qi添加给予不同的 ϵ i \epsilon_i ϵi. 比方说在 K ( p ) = p T p / 2 K(p)=p^Tp/2 K(p)=pTp/2的前提下, 应该对 q i q_i qi放大 s i s_i si倍, 即 q ′ = q / s i q'= q / s_i q′=q/si( p p p不变).
等价的, 可以令
K
(
p
)
=
p
T
M
−
1
p
/
2
,
m
i
=
1
/
s
i
2
K(p) = p^TM^{-1}p / 2, m_i = 1/ s_i^2
K(p)=pTM−1p/2,mi=1/si2(
q
q
q不变), 相当于
q
i
′
=
q
i
/
s
i
,
p
′
=
s
i
p
q_i'=q_i/s_i, p'=s_ip
qi′=qi/si,p′=sip, 则
m
i
′
=
s
i
(
1
/
s
i
2
)
s
i
=
1
m_i' = s_i (1/ s_i^2)s_i=1
mi′=si(1/si2)si=1, 所以
K
(
p
′
)
=
(
p
′
)
T
p
′
/
2
K(p')=(p')^Tp'/2
K(p′)=(p′)Tp′/2. 这么做就相当于一次leapfrog为:
结合HMC与其它MCMC
当我们所关心的变量是离散的, 或者其对数概率密度( U ( q ) U(q) U(q))的导数难以计算的时候, 结合其它MCMC是有必要的.
Scaling with dimensionality
U ( q ) = ∑ u i ( q i ) U(q) = \sum u_i(q_i) U(q)=∑ui(qi)的情况
如果 U ( q ) = ∑ u i ( q i ) U(q)=\sum u_i(q_i) U(q)=∑ui(qi), 且 u i u_i ui之间相互独立(?), 这种假设是可行的, 因为之前已经讨论过, 对于 q q q其协方差矩阵为 Σ \Sigma Σ, 我们可以通过线性变化使其对角化, 且效能保持.
Cruetz指出, 任何的Metropolis形式的算法在采样密度函数
P
(
x
)
=
1
Z
exp
(
−
E
(
x
)
)
P(x)=\frac{1}{Z}\exp(-E(x))
P(x)=Z1exp(−E(x))的时候都满足:
其中
x
x
x表现在的状态, 而
x
∗
x^*
x∗表提议. 则根据Jensen不等式可知:
1
=
E
[
exp
(
Δ
)
]
≥
exp
(
E
[
−
Δ
]
)
,
1 = \mathbb{E}[\exp(\Delta)] \ge \exp(\mathbb{E}[-\Delta]),
1=E[exp(Δ)]≥exp(E[−Δ]),
所以
E
[
−
Δ
]
≤
0
\mathbb{E}[-\Delta]\le 0
E[−Δ]≤0,
E
[
Δ
]
≥
0.
(4.18)
\tag{4.18} \mathbb{E}[\Delta] \ge 0.
E[Δ]≥0.(4.18)
在 U ( q ) = ∑ u i ( q i ) U(q) = \sum u_i(q_i) U(q)=∑ui(qi)的情况下, 令 Δ 1 : = E ( x ∗ ) − E ( x ) \Delta_1:=E(x^*)-E(x) Δ1:=E(x∗)−E(x), x = q i , E ( x ) = u i ( q i ) x=q_i, E(x)=u_i(q_i) x=qi,E(x)=ui(qi)或者 x = ( q i , p i ) , E ( x ) = u i ( q i ) = p i 2 / 2 x=(q_i, p_i), E(x)=u_i(q_i)=p_i^2/2 x=(qi,pi),E(x)=ui(qi)=pi2/2. 对于整个状态, 我们则用 Δ d \Delta_d Δd表示, 则 Δ d \Delta_d Δd是所有 Δ 1 \Delta_1 Δ1的和. 既然 Δ \Delta Δ的平均值均为正, 这会导致接受概率 min ( 1 , exp ( − Δ d ) \min (1, \exp(-\Delta_d) min(1,exp(−Δd)的减小(随着维度的增加), 除非以减小步长作为代价, 或者建议分布的宽度进一步降低(即 x , x ∗ x,x^* x,x∗尽可能在一个区域内).
因为
exp
(
−
Δ
1
)
≈
1
−
Δ
1
+
Δ
1
2
/
2
\exp(-\Delta_1) \approx 1 -\Delta_1+\Delta_1^2 / 2
exp(−Δ1)≈1−Δ1+Δ12/2, 再根据(4.17)得:
E
[
Δ
1
]
≈
E
[
Δ
1
2
]
/
2.
(4.19)
\tag{4.19} \mathbb{E} [\Delta_1] \approx \mathbb{E} [\Delta_1^2]/2.
E[Δ1]≈E[Δ12]/2.(4.19)
故 Δ 1 \Delta_1 Δ1的方差约是均值的两倍( Δ 1 \Delta_1 Δ1足够小的时候), 类似的也作用与 Δ d \Delta_d Δd. 为了有一个比较好的接受率, 我们应当控制 Δ d \Delta_d Δd的均值在1左右(小于?), 此时 exp ( − 1 ) ≈ 0.3679 \exp(-1)\approx0.3679 exp(−1)≈0.3679.
HMC的全局误差(标准差)在 O ( ϵ 2 ) \mathcal{O}(\epsilon^2) O(ϵ2)级别, 所以 Δ 1 2 \Delta_1^2 Δ12应当在 ϵ 4 \epsilon^4 ϵ4级别, 所以 E [ Δ 1 ] \mathbb{E}[\Delta_1] E[Δ1]也应当在 ϵ 4 \epsilon^4 ϵ4级别, 则 E [ Δ d ] \mathbb{E}[\Delta_d] E[Δd]在 d ϵ 4 d\epsilon^4 dϵ4级别上, 所以为了保持均值为1左右, 我们需要令 ϵ \epsilon ϵ正比于 d − 1 / 4 d^{-1/4} d−1/4, 相应的 L L L为 d 1 / 4 d^{1/4} d1/4.
文章中还有关于Randomwalk的分析, 这里不多赘述了.
HMC的扩展和变种
这个不一一讲了, 提一下
分割
假如
H
H
H能够分解成:
那么我们可以一个一个来处理, 相当于
T
1
,
ϵ
∘
T
2
,
ϵ
,
∘
⋯
∘
T
k
−
1
,
ϵ
∘
T
k
,
ϵ
T_{1, \epsilon} \circ T_{2, \epsilon}, \circ \cdots \circ T_{k-1, \epsilon} \circ T_{k, \epsilon}
T1,ϵ∘T2,ϵ,∘⋯∘Tk−1,ϵ∘Tk,ϵ. 这个做法依旧是保体积的(既然每一个算子都是保体积的), 但是如果希望其可逆(对称), 这就要求
H
i
(
q
,
p
)
=
H
k
−
i
+
1
(
q
,
p
)
.
H_i(q, p)=H_{k-i+1}(q, p).
Hi(q,p)=Hk−i+1(q,p). 这个有很多应用场景:
比如
U
(
q
)
=
U
0
(
q
)
+
U
1
(
q
)
U(q) = U_0(q)+U_1(q)
U(q)=U0(q)+U1(q), 其中计算
U
0
U_0
U0如果是容易的, 我们可以作如下分解:
此时有
3
M
+
2
3M+2
3M+2项,
H
1
(
q
,
p
)
=
H
k
(
q
,
p
)
=
U
1
(
q
)
/
2
H_1(q, p) = H_k(q, p)=U_1(q)/2
H1(q,p)=Hk(q,p)=U1(q)/2,
H
3
i
−
1
=
H
3
i
+
1
=
U
0
(
q
)
/
2
M
H_{3i-1}=H_{3i+1}=U_0(q)/2M
H3i−1=H3i+1=U0(q)/2M,
H
3
i
=
K
(
p
)
/
M
H_{3i}=K(p)/M
H3i=K(p)/M. 此时对于中间部分, 相当于步长变小了,误差自然会小.
当处理大量数据, 并用到似然函数的时候:
不过文章中说这个分解是不对称的, 可明明是对称的啊.
处理约束
有些时候, 我们对 q q q有约束条件, 比方 q > v , q < w q >v, q<w q>v,q<w等等, 直接给算法:
Langevin method, LMC
假设我们使用
K
(
p
)
=
(
1
/
2
)
∑
p
i
2
K(p)=(1/2)\sum p_i^2
K(p)=(1/2)∑pi2,
p
p
p从标准正态分布中采样, 每次我们只进行一次leapfrog变计算接受概率, 即
以及其接受概率:
Windows of states
这个方法试图将 H H H的曲线平滑来提高接受率.
我们可以通过任意 ( q , p ) (q, p) (q,p)构造一列 [ ( q 0 , p 0 ) , … , ( q W − 1 , p W − 1 ) ] [(q_0, p_0), \ldots, (q_{W-1}, p_{W-1})] [(q0,p0),…,(qW−1,pW−1)]. 首先从 { 0 , 1 , … , W − 1 } \{0, 1, \ldots, W-1\} {0,1,…,W−1}中等概率选一个数, 这个数代表 ( q , p ) (q, p) (q,p)在序列中的位置, 记为 ( q s , p s ) (q_s, p_s) (qs,ps), 则其前面的可以通过leapfrog ( − ϵ -\epsilon −ϵ)产生, 后面的通过leapfrog( + ϵ +\epsilon +ϵ)产生. 所以任意列的概率密度为:
然后从
(
q
W
−
1
,
p
W
−
1
)
(q_{W-1}, p_{W-1})
(qW−1,pW−1)出发, 通过L-W+1步leapfrog(
+
ϵ
+\epsilon
+ϵ)获得
[
q
W
,
p
W
,
…
,
(
q
L
,
p
L
)
]
[q_W,p_W,\ldots, (q_L, p_L)]
[qW,pW,…,(qL,pL)]并定义提议序列为
[
(
q
L
,
−
p
L
)
,
…
,
(
q
L
−
W
+
1
,
p
L
−
W
+
1
)
]
[(q_L, -p_{L}), \ldots, (q_{L-W+1}, p_{L-W+1)}]
[(qL,−pL),…,(qL−W+1,pL−W+1)],计算接受概率:
其中
P
(
q
,
p
)
∝
exp
(
−
H
(
q
,
p
)
)
P(q, p)\propto \exp(-H(q,p))
P(q,p)∝exp(−H(q,p)). 设拒绝或者接受后的状态为:
[
(
q
0
+
,
p
0
+
)
,
…
,
(
q
W
−
1
+
,
p
W
−
1
+
)
]
[(q_0^+, p_0^+), \ldots, (q_{W-1}^+, p_{W-1}^+)]
[(q0+,p0+),…,(qW−1+,pW−1+)], 依照概率
抽取
(
q
e
+
,
p
e
+
)
(q_e^+, p_e^+)
(qe+,pe+), 这个就是
(
q
,
p
)
(q,p)
(q,p)后的下一个状态.
文中说这么做分布不变, 因为:
如果没理解错, 前面的部分就是
(
q
e
+
,
p
e
+
)
(q_e^+, p_e^+)
(qe+,pe+)出现在最开始的序列中的概率, 但是中间的接受概率哪里去了? 总不能百分百接受吧…
代码
import numpy as np
from collections.abc import Iterator, Callable
from scipy import stats
class Euler:
"""
Euler方法
"""
def __init__(self, grad_u, grad_k, epsilon):
self.grad_u = grad_u
self.grad_k = grad_k
self.epsilon = epsilon
def start(self, p, q, steps):
trajectory_p = [p]
trajectory_q = [q]
for t in range(steps):
temp = p - self.epsilon * self.grad_u(q) # 更新一步P
q = q + self.epsilon * self.grad_k(p) # 更新一步q
p = temp
trajectory_p.append(p)
trajectory_q.append(q)
return trajectory_p, trajectory_q
def modified_start(self, p, q, steps):
"""
启动!
:param p:
:param q:
:param steps: 步数
:return: p, q
"""
trajectory_p = [p]
trajectory_q = [q]
for t in range(steps):
p = p - self.epsilon * self.grad_u(q) #更新一步P
q = q + self.epsilon * self.grad_k(p) #更新一步q
trajectory_p.append(p)
trajectory_q.append(q)
return trajectory_p, trajectory_q
class Leapfrog:
"""
Leapfrog 方法
"""
def __init__(self, grad_u, grad_k, epsilon):
self.grad_u = grad_u
self.grad_k = grad_k
self.epsilon = epsilon
self.trajectory_q = []
self.trajectory_p = []
def start(self, p, q, steps):
self.trajectory_p.append(p)
self.trajectory_q.append(q)
for t in range(steps):
p = p - self.epsilon * self.grad_u(q) / 2
q = q + self.epsilon * self.grad_k(p)
p = p - self.epsilon * self.grad_u(q) / 2
self.trajectory_q.append(q)
self.trajectory_p.append(p)
return p, q
class HMC:
"""
HMC方法
start为进行一次
accept_prob: 计算接受概率
hmc: 完整的过程
acc_rate: 接受概率
"""
def __init__(self, grad_u, grad_k, hamiltonian, epsilon):
assert isinstance(grad_u, Callable), "function needed..."
assert isinstance(grad_k, Callable), "function needed..."
assert isinstance(hamiltonian, Callable), "function needed..."
self.grad_u = grad_u
self.grad_k = grad_k
self.hamiltonian = hamiltonian
self.epsilon = epsilon
self.trajectory_q = []
self.trajectory_p = []
def start(self, p, q, steps):
self.trajectory_p.append(p)
self.trajectory_q.append(q)
p = p - self.epsilon * self.grad_u(q) / 2
for t in range(steps-1):
q = q + self.epsilon * self.grad_k(p)
p = p - self.epsilon * self.grad_u(q)
q = q + self.epsilon * self.grad_k(p)
p = p - self.epsilon * self.grad_u(q) / 2
p = -p
return p, q
def accept_prob(self, p1, q1, p2, q2):
"""
:param p1: 原先的
:param q1:
:param p2: 建议的
:param q2:
:return:
"""
p1 = np.exp(self.hamiltonian(p1, q1))
p2 = np.exp(self.hamiltonian(p2, q2))
alpha = min(1, p1 / p2)
return alpha
def hmc(self, generate_p, q, iterations, steps):
assert isinstance(generate_p, Iterator), "Invalid generate_p"
self.trajectory_q = [q]
p = next(generate_p)
self.trajectory_p = [p]
count = 0.
for t in range(iterations):
tempp, tempq = self.start(p, q, steps)
if np.random.rand() < self.accept_prob(p, q, tempp, tempq):
p = tempp
q = tempq
self.trajectory_p.append(p)
self.trajectory_q.append(q)
count += 1
p = next(generate_p)
self.acc_rate = count / iterations
return self.trajectory
@property
def trajectory(self):
return np.array(self.trajectory_p), \
np.array(self.trajectory_q)
class Randomwalk:
"""
walk: 完整的过程, 实际上Metropolis更新似乎就是start中steps=1,
一开始将文章的意思理解错了, 不过将错就错, 这样子也能增加一下灵活性.
"""
def __init__(self, pdf, sigma):
assert isinstance(pdf, Callable), "function needed..."
self.pdf = pdf
self.sigma = sigma
self.trajectory = []
def start(self, q, steps=1):
for t in range(steps):
q = stats.multivariate_normal.rvs(mean=q,
cov=self.sigma)
return q
def accept_prob(self, q1, q2):
"""
:param q1: 原始
:param q2: 建议
:return:
"""
p1 = self.pdf(q1)
p2 = self.pdf(q2)
alpha = min(1, p2 / p1)
return alpha
def walk(self, q, iterations, steps=1):
self.trajectory = [q]
count = 0.
for t in range(iterations):
temp = self.start(q, steps)
if np.random.rand() < self.accept_prob(q, temp):
q = temp
count += 1
self.trajectory.append(q)
self.acc_rate = count / iterations
return np.array(self.trajectory)