Как получить вторые производные функции Loss по параметрам нейронной сети, используя градиентную ленту в режиме Tensorflow eager - PullRequest
1 голос
/ 23 марта 2019

Я создаю базовый авто-кодировщик для набора данных MNIST, используя режим ожидания TensorFlow. Я хотел бы наблюдать частные производные второго порядка моей функции потерь по параметрам сети, когда она обучается. В настоящее время вызов tape.gradient() на выходе in_tape.gradient возвращает None (где in_tape - это GradientTape, вложенное во внешнюю GradientTape ленту, я включил мой код ниже)

Я пытался позвонить tape.gradient() прямо на in_tape.gradient(), при этом значение None не возвращалось. Мой следующий подход состоял в том, чтобы перебрать вывод in_tape.gradient() и применить tape.gradient() к каждому градиенту индивидуально (относительно переменных моей модели) с None, возвращаемым каждый раз.

Я получаю одно значение None для любого вызова tape.gradient(), а не список значений None, которые, как я полагаю, будут указывать None для одной частной производной, что в некоторых случаях ожидается.

В настоящее время я только пытаюсь получить вторые производные для первого набора весов (от ввода до скрытых слоев), однако я масштабирую его, чтобы включить все веса, как только у меня будет эта работа.

tf.enable_eager_execution()

mnist = keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = train_images.reshape((train_images.shape[0], train_images.shape[1]*train_images.shape[2])).astype(np.float32)/255
test_images = test_images.reshape((test_images.shape[0], test_images.shape[1]*test_images.shape[2])).astype(np.float32)/255

num_epochs = 200
batch_size = 100
learning_rate = 0.0003

class MNISTModel(tf.keras.Model):
    def __init__(self, device='/gpu:0'):
        super(MNISTModel, self).__init__()
        self.device = device
        self.initializer = tf.initializers.random_uniform(0.0, 0.5)
        self.hidden = tf.keras.layers.Dense(200, use_bias=False, kernel_initializer=tf.initializers.random_uniform(0.0, 0.5), name="Hidden")
        self.out = tf.keras.layers.Dense(train_images.shape[1], use_bias=False, kernel_initializer=tf.initializers.random_uniform(0.0, 0.5), name="Output")
        self.hidden.build(train_images.shape[1])
        self.out.build(200)

    def call(self, x):
        return self.out(self.hidden(x))

def loss_func(model, x, y_):
    return tf.reduce_mean(tf.losses.mean_squared_error(labels=y_, predictions=model(x)))
    #return tf.reduce_mean((y_ - model(x))**4)

model = MNISTModel()
optimizer = tf.train.GradientDescentOptimizer(learning_rate)

for epochs in range(num_epochs):
    print("Started epoch ", epochs)
    print("Num batches is: ", train_images.shape[0]/batch_size)
    for i in range(0,1): #(int(train_images.shape[0]/batch_size)):
        with tfe.GradientTape(persistent=True) as tape:
            tape.watch(model.variables)
            with tfe.GradientTape() as in_tape:
                in_tape.watch(model.variables)
                loss = loss_func(model,train_images[0:batch_size],train_images[0:batch_size])
        grads = tape.gradient(loss, model.variables)
        IH_partial_grads = np.array([]) 
        for i in range(len(grads[0])):
            collector = np.array([])
            for j in range(len(grads[0][i])):
                collector = np.append(collector, tape.gradient(grads[0][i][j], model.variables[0]))
            IH_partial_grads = np.append(IH_partial_grads, collector)
        optimizer.apply_gradients(zip(grads, model.variables), global_step=tf.train.get_or_create_global_step())
    print("Epoch test loss: ", loss_func(model, test_images, test_images))

Моя конечная цель - сформировать гессенскую матрицу для функции потерь по всем параметрам моей сети.

Спасибо за любую помощь!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...