贝叶斯优化

[1]崔佳旭,杨博.贝叶斯优化方法和应用综述.软件学报,2018,29(10):3068-3090. http://www.jos.org.cn/1000-9825/5607.htm

[2]Bobak Shahriari, Kevin Swersky,Ziyu Wang, Ryan PAdams, and Nando de Freitas. 2016. Taking the human out of the loop: A review of bayesian optimization. Proc. IEEE 104,1(2016),148–175.

简介

贝叶斯优化-marsggbo

首先,贝叶斯优化能干什么?给我的感觉是无所不能,当然其效果有些可能不尽如人意。贝叶斯优化,可以做回归的东西(虽然总感觉这个东西只是一个附属品),然而主要是去解决一个“优化问题”。
贝叶斯优化解决的是下面类型的问题:
x ∗ = a r g m a x x ∈ X f ( x ) \mathrm{x^{*}}=\mathop{argmax}\limits_{\mathrm{x}\in \mathcal{X}}f(\mathrm{x}) x=xXargmaxf(x)
注: 使用"argmin"并无实质上的不同,事实上[1]中采用的便是"argmin"。
往往, f f f我们并不知道,所以,这类问题很难采用经典的梯度上升("argmin"则梯度下降)来解决。贝叶斯优化采用概率代理模型来应对。 x \mathrm{x} x是决策,往往称 X \mathcal{X} X为决策空间。药物配方是一种决策,神经网络卷积核大小等也可以看成一种决策。而且,这种决策与最后的输出的关系(即 f f f)往往很难知晓。这也正是贝叶斯优化的强大之处。

贝叶斯优化框架

贝叶斯优化框架[2]
贝叶斯优化框架[1]

上面俩幅图分别来自[2]和[1],因为一些符号的差异,往下除特别指明,采用的均为[2]中的符号。
贝叶斯优化,每一次迭代,首先在代理模型的“先验”下,通过最大化采集函数(该函数往往是对评估点的分布以及 f ( x ) f(x) f(x)的提升的一种权衡(trade-off))。新的评估点,作为输入传入系统,获得新的输出,以此来更新 D D D和概率代理模型。
其中 D t = { ( x 1 , y 1 ) , … , ( x t , y t ) } D_t=\{(\mathrm{x_1}, y_1), \ldots, (\mathrm{x_t},y_t)\} Dt={(x1,y1),,(xt,yt)}
贝叶斯优化示例

上面这幅图,便是贝叶斯优化的一个简单演示。黑色虚线表示目标函数 f f f,而黑色实线表示我们拟合的曲线(图中是通过对概率代理模型求均值获得的)。蓝紫色区域是 μ ( ⋅ ) ± σ ( ⋅ ) \mu(\cdot)\pm \sigma(\cdot) μ()±σ()。下方的绿色曲线则是每一次迭代的 α ( ⋅ ) \alpha(\cdot) α(),可以看出,每一次迭代选出的评估点都是 α ( ⋅ ) \alpha(\cdot) α()最大值所对应的 x \mathrm{x} x

下面,我们分别来讨论概率代理模型,以及采集函数。

概率代理模型

概率代理模型,顾名思义,就是用来代理 f ( ⋅ ) f(\cdot) f()的一个概率模型。

参数模型

参数模型,即 f ( ⋅ ) f(\cdot) f()可由参数 w \mathrm{w} w来决定。如果我们给定 w \mathrm{w} w的先验分布 p ( w ) p(\mathrm{w}) p(w)。那么,通过贝叶斯公式,我们可以获得 w \mathrm{w} w的后验分布:
p ( w ∣ D ) = p ( D ∣ w ) p ( w ) p ( D ) p(\mathrm{w}|D)=\frac{p(D|\mathrm{w})p(\mathrm{w})}{p(D)} p(wD)=p(D)p(Dw)p(w)
现在问题来呢,我们还不知道 p ( D ∣ w ) p(D|\mathrm{w}) p(Dw) p ( D ) p(D) p(D)啊。 p ( D ∣ w ) p(D|w) p(Dw)是一个似然分布,往往通过 ∏ p ( ( x i , y i ) ∣ w ) \prod p((\mathrm{x}_i,y_i)|\mathrm{w}) p((xi,yi)w)来计算,当然,我们得知道 p ( ( x i , i i ) ∣ w ) p((\mathrm{x}_i, i_i)|\mathrm{w}) p((xi,ii)w)。至于 p ( D ) p(D) p(D),比较难计算,但是, p ( D ) p(D) p(D)在这里只是扮演了系数的作用,所以用核方法就能解决。事实上,我们常常选择共轭先验分布作为 w \mathrm{w} w的先验分布。

汤普森采样和Beta-Bernouli模型

这里给出一个例子:实验室有K种药,我们需要通过药物实验来找出哪种药的效果最好。假设,药作用在某个病人身上只有成功治愈和失败俩种可能,且不能通过一种药的效果来判断另外一种药的疗效。这种类型的问题似乎被称为A/B测试,常用于新闻推荐等。
我们用 a ∈ 1 … K a \in 1 \ldots K a1K来表示药物, w a w_a wa表示第 a a a种药物成功治愈病患的可能性,而 y i ∈ { 0 , 1 } y_i \in \{0, 1\} yi{0,1}则表示病人 i i i的治疗情况(0失败,1治愈)。函数 f ( ⋅ ) f(\cdot) f()就是某种复杂的映射。让参数 w ∈ ( 0 , 1 ) K \mathrm{w} \in (0, 1)^{K} w(0,1)K w a = w a \mathrm{w}_a=w_a wa=wa。那么我们选择的概率代理模型是 f w ( a ) : = w a f_\mathrm{w}(a):=w_a fw(a):=wa
我们选择 B e t a \mathrm{Beta} Beta分布作为 w \mathrm{w} w的先验分布,因为这是其共轭先验分布。
p ( w ∣ α , β ) = ∏ a = 1 K B e t a ( w a ∣ α , β ) p(\mathrm{w}|\alpha, \beta)=\prod \limits_{a=1}^{K}\mathrm{Beta}(w_a|\alpha, \beta) p(wα,β)=a=1KBeta(waα,β)
定义:
n a , 0 = ∑ i = 1 n I ( y i = 0 , a i = a ) n a , 1 = ∑ i = 1 n I ( y i = 1 , a i = a ) \begin{array}{ll} n_{a,0}=\sum \limits_{i=1}^{n}\mathbb{I}(y_i=0, a_i=a)\\ n_{a,1}=\sum \limits_{i=1}^{n}\mathbb{I}(y_i=1, a_i=a) \end{array} na,0=i=1nI(yi=0,ai=a)na,1=i=1nI(yi=1,ai=a)
其中 n a , 0 n_{a,0} na,0表示 n n n次评估中,选中 a a a药物且治疗失败的数目, n a , 1 n_{a,1} na,1则反之。 I ( ⋅ ) \mathbb{I}(\cdot) I()只有 ( ⋅ ) (\cdot) ()成立为1否则为0。
那么, w \mathrm{w} w的后验概率为:
p ( w ∣ D ) = ∏ a = 1 K B e t a ( w a ∣ α + n a , 1 , β + n a , 0 ) p(\mathrm{w}|D)=\prod \limits_{a=1}^{K} \mathrm{Beta}(w_a|\alpha+n_{a,1}, \beta+n_{a,0}) p(wD)=a=1KBeta(waα+na,1,β+na,0)
上述推导见附录。
从上述也能发现,超参数 α , β \alpha, \beta α,β表示的治愈数和失败数。下图是以 B e t a ( w ∣ 2 , 2 ) \mathrm{Beta}(w|2,2) Beta(w2,2)为先验的一个例子。
image.png

