2

我正在尝试在 GPFlow 中实现变分异方差高斯过程回归。

我的想法是使用带有自定义构建似然的变分稀疏高斯过程模型 (gpflow.models.SVGP),它表示给定两个独立 GP fg的y的密度:

p( y | f , g ) = N(y | f , t( g ) ) 其中 t(·) 是使g为正的某种变换(当前使用tf.nn.softplus)。

为了完成这项工作,我将其设置为 2,但将以,方法仅输出形状为 (N, 1) 的张量的model.num_latent方式实现似然性。以下是我当前的实现:logpconditional_meanconditional_variance

from gpflow.likelihoods import Likelihood
from gpflow.decors import params_as_tensors

import tensorflow as tf
import tensorflow_probability as tfp
tfd = tfp.distributions


class HeteroscedasticGaussian(Likelihood):
    r"""
    When using this class, num_latent must be 2.
    It does not support multi-output (num_output will be 1)
    """
    def __init__(self, transform=tf.nn.softplus, **kwargs):
        super().__init__(**kwargs)
        self.transform = transform

    @params_as_tensors
    def Y_given_F(self, F):
        mu = tf.squeeze(F[:, 0])
        sigma = self.transform(tf.squeeze(F[:, 1]))
        Y_given_F = tfd.Normal(mu, sigma)
        return Y_given_F

    @params_as_tensors
    def logp(self, F, Y):
        return self.Y_given_F(F).log_prob(Y)

    @params_as_tensors
    def conditional_mean(self, F):
        return self.Y_given_F(F).mean()

    @params_as_tensors
    def conditional_variance(self, F):
        return self.Y_given_F(F).variance()

我的疑问是如何使该方法variational_expectations与 d f d g上的双积分一起工作。我打算使用 Gauss-Hermite 求积,但我不明白如何用ndiagquad.

是不是像打电话一样简单

ndiagquad(self.logp, self.num_gauss_hermite_points, Fmu, Fvar, Y=Y)

??

编辑:

一些 MWE,使用variational_expectations来自基类的实现Likelihood

import gpflow as gpf
import tensorflow as tf
import numpy as np

N = 1001
M = 100

X = np.linspace(0, 4*np.pi, N)[:, None]
F = np.sin(X)
G = np.cos(X)
E = np.logaddexp(0, G) * np.random.normal(size=(N,1))
Y = F + E
Z_idx = np.random.choice(N, M, replace=False)

kernel = gpf.kernels.SquaredExponential(input_dim=1)
likelihood = HeteroscedasticGaussian()
likelihood.num_gauss_hermite_points = 11
model = gpf.models.SVGP(
    X=X, Z=X[Z_idx], Y=Y,
    kern=kernel, 
    likelihood=likelihood, 
    num_latent=2
)

# This method will call 
# model.likelihood.variational_expectations(...)
# internally
model.compute_log_likelihood()

我收到以下错误消息:

InvalidArgumentError: Incompatible shapes: [1001,11] vs. [2002]
     [[{{node SVGP-bdd79b25-24/Normal/log_prob/standardize/sub}}]]

我认为这与f有关,g相互堆叠(形状 [2002] = 2*N,N = 1001),并且每个维度仅生成 Gauss-Hermite 点 (11)观察(N = 1001),否则我们将有形状 [1001, 11, 11] 或 [1001, 121=11^2]。

所有帮助表示赞赏。

4

1 回答 1

1

你非常接近 - 我们确实为这个用例实现了多维正交ndiagquad,尽管它需要稍微不同地调用。最好让它工作,这样你写的东西开箱即用。但不幸的是,要找到一种既适用于实际多输出回归、具有多个潜在 GP 的单输出似然性以及两者结合的设计也不是一件容易的事!ndiagquad期望元组(或列表)用于FmuFvar指示您想要多维集成 -当您想要预测具有形状(N,L)的多个输出时,这保留了具有形状(N,L)的fY的向后兼容性。

所以你必须稍微不同地编写代码。此版本适用于您的 MWE:

from gpflow.likelihoods import Likelihood
from gpflow.decors import params_as_tensors

import tensorflow as tf
import tensorflow_probability as tfp
tfd = tfp.distributions


class MultiLatentLikelihood(Likelihood):
    def __init__(self, num_latent=1, **kwargs):
        super().__init__(**kwargs)
        self.num_latent = num_latent

    def _transform(self, F):
        return [F[:, i] for i in range(self.num_latent)]

    def predict_mean_and_var(self, Fmu, Fvar):
        return super().predict_mean_and_var(self._transform(Fmu), self._transform(Fvar))

    def predict_density(self, Fmu, Fvar, Y):
        return super().predict_density(self._transform(Fmu), self._transform(Fvar), Y)

    def variational_expectations(self, Fmu, Fvar, Y):
        return super().variational_expectations(self._transform(Fmu), self._transform(Fvar), Y)

class HeteroscedasticGaussian(MultiLatentLikelihood):
    r"""
    When using this class, num_latent must be 2.
    It does not support multi-output (num_output will be 1)
    """
    def __init__(self, transform=tf.nn.softplus, **kwargs):
        super().__init__(num_latent=2, **kwargs)
        self.transform = transform

    @params_as_tensors
    def Y_given_F(self, F, G):
        mu = tf.squeeze(F)
        sigma = self.transform(tf.squeeze(G))
        Y_given_F = tfd.Normal(mu, sigma)
        return Y_given_F

    @params_as_tensors
    def logp(self, F, G, Y):
        return self.Y_given_F(F, G).log_prob(Y)

    @params_as_tensors
    def conditional_mean(self, F, G):
        return self.Y_given_F(F, G).mean()

    @params_as_tensors
    def conditional_variance(self, F, G):
        return self.Y_given_F(F, G).variance()

我在自己的类中分离了样板代码MultiLatentLikelihood,以便更清楚地了解什么是通用的,什么是异方差高斯的特定的。

也许我们应该把 theMultiLatentLikelihood和 examples 都放到 GPflow 中——如果你愿意的话,为什么不把它添加到 GPflow 并在 github.com/GPflow/GPflow 上提出 Pull Request 呢?很乐意审查它。

此外,GPflow 教程包含一个笔记本,演示了如何处理异方差噪声,以防万一您没有遇到它 - 但它不允许您学习潜在的 GP 来模拟噪声方差。再说一次,我认为如果你想用这个例子(“Demo 3”)扩展笔记本并为你的修改提出一个请求请求会很棒:)

于 2019-08-22T09:42:21.330 回答