gpflow SVGP

时间:2019-05-21 10:38:01

标签: gradient gradient-descent gpflow

当使用Poisson Likelihood优化SVGP来处理大数据集时,我看到了我认为正在爆炸的梯度。 几个时期之后,我看到ELBO的下降幅度很大,在摆脱了之前取得的所有进步之后,ELBO的恢复非常缓慢。 大约有21个迭代对应一个纪元。

ELBO

这个峰值(至少是第二个峰值)导致参数的完全移位(对于参数向量,我只是绘制了范数以查看更改): Parameters

我该如何处理?我的第一种方法是剪切渐变,但这似乎需要挖掘gpflow代码。

我的设置:

通过自然梯度训练变量参数,其余部分通过ADAM进行训练,而自然梯度伽玛训练计划则以缓慢(线性)的方式进行。

对于我的设置,批次和诱导点的尺寸要尽可能大 (均为2 ^ 12,数据集包含约88k个样本)。我加入了1e-5抖动,并用kmeans初始化了诱导点。

我使用了一个组合的内核,它由RBF,Matern52,周期性和线性内核的组合组成,共有95个特征(很多都是由于“一键编码”),所有这些特征都是可以学习的。 长度刻度通过gpflow.transforms进行转换。

    with gpflow.defer_build():
        k1 = Matern52(input_dim=len(kernel_idxs["coords"]), active_dims=kernel_idxs["coords"], ARD=False)
        k2 = Periodic(input_dim=len(kernel_idxs["wday"]), active_dims=kernel_idxs["wday"])
        k3 = Linear(input_dim=len(kernel_idxs["onehot"]), active_dims=kernel_idxs["onehot"], ARD=True)
        k4 = RBF(input_dim=len(kernel_idxs["rest"]), active_dims=kernel_idxs["rest"], ARD=True)
        #
        k1.lengthscales.transform = gpflow.transforms.Exp()
        k2.lengthscales.transform = gpflow.transforms.Exp()
        k3.variance.transform = gpflow.transforms.Exp()
        k4.lengthscales.transform = gpflow.transforms.Exp()

        m = gpflow.models.SVGP(X, Y, k1 + k2 + k3 + k4, gpflow.likelihoods.Poisson(), Z,
                               mean_function=gpflow.mean_functions.Constant(c=np.ones(1)),
                               minibatch_size=MB_SIZE, name=NAME)
        m.mean_function.set_trainable(False)

    m.compile()

更新:仅使用ADAM 按照Mark的建议,我只改了ADAM, 这使我摆脱了突然的爆炸。但是,我仍然只用natgrad来初始化,这似乎可以节省很多时间。

Comparison of ADAM+NATGRAD(grey) vs ADAM only(red)

此外,变异参数的突变似乎不那么突然(至少就其规范而言)。我猜他们现在收敛速度会变慢,但至少它是稳定的。 Comparison of ADAM+NATGRAD(grey) vs ADAM only(red)

2 个答案:

答案 0 :(得分:2)

只需添加到上述Mark的答案中,当在非共轭模型中使用nat grads时,可能需要进行一些调整才能获得最佳性能,并且不稳定可能是个问题。正如Mark所指出的那样,提供潜在更快收敛的大步骤也可能导致参数最终出现在参数空间的不良区域。当变分近似值很好时(即真实和近似后验近似),则有充分的理由期望nat Grad会表现良好,但不幸的是,在一般情况下,没有银弹。有关一些直观信息,请参见https://arxiv.org/abs/1903.02984

答案 1 :(得分:1)

这很有趣。也许不使用natgrads也是一个好主意。裁剪渐变确实看起来像是可行的技巧。是的,这将需要在GPflow代码中进行一些挖掘。可以帮助实现这一目标的一个技巧是不直接使用GPflow优化器。 model._likelihood_tensor包含应优化的TF张量。也许使用一些手动TensorFlow魔术,您可以在运行优化器之前在此处进行渐变剪切。

总的来说,我认为这听起来像是您偶然发现了一个实际的研究问题。通常,这些大梯度在模型中有充分的理由,可以通过仔细考虑加以解决。蒙特卡洛估计中有差异吗?目标函数表现不好吗?

关于为什么不使用自然渐变会有所帮助。自然梯度使用Fisher矩阵作为预处理器来执行二阶优化。这样做可能会导致参数空间发生非常激进的移动。在某些情况下(当存在可用的共轭关系时),这些激进的举动可以使优化更快。在具有泊松可能性的情况下,这种情况并非存在共轭关系必将有助于优化的情况。实际上,Fisher预处理器通常是有害的,尤其是在变化参数未达到最佳值时。