Я хотел бы получить градиент функции потерь модели относительно заданного c вывода слоя во время обучения. Далее я хочу использовать значение этого градиента для изменения чего-либо в слое в следующей эпохе обучения. Итак, как получить этот градиент?
Вот минимальный пример. Код MinimalRNNCell копируется с веб-сайта TensorFlow, а данные игрушки предоставляются только для воспроизведения поведения.
import tensorflow as tf
from tensorflow.keras.layers import RNN, SimpleRNNCell, SimpleRNN, Layer, Dense, AbstractRNNCell
from tensorflow.keras import Model
import numpy as np
import tensorflow.keras.backend as K
class MinimalRNNCell(AbstractRNNCell):
def __init__(self, units, **kwargs):
self.units = units
super(MinimalRNNCell, self).__init__(**kwargs)
@property
def state_size(self):
return self.units
def build(self, input_shape):
self.kernel = self.add_weight(shape=(input_shape[-1], self.units),
initializer='uniform',
name='kernel')
self.recurrent_kernel = self.add_weight(
shape=(self.units, self.units),
initializer='uniform',
name='recurrent_kernel')
self.built = True
def call(self, inputs, states):
prev_output = states[0]
h = K.dot(inputs, self.kernel)
output = h + K.dot(prev_output, self.recurrent_kernel)
return output, output
class MyModel(Model):
def __init__(self, size):
super(MyModel, self).__init__()
self.minimalrnn=RNN(MinimalRNNCell(size), name='minimalrnn')
self.out=Dense(4)
def call(self, inputs):
out=self.minimalrnn(inputs)
out=self.out(out)
return out
x=np.array([[[3.],[0.],[1.],[2.],[3.]],[[3.],[0.],[1.],[2.],[3.]]])
y=np.array([[[0.],[1.],[2.],[3.]],[[0.],[1.],[2.],[3.]]])
model=MyModel(2)
model.compile(optimizer='sgd', loss='mse')
model.fit(x,y,epochs=10, batch_size=1, validation_split=0.2)
Теперь я хочу получить градиент вывода слоя minimalrnn MyModel (после каждой партии данных).
Как это сделать? Я полагаю, что я могу попробовать с GradientTape смотреть модель.get_layer ('minimalrnn'). Output, но мне нужно больше учебных ресурсов или примеров.
РЕДАКТИРОВАТЬ
Я использовал GradientTape как в коде, предоставленном Tia go Martins Peres, но я специально хочу получить вывод градиентного слоя, и я до сих пор не в состоянии достичь этого.
Теперь после определения классов мой код выглядит следующим образом:
x=np.array([[[3.],[0.],[1.],[2.],[3.]],[[3.],[0.],[1.],[2.],[3.]]])
y=np.array([[0., 1., 2., 3.],[0., 1., 2., 3.]])
model=MyModel(2)
#inputs = tf.keras.Input(shape=(2,5,1))
#model.call(x)
def gradients(model, inputs, targets):
with tf.GradientTape() as tape:
tape.watch(model.get_layer('minimalrnn').output)
loss_value = loss_fn(model, inputs, targets)
return tape.gradient(loss_value, model.trainable_variables)
def loss_fn(model, inputs, targets):
error = model(inputs) - targets
return tf.reduce_mean(tf.square(error))
optimizer = tf.keras.optimizers.Adam(learning_rate=0.01)
print("Initial loss: {:.3f}".format(loss_fn(model, x, y)))
for i in range(10):
grads = gradients(model, x, y)
optimizer.apply_gradients(zip(grads, model.trainable_variables))
print("Loss at step {:03d}: {:.3f}".format(i, loss_fn(model, x, y)))
print("Final loss: {:.3f}".format(loss_fn(model, x, y)))
Как вы можете видеть, я добавил tape.watch в определение функции градиентов, потому что я хочу наблюдать за выводом слоя. Однако я получаю сообщение об ошибке:
Traceback (most recent call last):
File "/home/.../test2.py", line 73, in <module>
grads = gradients(model, x, y)
File "/home/.../test2.py", line 58, in gradients
print(model.get_layer('minimalrnn').output)
File "/home/.../.venv/lib/python3.6/site-packages/tensorflow_core/python/keras/engine/base_layer.py", line 1553, in output
raise AttributeError('Layer ' + self.name + ' has no inbound nodes.')
AttributeError: Layer minimalrnn has no inbound nodes.
Я также пытался вызвать модель на входе с указанным размером (закомментированные строки), в соответствии с ответом на этот вопрос: Доступ к вводу / выводу слоя с использованием модели Tensorflow 2.0 Sub-причислять . Это не помогло. Указание формы ввода в функции инициализации модели, как показано ниже, также не помогает - все та же ошибка.
self.minimalrnn=RNN(MinimalRNNCell(size), name='minimalrnn', input_shape=(2,5,1))