如何在Tensorflow中创建优化器

28

我希望在Tensorflow上为我的网络编写一个新的优化算法。 我希望实现Levenberg Marquardt 优化算法,尽管它现在已被排除在TF API之外。 我发现很少关于如何编写自定义优化器的文档,所以我想问问是否有人可以给我一些建议。 谢谢。


阻尼因子与张量流无关。神经网络不需要岭回归......我不理解这个社区。发表一个好的深奥问题 +1。对我来说,提供一个好的答案需要一些学习,而这正是我最喜欢的 SO 方面。 - kpie
1
你是否曾经成功地在TensorFlow中创建了自定义优化器?如果你有通过Github或其他方式分享代码的链接,那将非常有帮助! - Charlie Parker
1
如果您想制作在TensorFlow语言接口之间(可能)更快且可重复使用的优化器,那么dga的答案很有用。但是,如果您只想在Python中实现优化器以供Python使用,请查看ExternalOptimizerInterface:https://www.tensorflow.org/api_docs/python/tf/contrib/opt/ExternalOptimizerInterface - hydronium
你最终实现了目标吗?我也想做同样的事情,愿意听听你的经验,Alberto。谢谢。 - Hamed MP
2个回答

18

最简单的优化器例子可能是梯度下降优化器。它展示了如何创建基本优化器类的实例。优化器基类文档解释了方法的作用。

优化器的Python部分添加了新节点到计算和应用反向传播梯度的图中。它提供传递给操作的参数,并进行一些优化器的高级管理。然后,您需要实际的“应用”操作。

操作具有Python和C++组件。编写训练操作与将操作添加到TensorFlow的一般过程相同(但是是专门的)。

例如一组训练操作,用于计算和应用梯度,请参见python/training/training_ops.py - 这是实际训练操作的Python粘合剂。请注意,这里的代码大多涉及形状推断 - 计算将在C++中进行。

应用梯度的实际数学由Op处理(回想一下,一般来说,ops是用C++编写的)。在这种情况下,应用梯度ops在core/kernels/training_ops.cc中定义。您可以在其中看到ApplyGradientDescentOp的实现,它引用了一个函数对象ApplyGradientDescent:

var.device(d) -= grad * lr();

该Op的实现遵循其他Op的实现方式,如添加Op文档中所述。

2
感谢你的解释。这是为什么要用C ++吗?我不明白如何在C ++中组合这个简单计算(标量乘法和逐元素减法)比在Python中快得多。对于原型优化器,使用Python做所有事情可能会很有用。你知道是否可以实现吗? - danijar
2
@danijar,简单的原因是Python只是Tensorflow可用接口之一。在C++中实现核心机制有助于为其他语言创建接口。 - Zhe Chen
1
抱歉,TensorFlow的代码非常密集而且令人困惑。那么在代码中确切地可以找到apply_gradient操作在进行什么数学运算呢?例如,我正在阅读https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/training/optimizer.py,但它似乎没有任何数学表达式,梯度下降优化器的代码https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/training/gradient_descent.py也是一样。我在哪里可以看到如何使用apply gradient呢? - Charlie Parker
2
这个文件提供了一个很好的例子,展示了如何在Python中实现一个优化器类:https://github.com/openai/iaf/blob/master/tf_utils/adamax.py - hydronium

11

在运行TensorFlow会话之前,应按照以下所示初始化一个优化器

# Gradient Descent
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)

tf.train.GradientDescentOptimizerGradientDescentOptimizer类的一个对象,它实现了梯度下降算法。

方法minimize()带有“cost”参数,并由两个方法compute_gradients()apply_gradients()组成。

对于大多数(自定义)优化器实现,需要调整方法apply_gradients()

该方法依赖于新的优化器(类),我们将创建并实现以下方法:_create_slots(),_prepare(),_apply_dense()和_apply_sparse()

  • _create_slots()_prepare()创建和初始化其他变量,例如动量。

  • _apply_dense()_apply_sparse()实现实际的操作,更新变量。

操作通常是用C++编写的。通过这些方法,您仍然可以返回一些操作的Python包装器而无需更改C++头文件。实现如下:

def _create_slots(self, var_list):
   # Create slots for allocation and later management of additional 
   # variables associated with the variables to train.
   # for example: the first and second moments.
   '''
   for v in var_list:
      self._zeros_slot(v, "m", self._name)
      self._zeros_slot(v, "v", self._name)
   '''
def _apply_dense(self, grad, var):
   #define your favourite variable update
    # for example:
   '''
   # Here we apply gradient descents by substracting the variables 
   # with the gradient times the learning_rate (defined in __init__)
   var_update = state_ops.assign_sub(var, self.learning_rate * grad) 
   '''
   #The trick is now to pass the Ops in the control_flow_ops and 
   # eventually groups any particular computation of the slots your 
   # wish to keep track of:
   # for example:    
   '''
    m_t = ...m... #do something with m and grad
    v_t = ...v... # do something with v and grad
    '''
  return control_flow_ops.group(*[var_update, m_t, v_t])

如需更详细的解释和示例,请参阅此博客文章 https://www.bigdatarepublic.nl/custom-optimizer-in-tensorflow/


1
嗨@cyboroid,我不确定你如何使用这些类。这是一个快速的colab笔记本,使用了那篇博客文章中的代码。https://colab.research.google.com/drive/1pxnSn47taAxg7aRV374pipcstJJNtJ-t - Benoit Descamps
谢谢。我回复晚了,但你的笔记本起作用了,我不确定我做错了什么。看起来和我做的完全一样。 - Astra Uvarova - Saturn's star
@BenoitDescamps,您能否分享一个在TensorFlow 2.0中实现此功能的示例? - S.Perera

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接