使用 Keras 获取模型输出 w.r.t 权重的梯度

Posted

技术标签:

【中文标题】使用 Keras 获取模型输出 w.r.t 权重的梯度【英文标题】:Getting gradient of model output w.r.t weights using Keras 【发布时间】:2017-01-26 10:59:24 【问题描述】:

我对使用 Keras API 的简单性构建强化学习模型很感兴趣。不幸的是,我无法提取输出相对于权重的梯度(不是错误)。我发现以下代码执行了类似的功能(Saliency maps of neural networks (using Keras))

get_output = theano.function([model.layers[0].input],model.layers[-1].output,allow_input_downcast=True)
fx = theano.function([model.layers[0].input] ,T.jacobian(model.layers[-1].output.flatten(),model.layers[0].input), allow_input_downcast=True)
grad = fx([trainingData])

任何关于如何计算模型输出相对于每一层权重的梯度的想法都将不胜感激。

【问题讨论】:

你有预付款吗?我使用类似的显着性函数收到以下错误:github.com/fchollet/keras/issues/1777#issuecomment-250040309 我在 Keras 上没有取得任何成功。但是,我已经能够使用 tensorflow 做到这一点。 github.com/yanpanlau/DDPG-Keras-TorcsCriticNetwork.py 使用 tensorflow 后端计算梯度,同时使用 Keras 实际构建网络架构 【参考方案1】:

要使用 Keras 获得模型输出相对于权重的梯度,您必须使用 Keras 后端模块。我创建了这个简单的示例来准确说明该怎么做:

from keras.models import Sequential
from keras.layers import Dense, Activation
from keras import backend as k


model = Sequential()
model.add(Dense(12, input_dim=8, init='uniform', activation='relu'))
model.add(Dense(8, init='uniform', activation='relu'))
model.add(Dense(1, init='uniform', activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

要计算梯度,我们首先需要找到输出张量。对于模型的输出(我最初提出的问题),我们只需调用 model.output。我们也可以通过调用model.layers[index].output找到其他层的输出梯度

outputTensor = model.output #Or model.layers[index].output

然后我们需要选择与梯度相关的变量。

  listOfVariableTensors = model.trainable_weights
  #or variableTensors = model.trainable_weights[0]

我们现在可以计算梯度。就这么简单:

gradients = k.gradients(outputTensor, listOfVariableTensors)

要实际运行给定输入的梯度,我们需要使用一点 Tensorflow。

trainingExample = np.random.random((1,8))
sess = tf.InteractiveSession()
sess.run(tf.initialize_all_variables())
evaluated_gradients = sess.run(gradients,feed_dict=model.input:trainingExample)

就是这样!

【讨论】:

我已经运行了这段代码(使用 theano 作为后端)并引发了以下错误:“TypeError: cost must be a scalar.”。我想知道,这可以通过与后端无关的方法来实现吗? Matt S,如何在不指定 sess.run 中的标签的情况下计算梯度? 我相信你的意思是'渐变 w.r.t.输出。' 这个解决方案的问题在于它没有解决如何在训练时从 Keras 中获取这些梯度的问题。当然,对于一些随机的玩具输入,我可以做你上面写的,但是如果我想要在 Keras 的 fit() 函数执行的实际训练步骤中计算的梯度,我该如何得到这些?它们不属于在 Keras 代码深处传递给 sess.run() 的 fetch 列表的一部分,所以除非我花一个月的时间来理解和重写 Keras 训练引擎,否则我无法拥有它们:/ @Alex,它们在优化器中。一些灵感:***.com/questions/51140950/…【参考方案2】:

下面的答案是交叉熵函数,你可以随意改变它。

outputTensor = model.output
listOfVariableTensors = model.trainable_weights
bce = keras.losses.BinaryCrossentropy()
loss = bce(outputTensor, labels)
gradients = k.gradients(loss, listOfVariableTensors)

sess = tf.InteractiveSession()
sess.run(tf.global_variables_initializer())
evaluated_gradients = sess.run(gradients,feed_dict=model.input:training_data1)
print(evaluated_gradients)

【讨论】:

以上是关于使用 Keras 获取模型输出 w.r.t 权重的梯度的主要内容,如果未能解决你的问题,请参考以下文章

如何在多个标签问题中为 tensorflow 模型设置类权重?

如何找出概率输出中每列的哪个类对应于使用Keras进行多类分类?

tf2.0 Keras:使用 RNN 的自定义张量流代码时无法保存权重

训练后使用量化权重进行 keras 模型评估

如何在 Keras 中重新初始化现有模型的层权重?

如何保存最佳 hyperopt 优化的 keras 模型及其权重?