是否可以将 Tensorflow Graphics 的 Levenberg-Marquardt 优化器与 Tensorflow 2.0 模型集成?

Vol*_*lov 5 tf.keras tensorflow2.0

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

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

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

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

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

isa*_*ndi 1

tfg.math.optimizer.levenberg_marquardt.minimize从实现/API 的角度来看,Keras 优化器和 Keras 优化器之间存在重大差异。

Keras 优化器,例如tf.keras.optimizers.Adam使用梯度作为输入和更新tf.Variable

相反,tfg.math.optimizer.levenberg_marquardt.minimize本质上是在图形模式下展开优化循环(使用tf.while_loop构造)。tf.Variable它采用初始参数值并生成更新的参数值,这与 Adam & co 不同,后者仅应用一次迭代并实际上通过更改 s 的值assign_add

回顾一下理论大局,Levenberg-Marquardt 并不是一个适用于任何非线性优化问题(例如 Adam)的通用梯度下降求解器。它专门解决非线性最小二乘优化问题,因此它不能直接替代 Adam 等优化器。在梯度下降中,我们计算损失相对于参数的梯度。在 Levenberg-Marquardt 中,我们计算残差相对于参数的雅可比行列式。具体来说,它重复解决使用Jacobian @ delta_params = residuals的线性化问题(内部使用根据雅可比行列式计算的格拉姆矩阵的 Cholesky 分解)并作为更新应用。delta_paramstf.linalg.lstsqdelta_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)
Run Code Online (Sandbox Code Playgroud)

相反,我相信在计算残差之前分配模型参数的情况下,以下简单的方法将不起作用:

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)
Run Code Online (Sandbox Code Playgroud)

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

总的来说,我认为最好编写自己的适用于 的 LM 优化器tf.Variables,因为tfg.math.optimizer.levenberg_marquardt.minimize它有一个非常不同的 API,并不真正适合优化 Keras 模型参数,因为如果model(input, parameters) - target_value没有tf.assign.