GPflow 2.0中使用Tensorflow双射链实现有界超参数优化 [英] Bounding hyperparameter optimization with Tensorflow bijector chain in GPflow 2.0
问题描述
在GPflow 2.0中进行GP回归时,我想在长度比例上设置硬边界(即限制长度比例优化范围).遵循此线程(在GPflow 2.0中设置超参数优化范围) ,我构造了一个TensorFlow Bijector链(请参见下面的bounded_lengthscale
函数).但是,下面的双射链不会阻止模型在假定范围之外进行优化.我需要更改什么以使bounded_lengthscale
函数对优化施加严格的限制?
While doing GP regression in GPflow 2.0, I want to set hard bounds on lengthscale (i.e. limiting lengthscale optimization range). Following this thread (Setting hyperparameter optimization bounds in GPflow 2.0), I constructed a TensorFlow Bijector chain (see bounded_lengthscale
function below). However, the bijector chain below does not prevent the model from optimizing outside the supposed bounds. What do I need to change to make the bounded_lengthscale
function put hard bounds on optimization?
下面是MRE:
import gpflow
import numpy as np
from gpflow.utilities import print_summary
import tensorflow as tf
from tensorflow_probability import bijectors as tfb
# Noisy training data
noise = 0.3
X = np.arange(-3, 4, 1).reshape(-1, 1).astype('float64')
Y = (np.sin(X) + noise * np.random.randn(*X.shape)).reshape(-1,1)
def bounded_lengthscale(low, high, lengthscale):
"""Returns lengthscale Parameter with optimization bounds."""
affine = tfb.AffineScalar(shift=low, scale=high-low)
sigmoid = tfb.Sigmoid()
logistic = tfb.Chain([affine, sigmoid])
parameter = gpflow.Parameter(lengthscale, transform=logistic, dtype=tf.float32)
parameter = tf.cast(parameter, dtype=tf.float64)
return parameter
# build GPR model
k = gpflow.kernels.Matern52()
m = gpflow.models.GPR(data=(X, Y), kernel=k)
m.kernel.lengthscale.assign(bounded_lengthscale(0, 1, 0.5))
print_summary(m)
# train model
@tf.function(autograph=False)
def objective_closure():
return - m.log_marginal_likelihood()
opt = gpflow.optimizers.Scipy()
opt_logs = opt.minimize(objective_closure,
m.trainable_variables)
print_summary(m)
谢谢!
推荐答案
在MWE中,您将assign
新的值设置为已存在的Parameter
(并且没有物流)变形).该值是使用logistic变换构造的Parameter具有的约束空间值,但是该变换不会被继承.取而代之的是,您需要替换而不进行逻辑转换的参数,并将其替换为您想要的转换:m.kernel.lengthscale = bounded_lengthscale(0,1,0.5)
.
In the MWE you assign
a new value to a Parameter
that is already existing (and does not have the logistic transform). This value is the constrained-space value that the Parameter constructed with logistic transform has, but the transform isn't carried over. Instead, you need to replace the Parameter without logistic transform with one with the transform you want: m.kernel.lengthscale = bounded_lengthscale(0,1,0.5)
.
请注意,您分配给kernel.lengthscale
属性的对象必须是Parameter
实例;如果您按照MWE中的方式分配tf.cast(parameter)
的返回值,则它等效于一个常量,并且实际上不会对其进行优化!
Note that the object that you assign to the kernel.lengthscale
attribute must be a Parameter
instance; if you assign the return value of tf.cast(parameter)
as in the MWE this is equivalent to a constant, and it won't actually be optimised!
由于float32/float64不匹配,在此问题中仅移动MWE中的tf.cast不会立即起作用.要解决此问题,AffineScalar双射器必须位于float64中;它没有dtype
参数,而是将参数强制转换为shift=
和scale=
到所需的类型:
Simply temoving the tf.cast in the MWE in this question won't immediately work due to float32/float64 mismatch. To fix it, the AffineScalar bijector needs to be in float64; it does not have a dtype
argument, instead cast the arguments to shift=
and scale=
to the required type:
def bounded_lengthscale(low, high, lengthscale):
"""Make lengthscale tfp Parameter with optimization bounds."""
affine = tfb.AffineScalar(shift=tf.cast(low, tf.float64),
scale=tf.cast(high-low, tf.float64))
sigmoid = tfb.Sigmoid()
logistic = tfb.Chain([affine, sigmoid])
parameter = gpflow.Parameter(lengthscale, transform=logistic, dtype=tf.float64)
return parameter
m.kernel.lengthscale = bounded_lengthscale(0, 1, 0.5)
(GPflow可能应该包含这样的辅助函数,以使有界参数转换更易于使用-GPflow总是感谢人们的帮助,因此,如果要将其转换为请求请求,请这样做!)
(GPflow should probably contain a helper function like this to make bounded parameter transforms easier to use - GPflow always appreciates people helping out, so if you want to turn this into a pull request, please do!)
这篇关于GPflow 2.0中使用Tensorflow双射链实现有界超参数优化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!