我试图在GPFlow中实现变分异方差高斯过程回归。
我的思想是使用变分稀疏高斯过程模型(gpflow.models.SVGP),用一个自定义的似然表示y的密度,给出两个独立的GPs,f,g。
p(y|f,g) = N(y f,t(g) ),其中t(·)是使g正(现用tf.nn.softplus)的变换。
为了实现这个工作,我将model.num_latent设置为2,但实现这种可能性的方式是logp、conditional_mean、conditional_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与df dg上的双积分一起工作。我打算使用Gauss求积,但我不知道如何用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是相互叠加的(shape 2002 = 2*N,n= 1001),而Gauss点( 11 )只对每个观测值产生一维(N = 1001),否则就会有一个1001、11、11或1001,121=11^2形状。
所有的帮助都很感激。
发布于 2019-08-22 09:42:21
您非常接近-我们确实为这个用例在ndiagquad中实现了多维求积,尽管需要稍微不同地调用它。如果你写的东西能在盒子里发挥作用,那就太好了。但不幸的是,要找到一种既适用于实际的多输出回归、具有多个潜在GPs的单输出可能性的设计,又能为Fmu和Fvar找到元组(或列表)的组合,这并不是一件简单的事情,它表明您需要多维集成--这保留了对具有形状(N,L)的f的兼容性,而当您希望预测多个输出时,Y也具有形状(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教程包含演示如何处理异方差噪声的笔记本电脑,以防您没有遇到它--但它不允许您学习潜在的GP来建模噪声变化。因此,我认为如果您想用这个示例("Demo 3")扩展笔记本并请求您的修改,那就太好了:)
https://stackoverflow.com/questions/57597349
复制相似问题