如何在Keras中获取梯度?

22

我正在尝试调试一个我构建的keras模型。看起来我的梯度爆炸了,或者有除以0之类的问题。检查各个梯度在反向传播过程中的情况会很方便。以下内容是理想的:

model.evaluate(np.array([[1,2]]), np.array([[1]])) #gives the loss
model.evaluate_gradient(np.array([[1,2]]), np.array([[1]]), layer=2) #gives the doutput/dloss at layer 2 for the given input
model.evaluate_weight_gradient(np.array([[1,2]]), np.array([[1]]), layer=2) #gives the dweight/dloss at layer 2 for the given input

1
我会查看这篇帖子这个Keras示例 - mpariente
1个回答

21
您需要创建一个符号化Keras函数,输入输入/输出并返回梯度。以下是一个工作示例:
import numpy as np
import keras
from keras import backend as K

model = keras.Sequential()
model.add(keras.layers.Dense(20, input_shape = (10, )))
model.add(keras.layers.Dense(5))
model.compile('adam', 'mse')

dummy_in = np.ones((4, 10))
dummy_out = np.ones((4, 5))
dummy_loss = model.train_on_batch(dummy_in, dummy_out)

def get_weight_grad(model, inputs, outputs):
    """ Gets gradient of model for given inputs and outputs for all weights"""
    grads = model.optimizer.get_gradients(model.total_loss, model.trainable_weights)
    symb_inputs = (model._feed_inputs + model._feed_targets + model._feed_sample_weights)
    f = K.function(symb_inputs, grads)
    x, y, sample_weight = model._standardize_user_data(inputs, outputs)
    output_grad = f(x + y + sample_weight)
    return output_grad


def get_layer_output_grad(model, inputs, outputs, layer=-1):
    """ Gets gradient a layer output for given inputs and outputs"""
    grads = model.optimizer.get_gradients(model.total_loss, model.layers[layer].output)
    symb_inputs = (model._feed_inputs + model._feed_targets + model._feed_sample_weights)
    f = K.function(symb_inputs, grads)
    x, y, sample_weight = model._standardize_user_data(inputs, outputs)
    output_grad = f(x + y + sample_weight)
    return output_grad


weight_grads = get_weight_grad(model, dummy_in, dummy_out)
output_grad = get_layer_output_grad(model, dummy_in, dummy_out)

我编写的第一个函数返回模型中的所有梯度,但很容易扩展它以支持层索引。然而,这可能是危险的,因为模型中任何没有权重的层都将被此索引忽略,并且您最终会在模型和梯度中得到不同的层索引。
我编写的第二个函数返回给定层输出的梯度,在那里,索引与模型中的索引相同,因此可以安全地使用它。

注意: 这适用于Keras 2.2.0以上版本,因为该版本包含了keras.engine的重大重构。


1
如何在后续使用K.function来获取实际输入的值? - Daniel Möller
3
如@DanielMöller所评论的,如果我提供特定的输入,这很有效,但通常您会希望在训练过程中记录和记录梯度(或它们的某些功能,例如它们的范数)。 我该如何做到这一点? - Alex
如果输入是一批样本,那么这两个函数返回的格式(形状)是什么?能否解释一下? - stochastic13
@Alex 这会是一个很好的独立问题。如果你发布这样一个问题并在这里链接它,我会点赞的。 - Him
1
我知道这个问题很老了,但是如果有多个输入和输出的网络,你会如何修改它?我的网络有两个输入和两个输出,还有两个损失函数。当我按原样应用此解决方案时,我会收到与不兼容大小相关的错误。 - Mastiff
1
@Mastiff 使用这个:[dummy_in1 dummy_in2] 代替 dummy_in。对于多个输出做同样的操作。 - Heaven

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