为什么 GPflow 的 Scipy 优化器与用 tf.function 装饰优化步骤不兼容?

Why is GPflow's Scipy optimizer incompatible with decorating the optimization step with tf.function?

我正在提供不同的小批量来优化 GPflow 模型 (SVGP)。如果我用 tf.function 装饰 optimization_step 我会收到以下错误:

NotImplementedError: Cannot convert a symbolic Tensor (concat:0) to a numpy array. This error may indicate that you're trying to pass a Tensor to a NumPy call, which is not supported

为了优化器 运行 我不得不删除 tf.function 装饰器,失去了加速优势。我需要更改什么才能继续使用 tf.function 装饰器?

xAndY 个输入形状和类型都是 numpy 个数组。

type(xAndY)
Out[71]: tuple
xAndY[0].shape
Out[72]: (245760, 2)
xAndY[1].shape
Out[73]: (245760, 1)
type(xAndY[0])
Out[74]: numpy.ndarray
def run_optimizer_on_minibatch_size(model, iterations, minibatch_size, xAndY):
    """
    Utility function running a Scipy optimizer
    :param model: GPflow model
    :param interations: number of iterations
    """
    N = xAndY[0].shape[0]
    tensor_data = tuple(map(tf.convert_to_tensor, xAndY))
    train_dataset = tf.data.Dataset.from_tensor_slices(tensor_data).repeat().shuffle(N)
    
    logf = []
    train_iter = iter(train_dataset.batch(minibatch_size))
    training_loss = model.training_loss_closure(train_iter, compile=True)
    optimizer = gpflow.optimizers.Scipy()

    @tf.function   # had to remove this decorator
    def optimization_step():
        optimizer.minimize(training_loss, model.trainable_variables)

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

from gpflow.ci_utils import ci_niter
maxiter = ci_niter(20000)
logf = run_optimizer_on_minibatch_size(m, maxiter, minibatch_size, (X,Y))

GPflow 的 gpflow.optimizers.Scipy() 是 Scipy 的 minimize() 的包装器,当它调用非 TensorFlow 操作时,您不能将其包装在 tf.function 中。此外,在 Scipy 的最小化中实现的优化器是二阶方法,假设您的梯度 不是 随机的,并且与 minibatching 不兼容。

如果你想用Scipy做full-batch优化:gpflow.optimizers.Scipy()minimize()方法默认会把objective和梯度计算包裹在里面tf.function(参见其 compile 参数,默认值为 True)。它还会进行全面优化,因此您只需调用 minimize() 方法 一次 (默认情况下,它 运行s 直到收敛或失败才能继续优化;您可以使用 options=dict(maxiter=1000) 参数提供最大迭代次数。

如果你想使用小批量处理:只需使用一种 TensorFlow 优化器,例如 tf.optimizers.Adam(),然后你的代码应该 运行 很好,包括 @tf.function 装饰器您的 optimization_step() 函数(在这种情况下,您确实需要像示例中那样在循环中调用它)。