汤普森采样-wiki
那么在 D n D_n Dn的基础上,如果找 a n + 1 a_{n+1} an+1呢。以下采用的是汤普森采样(或后验采样):
α n + 1 = a r g m a x a f w ~ ( a ) \alpha_{n+1}=\mathop{argmax}\limits_{a} f_{\widetilde{\mathrm{w}}}(a) αn+1=aargmaxfw (a)
w ~ ∼ p ( w ∣ D n ) \widetilde{\mathrm{w}}\sim p(\mathrm{w}|D_n) w p(wDn),即 w ~ \widetilde{\mathrm{w}} w w \mathrm{w} w的后验分布中采样得到。
该模型的好处是:

  • 只有 α , β \alpha,\beta α,β俩个超参数
  • 是对exploration和exploitation的一种比较好的权衡
  • 比较容易和蒙特卡洛采样-HFUT_qianyang结合
  • 汤普森采样的随机性使其容易推广到批量处理(不懂)

下面是该模型的算法:
Beta-Bernouli

线性模型(Linear models)

上述的模型在应对组合类型的时候会显得捉襟见肘。比方,我们在从 d d d个元素中寻求一种搭配,每个元素有 { 0 , 1 } \{0, 1\} {0,1}俩种状态,那么总共就有 2 K 2^K 2K种组合,如果为每种组合都设立一个 w w w,显然不切实际。更何况,先前模型的假设(无法从一种组合推断另外一种组合的有效性)显得站不住脚。因为,不同组合往往有微妙的相关性。
采用线性模型,能比较好的解决这一问题。
我们把每一种策略设为 x a ∈ R d \mathrm{x}_a \in \mathbb{R}^{d} xaRd,并且概率代理模型为 f w ( a ) = x a T w f_{\mathrm{w}}(a)=\mathrm{x}_a^{\mathrm{T}}\mathrm{w} fw(a)=xaTw,现在 w \mathrm{w} w成了权重向量。这只是代理模型的一部分,因为并没有体现“概率”的部分。
y a ∼ N ( x a T w , σ 2 ) y_a \sim N(\mathrm{x}_a^{\mathrm{T}}\mathrm{w}, \sigma^2) yaN(xaTw,σ2)
组合 a a a的观测值为 y a y_a ya,服从正态分布。很自然地,我们同样选择共轭先验分布作为 w , σ 2 \mathrm{w}, \sigma^2 w,σ2的先验分布:normal_inverse_gamma-wiki
N I G ( w , σ 2 ∣ w 0 , V 0 , α 0 , β 0 ) = ∣ 2 π σ 2 V 0 ∣ − 1 2 e x p { − 1 2 σ 2 ( w − w 0 ) T V 0 − 1 ( w − w 0 ) } × β 0 α 0 Γ ( α 0 ) ( σ 2 ) α + 1 e x p { − β 0 σ 2 } \begin{array}{l} \mathrm{NIG}(\mathrm{w}, \sigma^2|\mathrm{w}_0,V_0,\alpha_0,\beta_0)=\\ |2\pi \sigma^2 V_0|^{-\frac{1}{2}}\mathrm{exp}\{-\frac{1}{2\sigma^2}(\mathrm{w-w_0})^\mathrm{T}V_0^{-1}(\mathrm{w-w_0})\} \times \frac{\beta_0^{\alpha_0}}{\Gamma(\alpha_0)(\sigma^2)^{\alpha + 1}}\mathrm{exp}\{-\frac{\beta_0}{\sigma^2}\} \end{array} NIG(w,σ2w0,V0,α0,β0)=2πσ2V021exp{2σ21(ww0)TV01(ww0)}×Γ(α0)(σ2)α+1β0α0exp{σ2β0}
N I G \mathrm{NIG} NIG分布有4个超参数,而 w , σ 2 \mathrm{w}, \sigma^2 w,σ2的后验分布( D n D_n Dn的条件下)满足:
image.png

其中 X \mathrm{X} X的第 i i i行为 x α i \mathrm{x}_{\alpha_i} xαi
推导见附录。

关于 α n + 1 \alpha_{n+1} αn+1的选择,同样可以采用汤普森采样:
α n + 1 = a r g m a x a x a T w ~ \alpha_{n+1}=\mathop{argmax}\limits_{a} \mathrm{x}_a^{\mathrm{T}}\widetilde{\mathrm{w}} αn+1=aargmaxxaTw
其中 w ~ ∼ p ( w ∣ D n ) \widetilde{\mathrm{w}} \sim p(\mathrm{w}|D_n) w p(wDn)

线性模型有很多扩展:
f ( x ) = Φ ( x ) T w f(x)=\Phi(\mathrm{x})^{\mathrm{T}}\mathrm{w} f(x)=Φ(x)Tw
f ( x ) = g ( x T w ) f(x)=g(\mathrm{x^{T}w}) f(x)=g(xTw)

其中, Φ ( x ) = ( ϕ 1 ( x ) , … , ϕ J ( x ) ) T \Phi(\mathrm{x})=(\phi_1(\mathrm{x}),\ldots,\phi_J(\mathrm{x}))^{\mathrm{T}} Φ(x)=(ϕ1(x),,ϕJ(x))T ϕ j ( x ) \phi_j(\mathrm{x}) ϕj(x)常常为:
e x p { − ( x − z j ) T Λ ( x − z j ) 2 } \mathrm{exp}\{ -\frac{(\mathrm{x-z_j})^{\mathrm{T}}\Lambda(\mathrm{x-z_j})}{2} \} exp{2(xzj)TΛ(xzj)}

e x p { − i x T w j } \mathrm{exp}\{ -i\mathrm{x^T}w_j\} exp{ixTwj}
这里, Λ \Lambda Λ { z j } j = 1 J \{\mathrm{z}_j \}_{j=1}^{J} {zj}j=1J { w j } j = 1 J \{ w_j\}_{j=1}^{J} {wj}j=1J均为超参数,至于这些超参数怎么更新,我不大清楚。

非参数模型

非参数模型不是指没有参数,而是指参数(数量)不定。

我们先来看如何把先前的线性模型转换成非参数模型。
我们假设 σ 2 \sigma^2 σ2是固定的,且 p ( w ∣ V 0 ) = N ( 0 , V 0 ) p(\mathrm{w}|V_0)=\mathcal{N}(0,V_0) p(wV0)=N(0,V0),即服从均值为 0 0 0,协方差矩阵为 V 0 V_0 V0的多维正态分布。那么, y ∼ N ( X w , σ 2 I ) y\sim \mathcal{N}(\mathrm{Xw},\sigma^2\mathrm{I}) yN(Xw,σ2I),我们可以积分掉 w \mathrm{w} w从而获得 y y y的一个边际分布:
边际分布

推导见附录。
就像先前已经提到过的,我们可以引入 Φ = ( ϕ i , … , ϕ J ) T \Phi = (\phi_i,\ldots,\phi_J)^{T} Φ=(ϕi,,ϕJ)T,
将资料(设计)矩阵 X X X映射到 R n × J \mathbb{R}^{n\times J} Rn×J,如此一来,相应的边际分布也需发生变化:
映射后的边际分布

