2

在 GPflow 2.0 中进行 GP 回归时,我想在长度尺度上设置硬边界(即限制长度尺度优化范围)。按照这个线程(在 GPflow 2.0 中设置超参数优化边界),我构建了一个 TensorFlow Bijector 链(见bounded_lengthscale下面的函数)。但是,下面的双射器链不会阻止模型在假定的范围之外进行优化。我需要改变什么才能使bounded_lengthscale函数对优化施加严格的限制?

下面是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)

谢谢!

4

2 回答 2

3

在 MWE 中,您assign为 a 提供了一个新Parameter该值已经存在(并且没有逻辑转换)。该值是使用逻辑变换构造的 Parameter 具有的约束空间值,但不会延续变换。相反,您需要将没有逻辑转换的参数替换m.kernel.lengthscale = bounded_lengthscale(0,1,0.5)为您想要的转换: .

请注意,您分配给kernel.lengthscale属性的对象必须Parameter实例;如果您tf.cast(parameter)在 MWE 中分配 as 的返回值,这相当于一个常量,并且实际上不会被优化!

由于 float32/float64 不匹配,在这个问题中简单地删除 MWE 中的 tf.cast 不会立即起作用。要修复它,AffineScalar 双射器需要在 float64 中;它没有dtype参数,而是将参数转换shift=scale=所需的类型:

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 总是感谢人们提供帮助,所以如果你想把它变成一个拉取请求,请这样做!)

于 2019-12-27T23:08:10.693 回答
2

tfb.Sigmoid现在接受lowhigh参数,正如@Brian Patton 在评论中预测的那样。

因此,代码可以简化为:

from tensorflow_probability import bijectors as tfb

def bounded_lengthscale(low, high, lengthscale):
    """Make lengthscale tfp Parameter with optimization bounds."""
    sigmoid = tfb.Sigmoid(low, high)
    parameter = gpflow.Parameter(lengthscale, transform=sigmoid, dtype='float32')
    return parameter

m.kernel.lengthscale = bounded_lengthscale(0, 1, 0.5)
于 2021-06-28T14:57:53.903 回答