首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GPflow中多个潜在全谱图的似然组合

GPflow中多个潜在全谱图的似然组合
EN

Stack Overflow用户
提问于 2019-08-21 18:27:31
回答 1查看 569关注 0票数 2

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

我的思想是使用变分稀疏高斯过程模型(gpflow.models.SVGP),用一个自定义的似然表示y的密度,给出两个独立的GPs,fg

p(y|fg) = N(y f,t(g) ),其中t(·)是使g正(现用tf.nn.softplus)的变换。

为了实现这个工作,我将model.num_latent设置为2,但实现这种可能性的方式是logpconditional_meanconditional_variance方法只输出形状(N,1)的张量。以下是我目前的实现:

代码语言:javascript
复制
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与df dg上的双积分一起工作。我打算使用Gauss求积,但我不知道如何用ndiagquad实现这个双积分。

就像打电话一样简单吗

代码语言:javascript
复制
ndiagquad(self.logp, self.num_gauss_hermite_points, Fmu, Fvar, Y=Y)

??

编辑:

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

代码语言:javascript
复制
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()

我收到以下错误消息:

代码语言:javascript
复制
InvalidArgumentError: Incompatible shapes: [1001,11] vs. [2002]
     [[{{node SVGP-bdd79b25-24/Normal/log_prob/standardize/sub}}]]

我认为这与f有关,g是相互叠加的(shape 2002 = 2*N,n= 1001),而Gauss点( 11 )只对每个观测值产生一维(N = 1001),否则就会有一个1001、11、11或1001,121=11^2形状。

所有的帮助都很感激。

EN

回答 1

Stack Overflow用户

发布于 2019-08-22 09:42:21

您非常接近-我们确实为这个用例在ndiagquad中实现了多维求积,尽管需要稍微不同地调用它。如果你写的东西能在盒子里发挥作用,那就太好了。但不幸的是,要找到一种既适用于实际的多输出回归、具有多个潜在GPs的单输出可能性的设计,又能为FmuFvar找到元组(或列表)的组合,这并不是一件简单的事情,它表明您需要多维集成--这保留了对具有形状(N,L)的f的兼容性,而当您希望预测多个输出时,Y也具有形状(N,L)。

因此,您必须稍微改变一下代码的编写方式。此版本适用于您的MWE:

代码语言:javascript
复制
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教程包含演示如何处理异方差噪声的笔记本电脑,以防您没有遇到它--但它不允许您学习潜在的GP来建模噪声变化。因此,我认为如果您想用这个示例("Demo 3")扩展笔记本并请求您的修改,那就太好了:)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57597349

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档