注意到 Φ V 0 Φ T \Phi V_0 \Phi^{T} ΦV0ΦT,事实上,我们不需要特别指明 Φ \Phi Φ,而只需通过kernel.
kernel
K K K将是 Φ V 0 Φ T \Phi V_0 \Phi^{T} ΦV0ΦT的一个替代。采用这个策略,比原先在计算上和可解释性上更有优势。
不过,还有另外一个问题,如果去寻找下一个评估点呢。寻找下一个评估点,需要我们做预测,但是上面的边际分布显然是无法进行预测的。不过,我们可以通过条件公式来获得:
image.png

X ∗ \mathrm{X}_{*} X是新的位置,而 y ∗ y_{*} y是相应的预测,二者都可以是向量。
分子部分是一个联合的高斯分布。到此,我们实际上完成了一个简易的高斯过程,下面正式介绍高斯过程。

高斯过程

高斯过程-wiki
高斯过程-火星十一郎

高斯过程 f ( x ) ∼ G P ( μ 0 , k ) f(\mathrm{x}) \sim GP(\mu_0,k) f(x)GP(μ0,k),其核心便是均值函数 μ 0 \mu_0 μ0(在贝叶斯优化中,我们常常选择其为0)和协方差函数 k ( x i , x j ) k(\mathrm{x}_i,\mathrm{x}_j) k(xi,xj),而观测值 y = f + ε y=f+\varepsilon y=f+ε。通过高斯过程得到的序列 f 1 : n f_{1:n} f1:n,以及观测值 y 1 : n y_{1:n} y1:n都服从联合正态分布:
image.png
其中 m i : = μ 0 ( x i ) , K i , j : = k ( x i , x j ) m_i := \mu_0(\mathrm{x}_i),K_{i,j}:=k(\mathrm{x}_i, \mathrm{x}_j) mi:=μ0(xi),Ki,j:=k(xi,xj), σ 2 \sigma^2 σ2是随机变量 ε \varepsilon ε的方差。
于是,我们可以像之前所做的那样,求边际分布,和 y ∗ y_* y的分布。
首先,
p ( y ∣ X , σ 2 ) = N ( y ∣ m , K + σ 2 I ) p(y|\mathrm{X}, \sigma^2) = \mathcal{N}(y|m, K+\sigma^2\mathrm{I}) p(yX,σ2)=N(ym,K+σ2I)
我们并没有给出这个证明,因为这个不难验证。接下来,为了预测,我们需要求后验分布。论文此时并没有选择 y ∗ y_* y,而是 f ∗ f_* f的后验分布,这点倒是可以理解,比较我们的目标就是最大化 f ( x ) f(\mathrm{x}) f(x)。不过,论文给出的是标量(也就是只有一个预测值),实际上,很容易扩展到多个,在附录里,我们给出多个的后验分布的推导。
我们先给出一个的后验分布,依旧是正态分布:
image.png

常用的一些kernels

Kernel method - wiki
Matern covariance function - wiki

文献[1]给出的形式如下(实际上是 d = 1 d=1 d=1的情况):
image.png

其中, r = ∣ x − x ′ ∣ r=|x-x'| r=xx v v v为平滑参数, l l l为尺度参数, K v K_v Kv为第二类变形贝塞尔函数
同时给出了几种常用的Matern协方差函数。
文献[1].png

文献[2]给出的是另外一种表示方式:
文献[2].png

其中, r 2 = ( x − x ′ ) T Λ ( x − x ′ ) r^2=\mathrm{(x-x')^{T}\Lambda(\mathrm{x-x'})} r2=(xx)TΛ(xx) Λ \Lambda Λ是一个对角矩阵,其对角线元素为 θ i 2 , i = 1 , … , d \theta_i^2,i=1,\ldots,d θi2,i=1,,d

这些参数可以这么理解:

  • v v v,被称为平滑参数,因为,从使用Matern协方差函数的高斯过程中采样的目标函数 f ( x ) f(x) f(x) ⌊ v − 1 ⌋ \lfloor v-1 \rfloor v1次均方可微的(为什么?)。
  • l l l θ \theta θ的功能相似,反映该维度的重要性(前者是越小越重要,后者越大越重要)。

image.png

上面的一些参数,会在下面给出一些更新的方法。

边际似然

log 边际似然函数可以表示为:

image.png

从图中可以看到,等式右边被分成了三部分,三者有不同含义:

  • 第一项,表示模型和数据的拟合程度的好坏,以马氏距离为指标;
  • 第二项,表示模型的复杂度;
  • 第三项,是数据点 n n n的线性函数,表示数据的不确定性随着数据增大而减少(?)。

一个非常自然的想法是,对上述似然函数进行极大似然估计,从而获得 θ : = ( θ 0 : d , μ 0 , σ 2 ) \theta:=(\theta_{0:d},\mu_0,\sigma^2) θ:=(θ0:d,μ0,σ2)的估计。

复杂度

每一次高斯过程的复杂度在 O ( n 3 ) O(n^3) O(n3)级别左右,这是由计算矩阵的逆所带来的。通过Cholesky分解,可以降为 O ( n 2 ) O(n^2) O(n2)
所以产生了一些算法,试图克服这个困难。

sparse pseudo-input Gaussian processes (SPGP)

SPGP从n个输入中选择m个伪输入替代,从而达到降秩的目的。同时,这m个伪输入的位置也作为参数(虽然我不知道怎么去更新)。好处自然是,
能够把复杂度降为 0 ( n m 2 + m 3 ) 0(nm^2+m^3) 0(nm2+m3)。缺点是,参数相对比较多,容易产生“过拟合”现象。

Sparse spectrum Gaussian processes(SSGP)

由Bochner定理得,任何稳定得kernel都有一个正定得傅里叶谱表示:
image.png

之后,通过蒙特卡洛方法,采样m个样本频率,来近似估计上诉的积分。从而获得近似的协方差函数,当数据集较小时,SSGP同样易产生“过拟合”现象。

随机森林

随机森林 - Poll的笔记

随机森林可以作为高斯过程的一种替代。缺点是,数据缺少的地方,估计的并不准确(边际更是常数)。另外,由于随机森林不连续,也就不可微,所以无法采用梯度下降(或上升)的方法来更新参数。另外不解的是,随机森林的参数,即便我们给了一个先验分布,可其后验分布如何求呢?

image.png

采集函数

首先我们有一个效用函数 U : R d × R × Θ → R U:\mathbb{R}^d \times \mathbb{R} \times \Theta \rightarrow \mathbb{R} U:Rd×R×ΘR,顾名思义,效用函数,是反映评估 x \mathrm{x} x和对应的函数值 v = f ( x ) v=f(\mathrm{x}) v=f(x)(在 θ \theta θ条件下)的一个指标。论文[1]并没有引入这个效用函数,论文[2]引入这个概念应该是为了更好的说明。

一种采集函数的选择,便是期望效用:
image.png

其实蛮奇怪的,因为对 v v v求期望也就罢了,这个采集函数对 θ \theta θ也求了期望,我的理解是,这样子更加“模糊”了,如果选择极大似然等方式产出的“精准”的 θ \theta θ,或许不能够很好的让评估点足够分散,而陷入局部最优。而且,这样子做,似乎就没有必要去估计参数 θ \theta θ,虽然代价是求期望。

