为什么GPflow模型似乎没有从TensorFlow优化器(如tf.optimizers.Adam)中学到任何东西?



我的诱导点设置为可训练,但当我调用opt.minimize()时不会改变。为什么会这样,这意味着什么?这是否意味着模型没有学习?tf.optimizers.Adam(lr)gpflow.optimizers.Scipy有什么区别?

以下是根据文档改编的简单分类示例。当我使用 gpflow 的 Scipy 优化器运行此代码示例时,我得到了训练结果,并且诱导变量的值不断变化。但是当我使用亚当优化器时,我只得到一条直线预测,并且诱导点的值保持不变。它表明模型没有使用 Adam 优化器学习。

训练前的数据图

与亚当一起训练后的数据图

使用 gpflow 优化器 Scipy 训练后的数据图

该示例的链接 https://gpflow.readthedocs.io/en/develop/notebooks/advanced/multiclass_classification.html

import numpy as np
import tensorflow as tf

import warnings
warnings.filterwarnings('ignore')  # ignore DeprecationWarnings from tensorflow
import matplotlib.pyplot as plt
import gpflow
from gpflow.utilities import print_summary, set_trainable
from gpflow.ci_utils import ci_niter
from tensorflow2_work.multiclass_classification import plot_posterior_predictions, colors
np.random.seed(0)  # reproducibility
# Number of functions and number of data points
C = 3
N = 100
# RBF kernel lengthscale
lengthscale = 0.1
# Jitter
jitter_eye = np.eye(N) * 1e-6
# Input
X = np.random.rand(N, 1)
kernel_se = gpflow.kernels.SquaredExponential(lengthscale=lengthscale)
K = kernel_se(X) + jitter_eye
# Latents prior sample
f = np.random.multivariate_normal(mean=np.zeros(N), cov=K, size=(C)).T
# Hard max observation
Y = np.argmax(f, 1).reshape(-1,).astype(int)
print(Y.shape)
# One-hot encoding
Y_hot = np.zeros((N, C), dtype=bool)
Y_hot[np.arange(N), Y] = 1
data = (X, Y)
plt.figure(figsize=(12, 6))
order = np.argsort(X.reshape(-1,))
print(order.shape)
for c in range(C):
plt.plot(X[order], f[order, c], '.', color=colors[c], label=str(c))
plt.plot(X[order], Y_hot[order, c], '-', color=colors[c])

plt.legend()
plt.xlabel('$X$')
plt.ylabel('Latent (dots) and one-hot labels (lines)')
plt.title('Sample from the joint $p(Y, mathbf{f})$')
plt.grid()
plt.show()

# sum kernel: Matern32 + White
kernel = gpflow.kernels.Matern32() + gpflow.kernels.White(variance=0.01)
# Robustmax Multiclass Likelihood
invlink = gpflow.likelihoods.RobustMax(C)  # Robustmax inverse link function
likelihood = gpflow.likelihoods.MultiClass(C, invlink=invlink)  # Multiclass likelihood
Z = X[::5].copy()  # inducing inputs
#print(Z)
m = gpflow.models.SVGP(kernel=kernel, likelihood=likelihood,
inducing_variable=Z, num_latent_gps=C, whiten=True, q_diag=True)
# Only train the variational parameters
set_trainable(m.kernel.kernels[1].variance, True)
set_trainable(m.inducing_variable, True)
print(m.inducing_variable.Z)
print_summary(m)

training_loss = m.training_loss_closure(data) 
opt.minimize(training_loss, m.trainable_variables)
print(m.inducing_variable.Z)
print_summary(m.inducing_variable.Z)

print(m.inducing_variable.Z)
# %%
plot_posterior_predictions(m, X, Y)

问题中给出的示例不可复制和粘贴,但似乎您只需与opt = tf.optimizers.Adam()交换opt = gpflow.optimizers.Scipy()。gpflow 的 Scipy 优化器的minimize()方法运行一次 scipy.optimize.minimize 调用,默认情况下运行到收敛(您还可以通过传递(例如,options=dict(maxiter=100)次 minimize(( 调用来指定最大迭代次数(。

相比之下,TensorFlow 优化器的minimize()方法只运行一个优化步骤。要运行更多步骤,例如iter = 100,您需要手动编写一个循环:

for _ in range(iter):
opt.minimize(model.training_loss, model.trainable_variables)

为了真正快速运行,您还需要将优化步骤包装在tf.function中:

@tf.function
def optimization_step():
opt.minimize(model.training_loss, model.trainable_variables)
for _ in range(iter):
optimization_step()

这完全iter运行步骤 - 在 TensorFlow 中,您必须自己处理收敛检查,经过这么多步骤后,您的模型可能会也可能不会收敛。

因此,在您的使用中,您只运行了一个步骤 - 这确实更改了参数,但可能太少而无法注意到差异。(通过提高学习率,您可以在一个步骤中看到更大的效果,尽管这对于实际优化具有许多步骤的模型来说不是一个好主意。

Adam优化器与GPflow模型的用法在随机变分推理的笔记本中进行了演示,尽管它也适用于非随机优化。

请注意,在任何情况下,默认情况下,所有参数(如诱导点位置(都是可训练的,因此您对set_trainable(..., True)的调用不会影响此处发生的事情。

最新更新