使用长度尺度的先验分布自动确定相关性
Automatic relevance determination with prior distribution for lengthscale
我正在尝试使用 GPflow 来拟合 GP。我想对长度尺度使用自动相关性确定和先验。
我知道如何分别做:
kernel = gpflow.kernels.SquaredExponential(lengthscales=([10] * X_train.shape[1]))
和
kernel.lengthscales.prior = tfp.distributions.Gamma(
to_default_float(3), to_default_float(0.25)
)
...但我想两者都做(所以基本上不同的 Gamma 分布作为每个特征的先验)。
我尝试只使用两行代码并且没有错误,但之前似乎没有添加或更改任何内容。
我怎样才能将这两者结合起来?
编辑:我又玩了一会儿,我想也许这没什么大不了的,因为在训练过程中会调整长度尺度。然而,长度尺度的起点对我的模型的准确性有重大影响,并且它们从起点不会发生显着变化。
例如,使用 lengthscales = 10 进行初始化会得到 7 - 13 之间的优化长度尺度,15 会产生 12-18 等。使用较小的长度尺度(例如 0.1 或 1)进行初始化会导致长度尺度更接近 10。
不过,我认为如果可以为使用 ARD 的每个特征设置一个先验值,那将是非常有价值的。如果可以(仅?)使用 MCMC 方法,我可能会进行下一步调查。
每个输入维度也可以有不同的先验分布:您只需要相应地定义先验。例如,
alpha_ard = np.array([3.0, 4.0, 3.0, 3.0, 7.0])
beta_ard = np.array([0.25, 0.4, 0.4, 0.25, 0.25])
kernel.lengthscales.prior = tfp.distributions.Gamma(alpha_ard, beta_ard)
请注意,先验现在的 batch_shape
为 [5] 而不是之前的 []。
这确实改变了一些事情,您可以通过以下简单示例进行验证:
import gpflow
import numpy as np
import tensorflow_probability as tfp
import tensorflow as tf
num_data = 1
input_dim = 5
output_dim = 1
X_train = np.ones((num_data, input_dim))
Y_train = np.ones((num_data, output_dim))
single_prior = tfp.distributions.Gamma(np.float64(3.0), np.float64(0.25))
ard_equal_priors = tfp.distributions.Gamma(np.array([3.0]*5), np.array([0.25]*5))
ard_different_priors = tfp.distributions.Gamma(np.array([1.0, 2.0, 3.0, 4.0, 5.0]), np.array([0.25, 0.1, 0.5, 0.2, 0.3]))
def build_model(prior):
kernel = gpflow.kernels.SquaredExponential(lengthscales=([1.0] * input_dim))
kernel.lengthscales.prior = prior
model = gpflow.models.GPR((X_train, Y_train), kernel, noise_variance=0.01)
opt = gpflow.optimizers.Scipy()
opt.minimize(model.training_loss, model.trainable_variables)
m1 = build_model(single_prior)
m2 = build_model(ard_equal_priors)
m3 = build_model(ard_different_priors)
m1
和 m2
最终得到完全相同的长度尺度,而 m3
不同。
在不使用 MCMC 的情况下,超参数只是点估计(没有设置先验的最大似然 [MLE],或者像您一样设置先验的最大后验 [MAP])。通常有几个局部最优,所以你最终选择哪一个取决于初始化。有关更多说明,请参阅 this distill article。
我正在尝试使用 GPflow 来拟合 GP。我想对长度尺度使用自动相关性确定和先验。
我知道如何分别做:
kernel = gpflow.kernels.SquaredExponential(lengthscales=([10] * X_train.shape[1]))
和
kernel.lengthscales.prior = tfp.distributions.Gamma(
to_default_float(3), to_default_float(0.25)
)
...但我想两者都做(所以基本上不同的 Gamma 分布作为每个特征的先验)。
我尝试只使用两行代码并且没有错误,但之前似乎没有添加或更改任何内容。
我怎样才能将这两者结合起来?
编辑:我又玩了一会儿,我想也许这没什么大不了的,因为在训练过程中会调整长度尺度。然而,长度尺度的起点对我的模型的准确性有重大影响,并且它们从起点不会发生显着变化。
例如,使用 lengthscales = 10 进行初始化会得到 7 - 13 之间的优化长度尺度,15 会产生 12-18 等。使用较小的长度尺度(例如 0.1 或 1)进行初始化会导致长度尺度更接近 10。
不过,我认为如果可以为使用 ARD 的每个特征设置一个先验值,那将是非常有价值的。如果可以(仅?)使用 MCMC 方法,我可能会进行下一步调查。
每个输入维度也可以有不同的先验分布:您只需要相应地定义先验。例如,
alpha_ard = np.array([3.0, 4.0, 3.0, 3.0, 7.0])
beta_ard = np.array([0.25, 0.4, 0.4, 0.25, 0.25])
kernel.lengthscales.prior = tfp.distributions.Gamma(alpha_ard, beta_ard)
请注意,先验现在的 batch_shape
为 [5] 而不是之前的 []。
这确实改变了一些事情,您可以通过以下简单示例进行验证:
import gpflow
import numpy as np
import tensorflow_probability as tfp
import tensorflow as tf
num_data = 1
input_dim = 5
output_dim = 1
X_train = np.ones((num_data, input_dim))
Y_train = np.ones((num_data, output_dim))
single_prior = tfp.distributions.Gamma(np.float64(3.0), np.float64(0.25))
ard_equal_priors = tfp.distributions.Gamma(np.array([3.0]*5), np.array([0.25]*5))
ard_different_priors = tfp.distributions.Gamma(np.array([1.0, 2.0, 3.0, 4.0, 5.0]), np.array([0.25, 0.1, 0.5, 0.2, 0.3]))
def build_model(prior):
kernel = gpflow.kernels.SquaredExponential(lengthscales=([1.0] * input_dim))
kernel.lengthscales.prior = prior
model = gpflow.models.GPR((X_train, Y_train), kernel, noise_variance=0.01)
opt = gpflow.optimizers.Scipy()
opt.minimize(model.training_loss, model.trainable_variables)
m1 = build_model(single_prior)
m2 = build_model(ard_equal_priors)
m3 = build_model(ard_different_priors)
m1
和 m2
最终得到完全相同的长度尺度,而 m3
不同。
在不使用 MCMC 的情况下,超参数只是点估计(没有设置先验的最大似然 [MLE],或者像您一样设置先验的最大后验 [MAP])。通常有几个局部最优,所以你最终选择哪一个取决于初始化。有关更多说明,请参阅 this distill article。