从下面的一些算法中我们可以看到,往往没有 E θ ( ⋅ ) \mathbb{E}_{\theta}(\cdot) Eθ()这一步骤。

最后再次声明,采集函数的设计,往往都是对exploration和exploitation的一种权衡。即,我们希望新的评估点 x \mathrm{x} x既要和原来的那些数据点远一些(对未知区域的探索),又能够让 f ( x ) f(\mathrm{x}) f(x)能够提升(对当前区域的开发探索)。

基于提升的策略

PI (probability of improvement)

PI的采集函数的设计思想很简单,就是我们要寻找一个评估点 x \mathrm{x} x,这个 x \mathrm{x} x使得 v = f ( x ) v=f(\mathrm{x}) v=f(x)较已知的最大的(如果一开始是argmin就是最小的) f ( x ) f(\mathrm{x}) f(x),令其为 τ \tau τ。往往, τ = min ⁡ x ∈ X f ( x ) \tau=\min_{\mathrm{x\in X}} f(\mathrm{x}) τ=minxXf(x)
采集函数为:

image.png

注意,这里的 Φ \Phi Φ是标准正态分布的概率函数。
这个采集函数里的效用函数是:
U ( x , v , θ ) = I [ v > τ ] U(\mathrm{x}, v, \theta)=\mathbb{I}[v>\tau] U(x,v,θ)=I[v>τ]
其中 I \mathbb{I} I为指示函数。
τ \tau τ就是 f ( x ) f(\mathrm{x}) f(x)的最小值时,PI的效果非常好。
PI一个“弊端”是,只在乎提升的概率,而在乎提升的幅度,而,EI就涵盖了这俩方面。

EI(expected improvement)

通常,其提升函数由下式表示:
image.png

而相应的的采集函数是:

image.png

其中 ϕ \phi ϕ是标准正态分布的概率密度函数。式子通过积分变量替换可以推得。
实际上 I I I就是效用函数 U U U

UCB(upper confidence bound)

采集函数为:
image.png

这个采集函数,可以这么理解,对于任意一个 x \mathrm{x} x,它有一个均值 μ n ( x ) \mu_n (\mathrm{x}) μn(x),有一个标准差 σ n ( x ) \sigma_n(\mathrm{x}) σn(x)(体现浮动范围和程度), β n σ n ( x ) \beta_n\sigma_n(\mathrm{x}) βnσn(x)我们认为比较可靠的界,我们认为, f ( x ) f(\mathrm{x}) f(x)有较大可能达到 μ n ( x ) + β n σ n ( x ) \mu_n(\mathrm{x})+\beta_n\sigma_n(\mathrm{x}) μn(x)+βnσn(x)的值。所以最大化采集函数,就是最大化我们的这一种希望。
论文[2]中说 β \beta β的选择往往是Chernoff-Hoeffding界。听起来很玄乎,但是,UCB现在貌似非常火。另外,有一套理论,能够引导和规划超参数 β n \beta_n βn,使得能够达到最优。

基于信息的策略

不同之前的策略,基于信息的策略,依赖全局最优解 x ∗ \mathrm{x}^* x的后验分布 p ∗ ( x ∣ D n ) p_*(\mathrm{x}|D_n) p(xDn)。该分布,隐含在函数 f f f的后验分布里(不同的 f f f有不同的全局最优解,从而 x ∗ \mathrm{x}^* x也有一个后验分布)。

熵搜索算法旨在寻找能够极大减少不确定度的评估点 x ∗ \mathrm{x}^* x,从另外一个角度来说, x ∗ \mathrm{x}^* x给与了我们最多的信息。

因此效用函数为:

ES效用函数.png

此时的采集函数为:

ES采集函数.png

其中 H ( x ∗ ∣ D n ) = ∫ p ( x ∗ ∣ D n ) log ⁡ p ( x ∗ ∣ D n ) d x ∗ H(\mathrm{x^*|D_n})=\int p(\mathrm{x^*|D_n})\log p(\mathrm{x^*}|D_n)d\mathrm{x^*} H(xDn)=p(xDn)logp(xDn)dx代表微分熵, y ∼ N ( μ n ( x ) , σ n 2 ( x ) + σ 2 ) y \sim \mathcal{N}(\mu_n(\mathrm{x}), \sigma^2_n(\mathrm{x})+\sigma^2) yN(μn(x),σn2(x)+σ2)
不过,估计 p ( x ∗ ∣ D n ) p(\mathrm{x*}|D_n) p(xDn)或者 H H H都绝非易事,计算量也让人望而却步。

一种新的方法PES(predictive entropy search)很好地改善了这些问题。
利用互信息的对称性(不懂),我们可以将 α E S ( x ) \alpha_{ES}(\mathrm{x}) αES(x)改写为:
image.png

使得我们不必苦于 p ( x ∗ ∣ D n ) p(\mathrm{x^*}|D_n) p(xDn)上。

采集函数的组合

不同采集函数的组合或许能够达到更好的特性。
一种方案是,不同采集函数会给出一系列最优评估点的候选。通过一个准则来判断孰优孰劣。
ESP(entropy search portfolio)采用的准则如下:

image.png

即选择那个让不确定性最小的候选点。

出于实际的考量

处理超参数

处理(优化)超参数一般有如下的策略:

  • 通过 y y y的边际分布,进行极大似然估计,获得 θ ^ n M L \hat{\theta}_n^{ML} θ^nML
  • 给参数 θ \theta θ一个先验分布 p ( θ ) p(\theta) p(θ),通过贝叶斯公式获得其后验分布 p ( θ ∣ D n ) p(\theta | D_n) p(θDn),可得最大后验估计 θ ^ n M A P \hat{\theta}_n^{MAP} θ^nMAP
  • 同样用到后验分布 p ( θ ∣ D n ) p(\theta|D_n) p(θDn),对 θ \theta θ进行边际化处理:
    α n ( x ) = E θ α ( x ; θ ) = ∫ p ( θ ∣ D n ) α ( x ; θ ) d θ \alpha_n(\mathrm{x}) = \mathbb{E}_{\theta} \alpha(\mathrm{x};\theta)=\int p(\theta|D_n)\alpha (\mathrm{x};\theta)\mathrm{d} \theta αn(x)=Eθα(x;θ)=p(θDn)α(x;θ)dθ 这部分不必再估计参数 θ \theta θ,代价是需要估计一个期望,这项工作有不同的方案:蒙特卡洛技术,贝叶斯蒙特卡洛技术等。

采集函数的优化

实际上,采集函数的优化并不简单,因为其往往非凸。有基于梯度的方法(如果可微的话),还有网格搜索,自适应协方差矩阵进化策略,多启动局部搜索等。
最近还流行用空间切分的方法替代贝叶斯模型,如SOO(simultaneous optimistic optimization)。在有可用的先验知识时,这类方法比不上贝叶斯优化有效,BamSOO(Bayesian multi-scale SOO)算法结合贝叶斯和树切分空间,有很好的效果。

数值实验

Beta-Bernoulli

我们准备了8枚药丸,治疗概率分别0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8。进行80次试验,每次试验治疗3个无差别病患。下图是一个例子:

Beta-Bernouli

再下面的例子是,每次试验不选择药丸,统统进行试验:
Beta-Bernouli

高斯过程

