为什么 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()
函数(在这种情况下,您确实需要像示例中那样在循环中调用它)。
我正在提供不同的小批量来优化 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()
函数(在这种情况下,您确实需要像示例中那样在循环中调用它)。