任务场景

给定数据,真实的分布是未知的。我们学习的任务就是去拟合出真实的分布。现在我们给出一个真实分布是 GMM,在上面采样得到一组数据。你是否能够根据数据去拟合出这个分布?

1
2
GMM(means, variances, weights)
true_model = models.GMM([-4, 0, 2], [1, 2, .7], [0.2, 0.2, 0.6])

单峰分布

用高斯分布拟合

我们知道高斯分布是长这样的

p(xμ,σ2)=N(xμ,σ2)=12πσ2exp{(xμ)22σ2}
  • μ is the mean of the Gaussian density
  • σ2 is the variance of the Gaussian density
  • λ=1σ2 is the precision of the Gaussian density

(等等我们可以用 λ 代替方差来写高斯分布)

为了估计真实的分布,可以采用最大化似然的办法得到均值和方差

μ=1Nixiσ2=1Nix2i
1
2
3
N = len(X)
mean = np.sum(X)/N
var = np.sum(X**2)/N

显然这个结果不能很好地拟合真实分布。

贝叶斯推理:加入均值和方差的先验

A common and convenient choice of prior for the Gaussian is the Normal-Gamma prior:

p(μ,λm0,κ0,a0,b0)=N(μm0,(κ0λ)1)Gam(λa0,b0)

where:

Gam(λa0,b0)=1Γ(a0)ba00λa01exp{b0λ}

m0, κ0, a0 and b0 are called hyper-parameters. They are the parameters of the prior distribution.

为了对 Normal-Gamma 分布有个形象的了解,可以绘图看到,它的均值和方差是服从这样的概率分布的

1
2
NormalGamma(mean, kappa, a, b)
ng_prior = models.NormalGamma(0, 2, 5, 6)

由于 Normal-Gamma 是 正态分布的 共轭先验,因此 Normal-Gamma 的后验有闭式解,且可以写成如下形式:

p(μ,λx)=N(μmn,(κnλ)1)Gam(λan,bn)

where:

mn=κ0m0+Nˉxκ0+Nκn=κ0+Nan=a0+N2bn=b0+N2(s+κ0(ˉxm0)2κ0+N)ˉx=1Nixis=1Ni(xiˉx)2

N is the total number of point in the the training data and mn, κn, an and bn are the parameters of the posterior. Note that they are different from the hyper-parameters !!

因此加入后验的影响后,均值和方差的分布成为更加聚集的一小团。

当需要做预测任务时,则需要把均值和方差边缘化(积分掉),得到数据分布。恰好这个分布是学生分布。由此可以得到每个数据点的概率密度:

但是由于是单峰的,拟合效果还是很差!

多峰分布

用高斯混合模型拟合

我们尝试用 K 个不同的高斯分布来拟合真实分布:

p(x|μ,λ,π)=Kk=1πkN(x|μk,(λk)1)
  • μ is the vector of K means
  • λ is the vector of K precisions
  • π is the vector of K weights such that Kk=1πk=1

其中给不同高斯加的权重作为隐变量。

用 EM 算法求解参数

  • initialize the parameters of the GMM
  • iterate until convergence (logp(x|θnew)logp(x|θold)0.01):
    • Expectation (E-step): compute the probability of the latent variable for each data point
    • Maximization (M-step): update the parameters from the statistics of the E-step.

具体推导可以看 Expectation Maximization algorithm 以及 GMM

1
2
3
4
5
6
7
8
9
10
11
last_llh = -1e8
while 1e-2 < np.absolute(llh - last_llh):
# E-step
Z = gmm.EStep(X)

# M-step
gmm.MStep(X, Z)

last_llh = llh
llh = gmm.logLikelihood(X)
print('log-likelihood:', llh)

具体的 EStepMStep 可以看这里

不同的参数初始化得到的效果不同。这里给出了一个拟合得较好的分布:

贝叶斯推理:加入先验

加入参数的先验:

p(π)=Dir(πα0)p(μk,λk)=N(μkm0,(κ0λk)1)Gam(λka0,b0)

如果仍旧想用 EM 算法求解参数,则在 M 步会直接把均值和方差算出来,而不是算出均值和方差的后验。因此不能用 EM 算法。

考虑到参数之间有相互依赖的关系,可以用 Gibbs Sampling 得到参数的后验分布。给出以下三个条件分布,在每次迭代中,都假设知道了条件值,采出样本。最终它们将趋向于真实分布。

latent variable zi

p(zix,Θ)=p(zixi,π,μ,λ)p(zi=kxi,π,μ,λ)=πkN(xiμk,λk)Kj=0πjN(xiμj,λj)

mean and variance

We define the set of all data point xi that are assigned to the component k of the mixture as follows:

x(k)={xi:zi=k,i{1,...,N}}

and similarly for the latent variables z:

z(k)={zi:zi=k,i{1,...,N}}p(μk,λkx,z,Θ{μk,λk})=p(μk,λkx(k),z(k),Θ{μk,λk})=N(μkmn,k,(κn,kλk)1)Gam(λkan,k,bn,k)

where:

mn,k=κ0m0+Nkˉxkκ0+Nkκn,k=κ0+Nkan,k=a0+Nk2bn,k=b0+Nk2(s+κ0(ˉxkm0)2κ0+Nk)Nk=|x(k)|ˉxk=1Nkxx(k)xsn=1Nxx(k)(xiˉx)2

NOTE: these equations are very similar to the Bayesian Gaussian estimate. However, it remains some difference

weights

p(πx,z,Θ{π})=p(πz)=Dir(πα)

where:

αn,k=α0,k+Nk;k=1K
1
2
3
4
5
6
7
8
9
10
for i in range(20):
# Sample the latent variables
Z = bgmm.sampleLatentVariables(X)

# Update the parameters
bgmm.sampleMeansVariances(X, Z)
bgmm.sampleWeights(Z)

# Just for plotting, this is not part of the Gibbs Sampling algorithm.
plotting.plotGMM(bgmm.gmm, fig=fig, ax=ax, color='b', lw=.5, label='sampled GMM')

每次迭代的参数都可以生成一条蓝线。把蓝线加权平均得到了红线。看起来还是比较接近真实分布的。

相关教程