选择最简单的一维高斯过程,超参数有 θ 0 , θ 1 , σ \theta_0, \theta_1, \sigma θ0,θ1,σ,选择的kernel为 θ 0 2 e x p { − 1 2 r 2 } \theta_0^2 exp\{-\frac{1}{2}r^2 \} θ02exp{21r2},采集函数为 E I EI EI。优化超参数使用梯度下降(因为别的方法不怎么会),优化采集函数使用的是网格搜索。另外,我们给输出附加了方差为0.0001(基本上没有)的白噪声。

采用[1]中的例子:
image.png

首先,是在我们不知道 τ \tau τ的情况下,我们取初始值0.1,0.2, 0.4,0.5,0.7,0.9.,上面的图是选取11个点后的均值函数,下面的是真实的曲线,上面的点是每次选取的点。

0.1

0.1

0.2

0.2

0.4

0.4

0.5

0.5

0.9

0.7

0.9

0.9

接下来,我们固定 τ = − 0.2 \tau=-0.2 τ=0.2

0.1

0.1

0.4

0.4

0.9

0.9

最后再来一个加入方差为0.0025白噪声的 τ = − 0.2 \tau=-0.2 τ=0.2和未知的的:

0.4 已知

0.4 已知

0.4 未知

0.4 未知

代码


# Beta-Bernouli

import numpy as np
import scipy.stats



class Pill:
    """模拟药丸

    >>> p = Pill(0.5, -1, 1)
    Traceback (most recent call last):
    ...
    AssertionError: -1 is not positive
    >>> p = Pill(0.5, 1, 0.5)
    >>> p = Pill(0.7, 2, 2)
    >>> p.patient_num
    4
    >>> p.cure_num
    2
    >>> p.fail_num
    2
    """
    def __init__(self, cure_pro, cure_num, fail_num):
        assert 0 <= cure_pro <= 1, "Invalid probability"
        Pill.positive(cure_num)
        Pill.positive(fail_num)
        self.__cure_pro = cure_pro #私有变量 不允许修改
        self.__patient_num = cure_num + fail_num
        self.__cure_num = cure_num #预先给定的治疗成功的数
        self.__fail_num = fail_num #预先给定的治疗失败的数
        self.guess_pro = 0 #采样概率
        self.__expect_pro = self.__cure_num / self.__patient_num #期望概率

    @classmethod
    def positive(cls, num):
        assert num > 0, \
            "{0} is not positive".format(num)

    @property
    def expect_pro(self):
        """获取期望概率"""
        return  self.__expect_pro

    @property
    def cure_pro(self):
        """获得cure_pro"""
        return self.__cure_pro

    @property
    def patient_num(self):
        """返回治疗的人数"""
        return self.__patient_num

    @property
    def cure_num(self):
        """获得药丸治愈的人数"""
        return self.__cure_num

    @property
    def fail_num(self):
        """返回失败的人数"""
        return self.__fail_num

    def curing(self, number=1):
        """使用该药丸治疗病人
        返回(成功数,失败数)
        """
        if number < 0:
            raise ValueError("Invalid number")
        self.__patient_num += number
        fail = 0
        for i in range(number):
            if np.random.rand() > self.cure_pro:
                fail += 1
        self.__fail_num += fail
        self.__cure_num += number - fail
        self.__expect_pro = self.__cure_num / self.__patient_num
        return (number-fail, fail)

    def sampling_pro(self):
        """通过汤普森采样,获得guess_pro"""
        random_variable = scipy.stats.beta(self.cure_num,
                                           self.fail_num)
        self.guess_pro = random_variable.rvs() #采样

class Pills:
    """
    >>> pros = [i / 10 for i in range(1, 9)]
    >>> pills = Pills(pros, 2, 2)
    >>> pills.pills_num
    8
    """
    def __init__(self, pros, cure_num, fail_num):
        """
        初始化
        :param pros:每个药丸的治疗概率
        :param cure_num: 先验a
        :param fail_num: 先验b
        """
        self.__pills = []
        for pill_pro in pros:
            pill = Pill(pill_pro, cure_num, fail_num)
            self.__pills.append(pill)
        self.guess_pros = [pill.guess_pro
                           for pill in self.__pills]
        self.__pills_num = len(self.__pills)
        self.__patient_nums = [pill.patient_num
                              for pill in self.__pills]
        self.__expect_pros = [pill.expect_pro
                              for pill in self.__pills]
        self.process = []

    @property
    def pills_num(self):
        return self.__pills_num

    @property
    def expect_pros(self):
        """获取期望概率"""
        return self.__expect_pros

    @property
    def patient_nums(self):
        return self.__patient_nums

    def sampling_pros(self):
        """为药丸们采样"""
        for pill in self.__pills:
            pill.sampling_pro()

    def update_pros(self):
        """更新概率"""
        self.guess_pros = [
            pill.guess_pro \
            for pill in self.__pills
        ]
        self.__expect_pros = [
            pill.expect_pro \
            for pill in self.__pills
        ]

    def choose_pill(self):
        """选择药丸
        实际上,就是寻找治疗概率最大的那个
        """
        self.sampling_pros()
        self.update_pros()
        pros = np.array(self.guess_pros)
        location = pros.argmax()
        pill = self.__pills[location]

        return (pill, location)

    def curing(self, number=1):
        """选择药丸,进行治疗,只针对一种药丸"""
        pill, location = self.choose_pill()
        cure, fail = pill.curing(number)
        self.process = self.process + [location] * number #记录下过程
        self.patient_nums[location] = pill.patient_num

        return cure, fail
    def all_curing(self, number=1):
        """所有药丸都要试一遍"""
        self.update_pros()
        for k, pill in enumerate(self.__pills):
            pill.curing(number)
            self.patient_nums[k] = pill.patient_num




import matplotlib.pyplot as plt
pros = [i / 10 for i in range(1, 9)]
pills = Pills(pros, 2, 2)
opacity = 0.4
bar_width = 0.08
for i in range(100):
    pills.all_curing(3)
    expect_pros = pills.expect_pros
    nums = pills.patient_nums
    fig, ax = plt.subplots()
    ax.bar(pros, expect_pros, bar_width,
           alpha=opacity, color='r')
    ax.set_title("Beta-Bernoulli")
    ax.set_ylabel("Expected probability")
    for j in range(8):
        ax.text(pros[j] - 0.02, expect_pros[j] - 0.03, round(expect_pros[j], 2))
    fig.savefig("ben/pic{0}".format(
        i
    ))
    plt.close()
print(pills.guess_pros)
print(pills.patient_nums)




if __name__ == "__main__":

    import doctest
    doctest.testmod()



# 高斯过程


import numpy as np



PIC = 0

