如何在Keras中找到自定义模型的派生词? [英] How do I find the derivative of a custom model in Keras?

查看:129
本文介绍了如何在Keras中找到自定义模型的派生词?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义模型,该模型采用任意隐藏模型"作为输入,并将其包装在另一个张量中,该张量将隐藏模型的输出视为返回值,并通过将1乘以原始输出来计算隐式输出数据:

I have a custom model that takes an arbitrary "hidden model" as an input and wraps it in another tensor that treats the output of the hidden model as a return and computes the implied output by adding 1 and multiplying it by the original data:

class Model(tf.keras.Model):
    def __init__(self, hidden_model):
        super(Model, self).__init__(name='')
        self.hidden_model = hidden_model

    def build(
        self,
        reference_price_shape,
        hidden_inputs_shape):

        super(Model, self).build([reference_price_shape, hidden_inputs_shape])

    def call(self, inputs):
        reference_prices = inputs[0]
        hidden_layers_input = inputs[1]
        hidden_output = self.hidden_model(hidden_layers_input)
        return (hidden_output + 1) * reference_prices

    def compute_output_shape(self, input_shape):
        return (input_shape[0][0], 1)

但是,我现在想知道模型对每个输入变化的敏感程度.为此,我认为我可以使用keras.backend.gradients:

However, I'd now like to know how sensitive the model is to changes in each of the inputs. To do this I thought I'd be able to use the keras.backend.gradients:

rows = 10
cols = 2

hidden_model = tf.keras.Sequential()

hidden_model.add(
    tf.keras.layers.Dense(
        1,
        name='output',
        use_bias=True,
        kernel_initializer=tf.constant_initializer(0.1),
        bias_initializer=tf.constant_initializer(0)))

model = Model(hidden_model)
model.build(
    reference_price_shape=(rows,),
    hidden_inputs_shape=(rows, cols))

from tensorflow.keras import backend as K
grads = K.gradients(model.output, model.input)

但是,这将返回错误:

--------------------------------------------------- ---------------------------- RuntimeError Traceback(最近一次调用 最后) 来自TensorFlow导入Keras的1个 来自tensorflow.keras的2将后端导入为K ----> 3个K.gradients(hidden_​​model.output,hidden_​​model.input)

--------------------------------------------------------------------------- RuntimeError Traceback (most recent call last) in 1 from tensorflow import keras 2 from tensorflow.keras import backend as K ----> 3 K.gradients(hidden_model.output, hidden_model.input)

/usr/lib64/python3.6/site-packages/tensorflow_core/python/keras/backend.py 渐变(损失,变量)3795""3796返回 gradients_module.gradients( -> 3797损失,变量,colocate_gradients_with_ops = True)3798 3799

