在GPflow中合并多个潜在GP的可能性

时间:2019-08-21 18:27:31

标签: gpflow

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

我的想法是将变分稀疏高斯过程模型(gpflow.models.SVGP)与自定义构建的似然函数一起使用,该函数表示给定两个独立GP f y 的密度。 >, g

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

要实现此目的,我将model.num_latent设置为2,但将以如下方式实现似然性:logpconditional_meanconditional_variance方法仅输出张量形状(N,1)。下面是我当前的实现:

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的{​​{1}}的实现。

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()

我认为这与 f g 相互堆叠(形状[2002] = 2 * N,N = 1001)有关,并且每个观测值仅针对一个维度生成高斯-赫尔米特点(11)(N = 1001),否则我们将具有形状[1001、11、11]或[1001、121 = 11 ^ 2]。

感谢所有帮助。

1 个答案:

答案 0 :(得分:0)

您非常接近-我们确实在ndiagquad中实现了这种用例的多维正交,尽管它的调用方式略有不同。使它工作以使您所写的内容开箱即用是件好事。但是,不幸的是,找到一种既适用于实际的多输出回归,又具有多个潜在GP的单输出可能性,以及两者结合的设计,并不是完全简单的! ndiagquad期望FmuFvar元组(或列表)表示您想要多维集成-这保留了的向后兼容性f 当您想预测Y也具有形状(N,L)的多个输出时,形状为(N,L)。

因此,您必须稍微不同地编写代码。此版本适用于您的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中,以使内容更清楚,以及什么是异方差高斯式。

也许我们应该将MultiLatentLikelihood和示例都放入GPflow中-如果您愿意的话,为什么不将其添加到GPflow中并在github.com/GPflow/GPflow上发出请求请求呢?很乐意对其进行审查。

此外,GPflow教程中包含a notebook demonstrating how to deal with heteroscedastic noise,以防万一您没碰到它-但是它不允许您学习潜在的GP来模拟噪声方差。再次重申一下,如果您想使用此示例扩展笔记本(“演示3”)并提出“拉取请求”以进行修改,那就太好了:)