class BayesOpti_GP1:
    """
    贝叶斯优化,基于高斯过程
    只是用于一维的,可以进行扩展
    """
    def __init__(self, x, y, theta, sigma):
        """

        :param x: 位置坐标
        :param y:  输出
        :param theta:  包括theta0 和 theta1
        :param sigma:
        """

        self.__x = [x] # x是ndarray
        self.y = [y]  #y也是ndarray
        self.theta0 = theta[0]
        self.theta1 = theta[1] #尺度参数
        self.sigma = sigma[0]
        self.n = len(self.__x)  #即x的个数
        self.I = np.diag(np.ones(self.n, dtype=float)) #单位矩阵
        self.minimum = min(self.y) #最小值  用于EI

    @property
    def x(self):
        """获取属性x"""
        return self.__x

    """
    我们设定x为私有变量,所以原则上允许改变x
    def set_x(self, x):

        self.__x.append(x)
    """

    def add_y(self, y):
        """添加y同时更新最小值"""
        self.y.append(y)
        self.minimum = min(self.y)

    def kernel(self, r2):
        """为了简单,采用exp kernel"""
        return self.theta0 ** 2 * np.exp(-1/2 * r2)

    def matrix_K(self):
        """更新矩阵K,同时还有一系列衍生的矩阵,
        实际上有很多计算的浪费在此处,但是不想纠结这么多了
        """
        self.K = np.zeros((self.n, self.n), dtype=float)
        self.m_grad1 = np.zeros((self.n, self.n), dtype=float)
        for i in range(self.n):
            for j in range(i, self.n):
                r2 = (self.__x[i]-self.__x[j]) ** 2 \
                    * self.theta1 ** 2
                self.K[i, j] = self.kernel(r2)
                self.m_grad1[i, j] = -self.K[i, j] * r2 / self.theta1 #关于theta1的导数
                self.K[j, i] = self.K[i, j]
                self.m_grad1[j, i] = self.m_grad1[i, j]

        self.K_sigma = self.K + self.sigma ** 2 * self.I#K+sigma^2I
        self.K_sigma_inverse = np.linalg.inv(self.K_sigma) # 逆
        self.K_sigma_det = np.linalg.det(self.K_sigma) #行列式
        self.m_grad0 = 2 * self.K / self.theta0 #关于theta0的导数

    def grad_matrix(self, label):
        """根据需要选择导数矩阵。。。"""
        if label is 0:
            matrix = self.m_grad0
        elif label is 1:
            matrix = self.m_grad1
        else:
            matrix = self.I * 2 * self.sigma
        return matrix

    def grad_detA(self, label):
        """对行列式求导"""
        matrix = self.grad_matrix(label)
        grad = 0.
        for i in range(self.n):
            ksigma = self.K_sigma.copy()
            ksigma[i] = matrix[i]
            grad += np.linalg.det(ksigma)
        y = np.array(self.y, dtype=float)
        grad = (1. - y @ self.K_sigma_inverse @ y) * grad
        return grad


    def grad_A(self, label):
        """part1求导,不知道该怎么描述"""
        A_star = np.zeros((self.n, self.n), dtype=float)
        def grad_A_ij(self, matrix, i, j):
            m1 = np.delete(matrix, j, axis=0)
            m1 = np.delete(m1, i, axis=1)
            m2 = np.delete(self.K_sigma, j, axis=0)
            m2 = np.delete(m2, i, axis=1)
            grad = 0.
            for k in range(self.n-1):
                m3 = m2.copy()
                m3[k] = m1[k]
                grad += np.linalg.det(m3)

            return grad * (-1) ** (i + j)

        matrix = self.grad_matrix(label)
        for i in range(self.n):
            for j in range(i, self.n):
                A_star[i, j] = grad_A_ij(self, matrix, i, j)
                A_star[j, i] = A_star[i, j]
        y = np.array(self.y, dtype=float)
        return y @ A_star @ y

    def grad_pra(self, label):
        """落实道每个参数的导数,这回是真的
        导数了,而不是中间的过渡的矩阵
        """
        part1 = self.grad_A(label)
        part2 = self.grad_detA(label)
        grad = (part1 + part2) / self.K_sigma_det

        return grad

    def marginal_y(self):
        """y的边际分布,省略了很多东西,负号也去了,
        因为用的是梯度下降"""
        y = np.array(self.y, dtype=float)
        return y @ self.K_sigma_inverse @ y \
                + np.log(self.K_sigma_det)

    def update_pra(self):
        """更新参数,如果n为1是一种特殊情况
        采用梯度下降方法,而且是很愚蠢的那种
        """
        if self.n is 1:
            self.matrix_K()
            self.theta0 = self.y[0] * np.sqrt(2) / 2
            self.sigma = self.y[0] * np.sqrt(2) / 2
            return 1

        grad = [999., 999., 999.]
        t = 1
        self.matrix_K()
        min = self.marginal_y()
        min_pra = [self.theta0, self.theta1, self.sigma]
        while True:
            if sum(list(map(abs, grad))) < 1e-4 or t > 200:
                break
            grad[0] = self.grad_pra(0)
            grad[1] = self.grad_pra(1)
            grad[2] = self.grad_pra(2)
            step = max([0.013, 1/t])  #学习率
            self.theta0 = self.theta0 - step * grad[0]
            self.theta1 = self.theta1 - step * grad[1]
            self.sigma = self.sigma - step * grad[2]
            self.matrix_K()
            y = self.marginal_y()
            if y < min:
                min = y
                min_pra = [self.theta0, self.theta1, self.sigma]
            else:
                pass
            t += 1
        self.theta0 = min_pra[0]
        self.theta1 = min_pra[1]
        self.sigma = min_pra[2]
        return 1

    def find_newx(self):
        """根据PI寻找x"""
        x = np.linspace(0, 1, 1000)
        y = np.array(self.y)
        z = []
        u = []
        for item in x:
            k = []
            for xi in self.__x:
                r2 = (xi - item) ** 2 * self.theta1 ** 2
                k.append(self.kernel(r2))
            k = np.array(k)
            q = (self.minimum - k @ self.K_sigma_inverse @ y) / \
                        (self.theta0 ** 2 - k @ self.K_sigma_inverse @ k)
            u.append(k @ self.K_sigma_inverse @ y)
            z.append(q)
        z = np.array(z)
        u = np.array(u)
        import matplotlib.pyplot as plt
        #plt.cla() #清空当前axes
        #plt.plot(x, u)
        #plt.pause(0.1)
        plt.cla()
        fig, ax = plt.subplots()
        ax.plot(x, u)
        fig.savefig("bayes/pic{0}".format(
            PIC
        ))
        newx = x[z.argmax()]
        self.__x.append(newx)
        self.n += 1
        self.I = np.diag(np.ones(self.n, dtype=float))
        return newx




def f(x):  #实际的函数

    return (x - 0.3) ** 2 + 0.2 * np.sin(20 * x)

def f2(x): #加了噪声的函数

    return (x - 0.3) ** 2 + 0.2 * np.sin(20 * x) \
                + np.random.randn() * 0.05


points = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
count = 3
x0 = points[count]
y0 = f(x0)
theta = np.random.randn(2) * 100 #给定初始的参数  随机给的
sigma = np.random.randn(1) * 100
test = BayesOpti_GP1(x0, y0, theta, sigma)

for i in range(10):  #进行10次评估
    test.update_pra()
    newx = test.find_newx()
    newy = f2(newx)
    test.add_y(newy)
    PIC += 1

x = test.x
y = test.y

x1 = np.linspace(0, 1, 1000)
y1 = [f(item) for item in x1]
import matplotlib.pyplot as plt
plt.cla()
print(x, y)
print(test.theta0, test.theta1, test.sigma)
fig, ax = plt.subplots()
ax.plot(x1, y1)
ax.scatter(x, y)
for i in range(len(x)):
    plt.text(x[i], y[i]+0.02, str(i+1), size=10)
plt.show()

附录

Beta-Bernoulli 模型的推导