/usr/lib64/python3.6/site-packages/tensorflow_core/python/keras/backend.py in gradients(loss, variables) 3795 """ 3796 return gradients_module.gradients( -> 3797 loss, variables, colocate_gradients_with_ops=True) 3798 3799

/usr/lib64/python3.6/site-packages/tensorflow_core/python/ops/gradients_impl.py 以渐变(ys,xs,grad_ys,名称,colocate_gradients_with_ops, gate_gradients,aggregation_method,stop_gradients, unconnected_gradients) 156 ys,xs,grad_ys,name,colocate_gradients_with_ops, 157 gate_gradients,aggregation_method,stop_gradients, -> 158个unconnected_gradients) 159#pylint:启用=受保护的访问 160

/usr/lib64/python3.6/site-packages/tensorflow_core/python/ops/gradients_impl.py in gradients(ys, xs, grad_ys, name, colocate_gradients_with_ops, gate_gradients, aggregation_method, stop_gradients, unconnected_gradients) 156 ys, xs, grad_ys, name, colocate_gradients_with_ops, 157 gate_gradients, aggregation_method, stop_gradients, --> 158 unconnected_gradients) 159 # pylint: enable=protected-access 160

/usr/lib64/python3.6/site-packages/tensorflow_core/python/ops/gradients_util.py 在_GradientsHelper(ys,xs,grad_ys,name, colocate_gradients_with_ops,gate_gradients,aggregation_method, stop_gradients,unconnected_gradients,src_graph) 503""gradients()的实现."" 504如果context.executing_eagerly(): -> 505提高RuntimeError(急于执行时不支持tf.gradients" 506已启用.请改用tf.GradientTape.") 507,如果src_graph为None:

/usr/lib64/python3.6/site-packages/tensorflow_core/python/ops/gradients_util.py in _GradientsHelper(ys, xs, grad_ys, name, colocate_gradients_with_ops, gate_gradients, aggregation_method, stop_gradients, unconnected_gradients, src_graph) 503 """Implementation of gradients().""" 504 if context.executing_eagerly(): --> 505 raise RuntimeError("tf.gradients is not supported when eager execution " 506 "is enabled. Use tf.GradientTape instead.") 507 if src_graph is None:

RuntimeError:当急于执行时不支持tf.gradients 已启用.改用tf.GradientTape.

RuntimeError: tf.gradients is not supported when eager execution is enabled. Use tf.GradientTape instead.

我查看了 tf.GradientTape的指南,基于此,我试图在代码中添加以下内容:

I had a look at the guide for tf.GradientTape, based on which I tried to add the following to my code:

with tf.GradientTape() as g:
  g.watch(x)

但是在哪里我要把它放在哪里? x是张量,我没有输入张量.我只有inputs,它是一个numpy数组.

But where do I put this? x is a tensor, and I don't have an input tensor. I just have inputs, which is an array of numpy arrays.

只是增加了混乱,在 github此处发布似乎暗示这是tensorflow 2.0错误,并且添加tf.compat.v1.disable_eager_execution()将为我解决问题.没错(尽管确实得到了以上错误,将其更改为Layer model_1 has no inbound nodes.-不知道这是向前还是向后迈了一步.)

Just to add to the confusion, there's a github post here that seems to suggest this is tensorflow 2.0 bug, and that adding tf.compat.v1.disable_eager_execution() will resolve the issue for me. It didn't (although it did get the above error to change to Layer model_1 has no inbound nodes. - not sure if that's a step forwards or backwards).

对不起,我意识到这个问题即将到来,但是我真的很困惑,这可能是我最好的解决办法.

Sorry I realise this question is bordering on untenable, but at this point I'm really confused and this is probably the best I can do at framing it as something answerable.

作为测试,我尝试使用hidden_model来运行K.gradients,这是可行的:

As a test I tried running K.gradients with hidden_model instead, which kind of worked:

但是我不知道该怎么做,因为我通常使用model.predict(input_data)运行模型-我应该如何使用该张量来获取局部导数?

But I don't know what to do with this, as I usually run my model using model.predict(input_data) - how am I supposed to get the local derivatives using that tensor?

所以我认为我有两个问题:

So I think I have two problems:

  1. 对于整个模型,我如何计算输出相对于输入的导数-一直以来都是张量,因此Keras/tensorflow确实应该能够应用链规则,即使使用我的自定义call()函数/模型也是如此.
  2. 一旦有了导数张量,我该怎么办?
  1. How do I calculate the derivative of my output with respect to my input for the whole model - it's tensors all the way through so Keras/tensorflow really should be able to apply the chain rule even with my custom call() function/model.
  2. Once I have the derivative tensor, what do I do with it?

最初,我认为我应该尝试将这些问题分开,但是一个人单独问可能是一个XY问题,所以我想我会一起问这些问题,以便为回答者提供一些背景信息.

I initially thought I should try to separate these questions, but either of them asked alone might be an XY problem so I thought I'd ask them together to give the answerers some context.

推荐答案

可能,但是需要一些工作(显然).希望看到更优雅的解决方案.但这比对我来说更好.

It is possible but requires some work (apparently). Would love to see a more elegant solution. But this is as better as it got for me.

import tensorflow as tf
from tensorflow.keras import backend as K
import numpy as np

rows = 10
cols = 2

with tf.Graph().as_default():


  hidden_model = tf.keras.Sequential()

  hidden_model.add(
      tf.keras.layers.Dense(
          1,
          name='output',
          use_bias=True,
          kernel_initializer=tf.constant_initializer(0.1),
          bias_initializer=tf.constant_initializer(0)))

  model = Model(hidden_model)
  model.build(
      reference_price_shape=(rows,),
      hidden_inputs_shape=(rows, cols))

请注意,模型构建需要在您尝试在其中获得梯度的同一张图中进行.可能不必是默认图形,而是相同的图形.

Note that, model building needs to happen in the same graph you try to get the gradients within. Probably doesn't need to be the default graph, but the same graph.

然后在图的相同上下文中,创建一个渐变磁带上下文.另外请注意,x必须是tf.Variable()才能注册为渐变的输入.

Then within the same context of the graph, create a gradient tape context. Also note that x needs to be a tf.Variable() in order to register as an input to a gradient.

  with tf.GradientTape() as tape:
    x = tf.Variable(np.random.normal(size=(10, rows, cols)), dtype=tf.float32)
    out = model(x)

有了它,您可以获得渐变.

With that you can get the gradients.

  grads = tape.gradient(out, x)

  sess = tf.compat.v1.keras.backend.get_session()
  sess.run(tf.compat.v1.global_variables_initializer())
  g = sess.run(grads)
  print(g)

这篇关于如何在Keras中找到自定义模型的派生词?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