Как получить градиенты в керасе?

Я пытаюсь отладить 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, принимая входные / выходные данные в качестве входных данных и возвращая градиенты. Вот рабочий пример:

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

Другие вопросы по тегам