是否可以将Tensorflow Graphics的Levenberg-Marquardt优化器与Tensorflow 2



我有一个Tensorflow 2.0tf.keras.Sequential模型。现在,我的技术规范规定使用Levenberg-Marquardt优化器来拟合模型。Tensorflow 2.0并没有提供开箱即用的优化器,但它可以在Tensorflow Graphics模块中使用。

tfg.math.optimizer.levenberg_marquardt.minimize函数接受residuals(残差是返回张量的Pythoncallable(和variables(与我的模型权重相对应的张量列表(作为参数。

将我的模型转换为残差和变量的最佳方法是什么?

如果我正确理解minimize函数是如何工作的,我必须提供两个残差。第一个残差必须为每个学习案例调用我的模型,并将所有结果聚合到一个张量中。第二个残差必须将所有标签返回为单个常量张量。问题是tf.keras.Sequential.predict函数返回的是numpy数组,而不是张量。我相信,如果我把它转换成张量,最小化器将无法计算关于变量的雅可比。

变量也有同样的问题。似乎没有办法将模型中的所有权重提取到张量列表中。

从实现/API的角度来看,tfg.math.optimizer.levenberg_marquardt.minimize和Keras优化器之间有很大的区别。

Keras优化器,如tf.keras.optimizers.Adam,使用梯度作为输入并更新tf.Variables。

相反,tfg.math.optimizer.levenberg_marquardt.minimize本质上是以图形模式展开优化循环(使用tf.while_loop构造(。它获取初始参数值并生成更新的参数值,这与Adam&co,其仅应用一次迭代并通过assign_add实际改变tf.Variables的值。

回到理论大局,Levenberg-Marquardt不是任何非线性优化问题的一般梯度下降式求解器(比如Adam(。它专门针对非线性最小二乘优化,因此它不是像Adam这样的优化器的替代品。在梯度下降中,我们计算损失相对于参数的梯度。在Levenberg-Marquardt中,我们计算残差相对于参数的雅可比。具体地,它使用tf.linalg.lstsq(内部使用根据雅可比矩阵计算的Gram矩阵上的Cholesky分解(来重复求解delta_params的线性化问题Jacobian @ delta_params = residuals,并应用delta_params作为更新。

注意,这种lstsq运算在参数数量上具有三次复杂性,因此在神经网络的情况下,它只能应用于相当小的网络。

还要注意,Levenberg-Marquardt通常作为批处理算法应用,而不是像SGD那样的小型批处理算法,尽管没有什么可以阻止您在每次迭代中对不同的小型批进行LM迭代。

我认为你可能只能通过这样的东西从tfg的LM算法中得到一次迭代

from tensorflow_graphics.math.optimizer.levenberg_marquardt import minimize as lm_minimize
for input_batch, target_batch in dataset:
def residual_fn(trainable_params):
# do not use trainable params, it will still be at its initial value, since we only do one iteration of Levenberg Marquardt each time.
return model(input_batch) - target_batch
new_objective_value, new_params = lm_minimize(residual_fn, model.trainable_variables, max_iter=1)
for var, new_param in zip(model.trainable_variables, new_params):
var.assign(new_param)

相比之下,我相信下面的天真方法将不起作用在计算残差之前分配模型参数:

from tensorflow_graphics.math.optimizer.levenberg_marquardt import minimize as lm_minimize
dataset_iterator = ...
def residual_fn(params):
input_batch, target_batch = next(dataset_iterator)
for var, param in zip(model.trainable_variables, params):
var.assign(param)
return model(input_batch) - target_batch
final_objective, final_params = lm_minimize(residual_fn, model.trainable_variables, max_iter=10000)
for var, final_param in zip(model.trainable_variables, final_params):
var.assign(final_param)

主要的概念问题是residual_fn的输出与其输入params没有梯度,因为这种依赖关系通过tf.assign。但是,由于使用了在图形模式中不允许使用的构造,它甚至可能在此之前失败。

总的来说,我认为最好编写自己的LM优化器来处理tf.Variables,因为tfg.math.optimizer.levenberg_marquardt.minimize有一个非常不同的API,它不适合优化Keras模型参数,因为如果没有tf.assign,你就无法直接计算model(input, parameters) - target_value

最新更新