为什么 HMC 采样器 return 需要为正的超参数的负值? [1.0 之前的旧 GPflow 版本]
Why does the HMC sampler return negative values for hyperparameters that need to be positive? [older GPflow versions before 1.0]
我想构建一个具有边缘化超参数的 GP。
我已经看到,这可以通过 this notebook
的 gpflow 中提供的 HMC 采样器实现
然而,当我尝试运行以下代码作为第一步时(注意这是在 gpflow 0.5 上,旧版本),返回样本为负,即使长度尺度和方差需要为正(负值将毫无意义)。
import numpy as np
from matplotlib import pyplot as plt
import gpflow
from gpflow import hmc
X = np.linspace(-3, 3, 20)
Y = np.random.exponential(np.sin(X) ** 2)
Y = (Y - np.mean(Y)) / np.std(Y)
k = gpflow.kernels.Matern32(1, lengthscales=.2, ARD=False)
m = gpflow.gpr.GPR(X[:, None], Y[:, None], k)
m.kern.lengthscales.prior = gpflow.priors.Gamma(1., 1.)
m.kern.variance.prior = gpflow.priors.Gamma(1., 1.)
# dont want likelihood be a hyperparam now so fixed
m.likelihood.variance = 1e-6
m.likelihood.variance.fixed = True
m.optimize(maxiter=1000)
samples = m.sample(500)
print(samples)
输出:
[[-0.43764571 -0.22753325]
[-0.50418501 -0.11070128]
[-0.5932655 0.00821438]
[-0.70217714 0.05077999]
[-0.77745654 0.09362291]
[-0.79404456 0.13649446]
[-0.83989415 0.27118385]
[-0.90355789 0.29589641]
...
我不太了解 HMC 采样的细节,但我希望采样的后验超参数是正的,我检查了代码,它似乎可能与 Log1pe 变换有关,但我没有想到我自己解决了。
有什么提示吗?
如果您指定 您正在使用哪个 GPflow 版本,这将很有帮助 - 特别是考虑到从您发布的输出来看,您使用的确实是 旧版本的 GPflow(1.0 之前),这实际上是从那以后得到改进的东西。这里发生的事情(在旧的 GPflow 中)是 sample() 方法 returns 单个数组 S x P,其中 S 是样本数,P 是自由参数的数量 [例如对于具有下三角变换的 M x M 矩阵参数(例如近似后验协方差的 Cholesky,q_sqrt),实际上仅存储和优化了 M * (M - 1)/2 个参数!] .这些是 unconstrained space 中的值,即它们可以取任何值。转换(参见 gpflow.transforms
模块)提供此值(在 plus/minus 无穷大之间)和约束值(例如 gpflow.transforms.positive 用于长度尺度和方差)之间的映射。在旧的 GPflow 中,该模型提供了一个 get_samples_df()
方法,该方法采用 sample()
返回的 S x P 数组和 returns 一个 pandas DataFrame,其中包含所有可训练参数的列成为你想成为的人。或者,理想情况下,您只需使用最新版本的 GPflow,其中 HMC 采样器直接 returns DataFrame!
我想构建一个具有边缘化超参数的 GP。
我已经看到,这可以通过 this notebook
的 gpflow 中提供的 HMC 采样器实现然而,当我尝试运行以下代码作为第一步时(注意这是在 gpflow 0.5 上,旧版本),返回样本为负,即使长度尺度和方差需要为正(负值将毫无意义)。
import numpy as np
from matplotlib import pyplot as plt
import gpflow
from gpflow import hmc
X = np.linspace(-3, 3, 20)
Y = np.random.exponential(np.sin(X) ** 2)
Y = (Y - np.mean(Y)) / np.std(Y)
k = gpflow.kernels.Matern32(1, lengthscales=.2, ARD=False)
m = gpflow.gpr.GPR(X[:, None], Y[:, None], k)
m.kern.lengthscales.prior = gpflow.priors.Gamma(1., 1.)
m.kern.variance.prior = gpflow.priors.Gamma(1., 1.)
# dont want likelihood be a hyperparam now so fixed
m.likelihood.variance = 1e-6
m.likelihood.variance.fixed = True
m.optimize(maxiter=1000)
samples = m.sample(500)
print(samples)
输出:
[[-0.43764571 -0.22753325]
[-0.50418501 -0.11070128]
[-0.5932655 0.00821438]
[-0.70217714 0.05077999]
[-0.77745654 0.09362291]
[-0.79404456 0.13649446]
[-0.83989415 0.27118385]
[-0.90355789 0.29589641]
...
我不太了解 HMC 采样的细节,但我希望采样的后验超参数是正的,我检查了代码,它似乎可能与 Log1pe 变换有关,但我没有想到我自己解决了。
有什么提示吗?
如果您指定 您正在使用哪个 GPflow 版本,这将很有帮助 - 特别是考虑到从您发布的输出来看,您使用的确实是 旧版本的 GPflow(1.0 之前),这实际上是从那以后得到改进的东西。这里发生的事情(在旧的 GPflow 中)是 sample() 方法 returns 单个数组 S x P,其中 S 是样本数,P 是自由参数的数量 [例如对于具有下三角变换的 M x M 矩阵参数(例如近似后验协方差的 Cholesky,q_sqrt),实际上仅存储和优化了 M * (M - 1)/2 个参数!] .这些是 unconstrained space 中的值,即它们可以取任何值。转换(参见 gpflow.transforms
模块)提供此值(在 plus/minus 无穷大之间)和约束值(例如 gpflow.transforms.positive 用于长度尺度和方差)之间的映射。在旧的 GPflow 中,该模型提供了一个 get_samples_df()
方法,该方法采用 sample()
返回的 S x P 数组和 returns 一个 pandas DataFrame,其中包含所有可训练参数的列成为你想成为的人。或者,理想情况下,您只需使用最新版本的 GPflow,其中 HMC 采样器直接 returns DataFrame!