B e t a ( w a ∣ α , β ) = Γ ( α + β ) Γ ( α ) Γ ( β ) w a α − 1 ( 1 − w a ) β − 1 , w a ∈ [ 0 , 1 ] \mathrm{Beta}(w_a|\alpha,\beta)=\frac{\Gamma(\alpha+\beta)}{\Gamma(\alpha)\Gamma(\beta)}w_a^{\alpha-1}(1-w_a)^{\beta-1}, w_a \in [0,1] Beta(waα,β)=Γ(α)Γ(β)Γ(α+β)waα1(1wa)β1,wa[0,1]
p ( w ∣ D ) = ∏ a = 1 k p ( w a ∣ D ) ∝ ∏ a = 1 k p ( D ∣ w a ) p ( w a ) \begin{array}{ll} p(\mathrm{w}|D) &=\prod \limits_{a=1}^{k}p(\mathrm{w}_a|D)\\ &\propto \prod \limits_{a=1}^{k}p(D|\mathrm{w}_a)p(\mathrm{w}_a) \end{array} p(wD)=a=1kp(waD)a=1kp(Dwa)p(wa)
p ( D ∣ w a ) = w a n a , 1 ( 1 − w a ) n a , 0 p(D|\mathrm{w}_a)=w_a^{n_{a,1}}(1-w_a)^{n_{a,0}} p(Dwa)=wana,1(1wa)na,0
所以, p ( D ∣ w a ) p ( w a ) p(D|\mathrm{w}_a)p(\mathrm{w}_a) p(Dwa)p(wa)的核为 w a n a , 1 + α − 1 ( 1 − w a ) n a , 0 + β − 1 w_a^{n_{a,1}+\alpha-1}(1-w_a)^{n_{a,0}+\beta-1} wana,1+α1(1wa)na,0+β1,满足的是 B e t a ( w a ∣ a + n a , 1 , β + n a , 0 ) \mathrm{Beta}(w_a|a+n_{a,1},\beta+n_{a,0}) Beta(waa+na,1,β+na,0)
证毕。

线性模型 后验分布 p ( w , σ 2 ∣ D n ) p(\mathrm{w},\sigma^2|D_n) p(w,σ2Dn)的推导

只需考虑 p ( D n ∣ w , σ 2 ) p ( w , σ 2 ) p(D_n|\mathrm{w},\sigma^2)p(\mathrm{w},\sigma^2) p(Dnw,σ2)p(w,σ2)的核即可。

p ( D n ∣ w , σ 2 ) ∝ 1 σ n e x p { − ( y − X w ) T ( y − X w ) 2 σ 2 } p(D_n|\mathrm{w},\sigma^2)\propto \frac{1}{\sigma^n}\mathrm{exp}\{-\frac{(y-\mathrm{Xw})^{\mathrm{T}}(y-\mathrm{Xw})}{2\sigma^2}\} p(Dnw,σ2)σn1exp{2σ2(yXw)T(yXw)}
p ( w , σ 2 ) ∝ 1 σ 2 α 0 + 3 e x p { − ( w − w 0 ) T V 0 − 1 ( w − w 0 ) + 2 β 0 2 σ 2 } p(\mathrm{w}, \sigma^2)\propto \frac{1}{\sigma^{2\alpha_0+3}}\mathrm{exp}\{-\frac{(\mathrm{w-w_0})^{\mathrm{T}}V_0^{-1}(\mathrm{w-w_0})+2\beta_0}{2\sigma^2} \} p(w,σ2)σ2α0+31exp{2σ2(ww0)TV01(ww0)+2β0}
先配 w \mathrm{w} w,再配第二部分,即可得:
image.png

y y y边际分布推导

