GPflow 中的 Adam 优化器正在处理哪种类型的参数,受约束的还是不受约束的?

Which type of parameter the Adam optimizer in GPflow is working on, constrained or unconstrained?

在GPflow的文档中SVGP and natural gradient,在使用随机变分推理技术训练GP模型的模型参数(长度尺度、方差、诱导输入等)时,使用了TensorFlow中的Adam优化器,而变分参数的自然梯度优化器。片段如下所示

def run_adam(model, iterations):
    """
    Utility function running the Adam optimizer

    :param model: GPflow model
    :param interations: number of iterations
    """
    # Create an Adam Optimizer action
    logf = []
    train_iter = iter(train_dataset.batch(minibatch_size))
    training_loss = model.training_loss_closure(train_iter, compile=True)
    optimizer = tf.optimizers.Adam()

    @tf.function
    def optimization_step():
        optimizer.minimize(training_loss, model.trainable_variables)

    for step in range(iterations):
        optimization_step()
        if step % 10 == 0:
            elbo = -training_loss().numpy()
            logf.append(elbo)
    return logf

如上所示,model.trainable_variables 被传递给继承自 tf.Module 的 Adam 优化器,由包括 lengthscale 和 variance 在内的几个参数组成。

我关心的是 Adam 优化器是在处理模型参数的无约束版本还是有约束版本。一段测试代码运行如下

import gpflow as gpf
import numpy as np

x = np.arange(10)[:, np.newaxis]
y = np.arange(10)[:, np.newaxis]
model = gpf.models.GPR((x, y), 
                       kernel = gpf.kernels.SquaredExponential(variance = 2, lengthscales = 3), 
                       noise_variance = 4)

model.kernel.parameters[0].unconstrained_variable is model.trainable_variables[0]

和returns

True

据我所知,像lenghtscales和kernel的variances这样的gaussian过程的参数都是非负的,训练的时候应该对它们进行约束。我不是 GPflow 或 TensorFlow 源代码的专家,但 Adam 似乎正在研究无约束参数。这是对我的误解,还是别的什么?

在此先感谢您的帮助!

你是对的,这是设计使然。 GPflow 中的约束变量由 Parameter 表示。 Parameter 包裹了 unconstrained_variable。当您在模型上访问 .trainable_variables 时,这将包括 Parameterunconstrained_variable,因此当您将这些变量传递给优化器时,优化器将训练这些变量而不是 Parameter本身。

但是你的模型没有看到 unconstrained_value,它看到了 Parameter 接口,它是一个类似于 tf.Tensor 的接口,通过一个可选转换。此转换将不受约束的值映射到受约束的值。因此,您的模型只会看到受约束的值。您的约束值必须为正不是问题,转换会将无约束值的负值映射为约束值的正值。

您可以看到内核的第一个 Parameter 的无约束和约束值,以及与它们相关的转换,

param = model.kernel.parameters[0]
param.value()  # this is what your model will see
param.unconstrained_variable  # this is what the optimizer will see
param.transform  # the above two are related via this