Отладка промежуточного слоя keras или объектных переменных с помощью тензорного потока
Я пишу пользовательскую задачу по обучению модели Keras (с тензорным потоком), но мне нужно отлаживать некоторые промежуточные вычисления. Для простоты позвольте сказать, что у меня есть:
def custom_loss(y_pred, y_true):
diff = y_pred - y_true
return K.square(diff)
Я не мог найти простой способ доступа, например, промежуточную переменную diff или ее форму во время обучения. В этом простом примере я знаю, что я могу вернуть diff для печати своих значений, но мои фактические потери сложнее, и я не могу вернуть промежуточные значения, не получая компиляцию ошибок.
Есть ли простой способ отладки промежуточных переменных в Keras?
Ответы
Ответ 1
Насколько я знаю, это не то, что разрешено в Keras, поэтому вам нужно прибегать к функциональности, зависящей от бэкэнд. Оба Theano и TensorFlow имеют узлы Print
которые являются узлами идентификации (т.е. Возвращают входной узел) и имеют побочный эффект печати ввода (или некоторого тензора входа).
Пример для Theano:
diff = y_pred - y_true
diff = theano.printing.Print('shape of diff', attrs=['shape'])(diff)
return K.square(diff)
Пример для TensorFlow:
diff = y_pred - y_true
diff = tf.Print(diff, [tf.shape(diff)])
return K.square(diff)
Обратите внимание, что это работает только для промежуточных значений. Keras ожидает, что тензоры, которые передаются другим слоям, имеют определенные атрибуты, такие как _keras_shape
. Значения, обрабатываемые бэкэнд, то есть через Print
, обычно не имеют этого атрибута. Чтобы решить эту проблему, вы можете, например, обернуть операторы отладки в слое Lambda
.
Ответ 2
В TensorFlow 2 теперь можно добавлять точки останова IDE в модели/слои/потери TensorFlow Keras, в том числе при использовании методов подбора, оценки и прогнозирования. Однако вы должны добавить model.run_eagerly = True
после вызова model.compile()
, чтобы значения тензора были доступны в отладчике в точке останова. Например,
import tensorflow as tf
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
def custom_loss(y_pred, y_true):
diff = y_pred - y_true
return tf.keras.backend.square(diff) # Breakpoint in IDE here. =====
class SimpleModel(Model):
def __init__(self):
super().__init__()
self.dense0 = Dense(2)
self.dense1 = Dense(1)
def call(self, inputs):
z = self.dense0(inputs)
z = self.dense1(z)
return z
x = tf.convert_to_tensor([[1, 2, 3], [4, 5, 6]], dtype=tf.float32)
y = tf.convert_to_tensor([0, 1], dtype=tf.float32)
model0 = SimpleModel()
model0.run_eagerly = True
model0.compile(optimizer=Adam(), loss=custom_loss)
y0 = model0.fit(x, y, epochs=1) # Values of diff *not* shown at breakpoint. =====
model1 = SimpleModel()
model1.compile(optimizer=Adam(), loss=custom_loss)
model1.run_eagerly = True
y1 = model1.fit(x, y, epochs=1) # Values of diff shown at breakpoint. =====
Это также работает для отладки выходов промежуточных сетевых уровней (например, добавление точки останова в call
SimpleModel).
Примечание: это было проверено в TensorFlow 2.0.0-rc0
.