skipping layer in backpropagation in keras

Dal*_*eme 5 keras tensorflow keras-layer

I am using Keras with tensorflow backend and I am curious whether it is possible to skip a layer during backpropagation but have it execute in the forward pass. So here is what I mean

Lambda (lambda x: a(x))
Run Code Online (Sandbox Code Playgroud)

I want to apply a to x in the forward pass but I do not want a to be included in the derivation when the backprop takes place.

我试图找到解决方案,但找不到任何东西。有人可以帮我吗?

jde*_*esa 4

更新2

除此之外tf.py_func,现在还有关于如何添加自定义操作的官方指南


更新

请参阅此问题,了解纯粹用 Python 编写带有渐变的自定义操作而无需重建任何内容的示例。请注意,该方法有一些限制(请参阅 的文档tf.py_func)。


不完全是问题的解决方案,但仍然是一种答案,而且评论太长。

这甚至不是 Keras 问题,而是 TensorFlow 问题。每个操作都定义了自己的梯度计算,该计算在反向传播过程中使用。如果你真的想要这样的东西,你需要自己将操作实现到 TensorFlow 中(这不是一件容易的事)并定义你想要的梯度 - 因为你不能有“无梯度”,如果有的话它会是 1 或0(否则你无法继续反向传播)。TensorFlow 中有一个tf.NoGradient函数会导致操作传播零,但我不认为它意味着/可以在 TensorFlow 自己的内部结构之外使用。

更新

好的,更多一点背景知识。TensorFlow 图由操作构建,操作由内核实现;这基本上是一个 1 对 1 的映射,除了一个操作可能有一个 CPU 和一个 GPU 内核,因此存在差异。TensorFlow支持的操作集通常是静态的,我的意思是它可以随着新版本的变化而改变,但原则上你不能添加自己的操作,因为图的操作进入Protobuf序列化格式,所以如果你制作了自己的操作那么您将无法共享您的图表。然后使用宏REGISTER_OP(参见此处的示例)在 C++ 级别定义操作,并使用内核REGISTER_KERNEL_BUILDER(参见此处的示例)。

现在,渐变在哪里发挥作用?有趣的是,op 的梯度不是在 C++ 级别定义的;有一些操作(和内核)实现了其他操作的梯度(如果您查看之前的文件,您会发现名称以 结尾的操作/内核Grad),但是(据我所知)这些并不是明确的在这个级别上“链接”。操作及其梯度之间的关联似乎是在 Python 中定义的,通常是通过tf.RegisterGradient或 前面提到的tf.NoGradient(例如,参见此处,以 开头的 Python 模块gen_是在 C++ 宏的帮助下自动生成的);这些注册告知反向传播算法如何计算图的梯度。

那么,如何实际解决这个问题呢?那么,您需要在 C++ 中创建至少一个操作,并使用相应的内核来实现您的前向传递所需的计算。然后,如果您想要使用的梯度计算可以用现有的 TensorFlow 操作来表达(这是最有可能的),您只需要tf.RegisterGradient在 Python 中调用并在“标准”TensorFlow 中进行计算即可。这相当复杂,但好消息是这是可能的,甚至还有一个示例(尽管我认为他们有点忘记了其中的梯度注册部分)!正如您将看到的,该过程涉及将新的操作代码编译到一个库中(顺便说一句,我不确定其中是否可以在 Windows 上运行),然后从 Python 加载该库(显然这涉及到手动编译的痛苦过程) TensorFlowBazel的结合)。一个可能更现实的例子可以在TensorFlow Fold中找到,它是 TensorFlow 针对结构化数据的扩展,通过此处定义的调用 的宏这里注册(从一个)一个自定义操作,然后在 Python 中加载该库并注册其梯度这里通过他们自己定义的注册函数简单地调用( 的另一个名称)REGISTER_OPtf.NotDifferentiabletf.NoGradient

tldr:这相当困难,但可以做到,甚至还有几个例子。