#tensorflow #keras #optimization #neural-network #tensorflow2.0
Вопрос:
В настоящее время я пытаюсь реализовать состязательное обучение с прогнозируемым градиентным спуском в tensorflow2. Поэтому я хочу итеративно рассчитать градиент отрицательных потерь, т. е. текущую итерацию, а затем изменить мою партию, двигаясь в направлении отрицательного градиента.
Поэтому я адаптировал пример из https://www.tensorflow.org/guide/keras/customizing_what_happens_in_fit и попытался перезаписать train_step
метод. Это, однако, выдает мне следующее сообщение об ошибке, которое, как я думаю, отключает выполнение графика в tensorflow и запускает код в режиме быстрого выполнения:
E tensorflow/core/grappler/optimizers/meta_optimizer.cc:808] layout failed: Invalid argument: MutableGraphView::SortTopologically error: detected edge(s) creating cycle(s) {'while/body/_1/while/clip_by_value' -> 'while/body/_1/while/Identity_2', 'while/body/_1/while/AssignAddVariableOp' -> 'while/body/_1/while/Identity_2', 'Func/while/body/_1/output_control_node/_97' -> 'while/next_iteration/_43', 'while/body/_1/while/AssignAddVariableOp_1' -> 'while/body/_1/while/Identity_2'}.
Чего я не понимаю, так это почему возникает эта ошибка. Без сверточного слоя сообщение об ошибке исчезает, а также при установке descent_direction
в теле цикла tf.zeros
значения . Является ли мой подход просто неправильным? Что я могу сделать, чтобы это сработало? Я действительно не понимаю, как работают оптимизаторы захвата. Любая помощь будет признательна.
Мой код следующий (я только добавил tf.while_loop()
в train_step()
):
import tensorflow as tf
class CustomModel(tf.keras.Model):
def __init__(self):
super(CustomModel, self).__init__()
self.sequential = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10)
])
def call(self, inputs):
return self.sequential(inputs)
def train_step(self, data):
x, y = data
tol = 1e-7
max_iterations = 5
epsilon = 0.09
sigma = 10.0
x_lower = tf.clip_by_value(tf.subtract(x, epsilon), 0, 1)
x_upper = tf.clip_by_value(tf.add(x, epsilon), 0, 1)
def pgd_iterations_cond(xk, gradients_xk):
"""Should be a stopping criterion depending on the gradient."""
return True
def pgd_iterations_body(xk, gradients_xk):
"""Calculate gradient w.r.t. current iterate xk and do projected step of size sigma in descent direction."""
with tf.GradientTape() as tape:
tape.watch(xk)
y_pred = self(xk, training=True)
loss = self.compiled_loss(y, y_pred, regularization_losses=self.losses)
neg_loss = tf.negative(loss)
gradients_xk_step = tape.gradient(neg_loss, xk)
descent_direction = tf.negative(gradients_xk_step)
xk_step = tf.add(xk, tf.scalar_mul(sigma, descent_direction))
xk_step = tf.clip_by_value(xk_step, x_lower, x_upper)
return xk_step, gradients_xk_step
gradients_x = tf.ones_like(x)
x_perturbed, _ = tf.while_loop(pgd_iterations_cond, pgd_iterations_body, [x, gradients_x],
maximum_iterations=max_iterations)
with tf.GradientTape() as tape:
y_pred = self(x_perturbed, training=True)
loss = self.compiled_loss(y, y_pred, regularization_losses=self.losses)
trainable_vars = self.trainable_variables
gradients = tape.gradient(loss, trainable_vars)
self.optimizer.apply_gradients(zip(gradients, trainable_vars))
self.compiled_metrics.update_state(y, y_pred)
return {m.name: m.result() for m in self.metrics}
if __name__ == "__main__":
mnist = tf.keras.datasets.mnist
(x_train, y_train), _ = mnist.load_data()
x_train = x_train / 255.0
x_train = x_train[..., tf.newaxis].astype('float32')
Model = CustomModel()
loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
Model.compile(optimizer='adam',
loss=loss_fn,
metrics=['accuracy'])
Model.fit(x_train, y_train, epochs=5)
РЕДАКТИРОВАТЬ: На случай, если кто-то хочет знать: Не смог решить эту проблему таким образом, пришлось написать свой собственный цикл обучения, и ошибка исчезла.