如果我们令 f = X w f=\mathrm{Xw} f=Xw,那么 p ( y ∣ X , σ 2 ) p(y|\mathrm{X},\sigma^2) p(yX,σ2)也可以表示为:
p ( y ∣ X , σ 2 ) = ∫ p ( y ∣ f , σ 2 ) p ( f ∣ X , V 0 ) d f = ∫ N ( y ∣ f , σ 2 I ) N ( f ∣ 0 , X V 0 X T ) d f \begin{array}{ll} p(y|\mathrm{X},\sigma^2) &=\int p(y|f,\sigma^2) p(f|\mathrm{X},\mathrm{V_0})df\\ &=\int \mathcal{N} (y|f,\sigma^2I) \mathcal{N} (f|0, \mathrm{XV_0X^{T}})df \end{array} p(yX,σ2)=p(yf,σ2)p(fX,V0)df=N(yf,σ2I)N(f0,XV0XT)df
这个积分比先前的积分要容易求解(至少前面的那个我直接求不出来)。
依旧采用核方法:
p ( y ∣ X , σ 2 ) ∝ e x p { − ( y − f ) T ( σ 2 I ) − 1 ( y − f ) + f T ( X V 0 X T ) − 1 f 2 } ∝ e x p { − y T ( ( σ − 2 − σ − 2 ( Σ − 1 + σ − 2 ) − 1 σ − 2 ) y 2 } × e x p { − ( f − μ ) T ( Σ − 1 + σ − 2 ) ( f − μ ) 2 } \begin{array}{ll} p(y|\mathrm{X}, \sigma^2) & \propto \mathrm{exp} \{-\frac{(y-f)^{\mathrm{T}}(\sigma^2 I)^{-1}(y-f)+f^{\mathrm{T}}(\mathrm{XV_0X^T})^{-1}f}{2}\}\\ & \propto \mathrm{exp} \{-\frac{y^{\mathrm{T}}((\sigma^{-2}-\sigma^{-2}(\Sigma^{-1}+\sigma^{-2})^{-1}\sigma^{-2})y}{2}\} \\ & \quad \times \mathrm{exp}\{ -\frac{(f-\mu)^{\mathrm{T}}(\Sigma^{-1}+\sigma^{-2})(f-\mu)}{2}\} \end{array} p(yX,σ2)exp{2(yf)T(σ2I)1(yf)+fT(XV0XT)1f}exp{2yT((σ2σ2(Σ1+σ2)1σ2)y}×exp{2(fμ)T(Σ1+σ2)(fμ)}
其中:
μ = ( Σ − 1 + σ − 2 ) − 1 σ − 2 y Σ = X V 0 X T \begin{array}{l} \mu = (\Sigma^{-1}+\sigma^{-2})^{-1}\sigma^{-2}y \\ \Sigma = \mathrm{XV_0X^T} \end{array} μ=(Σ1+σ2)1σ2yΣ=XV0XT
上面第二个 ∝ \propto 的前半部分在积分中相当于常数可以提出,后半部分会被积分掉。所以,现在我们只需要证明:
( ( σ − 2 − σ − 2 ( Σ − 1 + σ − 2 ) − 1 σ − 2 ) − 1 = Σ + σ 2 I ((\sigma^{-2}-\sigma^{-2}(\Sigma^{-1}+\sigma^{-2})^{-1}\sigma^{-2})^{-1}=\Sigma+\sigma^2\mathrm{I} ((σ2σ2(Σ1+σ2)1σ2)1=Σ+σ2I

( ( σ − 2 − σ − 2 ( Σ − 1 + σ − 2 ) − 1 σ − 2 ) = σ 2 − ( Σ − 1 + σ − 2 ) − 1 σ 2 \begin{array}{ll} ((\sigma^{-2}-\sigma^{-2}(\Sigma^{-1}+\sigma^{-2})^{-1}\sigma^{-2}) &= \frac{\sigma^2-(\Sigma^{-1}+\sigma^{-2})^{-1}}{\sigma^2} \end{array} ((σ2σ2(Σ1+σ2)1σ2)=σ2σ2(Σ1+σ2)1
容易证明 ( A + B ) − 1 = A − 1 ( A − 1 + B − 1 ) − 1 B − 1 (A+B)^{-1}=A^{-1}(A^{-1}+B^{-1})^{-1}B^{-1} (A+B)1=A1(A1+B1)1B1 A , B A,B A,B可逆)
所以,
( Σ − 1 + σ − 2 ) − 1 = Σ ( Σ + σ 2 ) − 1 σ 2 (\Sigma^{-1}+\sigma^{-2})^{-1}=\Sigma(\Sigma+\sigma^2)^{-1}\sigma^2 (Σ1+σ2)1=Σ(Σ+σ2)1σ2
C = I − Σ ( Σ + σ 2 ) − 1 C = \mathrm{I}-\Sigma(\Sigma+\sigma^2)^{-1} C=IΣ(Σ+σ2)1,
等式俩边,右乘 ( Σ + σ 2 ) (\Sigma+\sigma^2) (Σ+σ2)得:
C ( Σ + σ 2 ) = σ 2 C(\Sigma+\sigma^2)=\sigma^2 C(Σ+σ2)=σ2
所以,
C = I − Σ ( Σ + σ 2 ) − 1 = σ 2 ( Σ + σ 2 ) − 1 C = \mathrm{I}-\Sigma(\Sigma+\sigma^2)^{-1} = \sigma^2(\Sigma+\sigma^2)^{-1} C=IΣ(Σ+σ2)1=σ2(Σ+σ2)1
所以,
( ( σ − 2 − σ − 2 ( Σ − 1 + σ − 2 ) − 1 σ − 2 ) = ( Σ + σ 2 I ) − 1 ((\sigma^{-2}-\sigma^{-2}(\Sigma^{-1}+\sigma^{-2})^{-1}\sigma^{-2})=(\Sigma+\sigma^2\mathrm{I})^{-1} ((σ2σ2(Σ1+σ2)1σ2)=(Σ+σ2I)1
得证,
证毕.

f ∗ f_* f的后验分布

我们不加推导地给出:
p ( y ∣ X , σ 2 ) = N ( y ∣ m , K + σ 2 I ) p(y|\mathrm{X}, \sigma^2) = \mathcal{N}(y|m, K+\sigma^2\mathrm{I}) p(yX,σ2)=N(ym,K+σ2I)
根据高斯过程的性质,存在如下的联合分布:
[ y f ∗ ] ∼ N ( [ m m ∗ ] , [ K + σ 2 I K ∗ K ∗ T K ∗ ∗ ] ) \left [ \begin{array}{c} y\\ f_* \end{array} \right ] \sim \mathcal{N}\Big( \left [ \begin{array}{c} m\\ m_* \end{array} \right ], \left [ \begin{array}{cc} K+\sigma^2\mathrm{I} & K_*\\ K_*^\mathrm{T} & K_{**} \end{array} \right ] \Big) [yf]N([mm],[K+σ2IKTKK])
其中, X ∗ \mathrm{X}_* X表示预测输入,而 f ∗ f_* f表示预测输出, m ∗ = u 0 ( X ∗ ) m_*=u_0(\mathrm{X_*}) m=u0(X) K ∗ T = { k ( x 1 , X ∗ ) , … , k ( x n , X ∗ ) } K_*^\mathrm{T}=\{k(\mathrm{x}_1,\mathrm{X_*}), \ldots, k(\mathrm{x}_n,\mathrm{X}_*)\} KT={k(x1,X),,k(xn,X)}, K ∗ ∗ = k ( X ∗ , X ∗ ) K_{**}=k(\mathrm{X}_*, \mathrm{X}_*) K=k(X,X)
我们有:
p ( f ∗ ∣ X ∗ , X , y , σ 2 ) = p ( f ∗ , y ∣ X ∗ , X , σ 2 ) p ( y ∣ X , σ 2 ) p(f_*|\mathrm{X}_*, \mathrm{X}, y, \sigma^2)=\frac{p(f_*,y|\mathrm{X}_*,\mathrm{X}, \sigma^2)}{p(y|\mathrm{X}, \sigma^2)} p(fX,X,y,σ2)=p(yX,σ2)p(f,yX,X,σ2)
所以,同样的,我们只需要考虑分子关于$f_* $的核就行了。
p ( f ∗ , y ∣ X ∗ , X , σ 2 ) ∝ e x p { − ( f ∗ − m ∗ ) T C ( f ∗ − m ∗ ) + 2 ( f ∗ − m ∗ ) T B T ( y − m ) 2 } p(f_*,y|\mathrm{X}_*,\mathrm{X}, \sigma^2) \propto \mathrm{exp}\{-\frac{(f_*-m_*)^{\mathrm{T}}C(f_*-m_*)+2(f_*-m_*)^{\mathrm{T}}B^{\mathrm{T}}(y-m)}{2}\} p(f,yX,X,σ2)exp{2(fm)TC(fm)+2(fm)TBT(ym)}
其中:
[ A B B T C ] = [ K + σ 2 I K ∗ K ∗ T K ∗ ∗ ] − 1 \left [\begin{array}{cc} A & B \\ B^{\mathrm{T}} & C \end{array} \right ]= \left [\begin{array}{cc} K+\sigma^2\mathrm{I} & K_* \\ K_*^{\mathrm{T}}& K_{**} \end{array} \right ]^{-1} [ABTBC]=[K+σ2IKTKK]1
容易推得 f ∗ f_* f的均值 μ ∗ \mu_* μ和协方差 σ ∗ 2 \sigma_*^2 σ2为:
μ ∗ = − C − 1 B T ( y − m ) + m ∗ σ ∗ 2 = C − 1 \begin{array}{l} \mu_* = -C^{-1}B^{\mathrm{T}}(y-m)+m_*\\ \sigma_*^2=C^{-1} \end{array} μ=C1BT(ym)+mσ2=C1

根据Schur补和分块矩阵求逆(凸优化-p622)的性质,我们可以得到:
C − 1 = K ∗ ∗ − K ∗ T ( K + σ 2 I ) − 1 K ∗ B T = − C K ∗ T ( K + σ 2 I ) − 1 \begin{array}{c} C^{-1} = K_{**}-K_*^{\mathrm{T}}(K+\sigma^2\mathrm{I})^{-1}K_*\\ B^{\mathrm{T}} = -CK_*^{\mathrm{T}}(K+\sigma^2\mathrm{I})^{-1} \end{array} C1=KKT(K+σ2I)1KBT=CKT(K+σ2I)1
所以,我们得到:
μ ∗ ( X ∗ ) = m ∗ + K ∗ T ( K + σ 2 I ) − 1 ( y − m ) σ ∗ 2 = K ∗ ∗ − K ∗ T ( K + σ 2 I ) − 1 K ∗ \begin{array}{c} \mu_*(\mathrm{X}_*)=m_*+K_*^{\mathrm{T}}(K+\sigma^2\mathrm{I})^{-1}(y-m)\\ \sigma_*^2=K_{**}-K_*^{\mathrm{T}}(K+\sigma^2\mathrm{I})^{-1}K_* \end{array} μ(X)=m+KT(K+σ2I)1(ym)σ2=KKT(K+σ2I)1K
证毕.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值