Определение пользовательского слоя может несколько раз запутать. Некоторые из методов, которые вы переопределяете, будут вызываться один раз, но создается впечатление, что, как и многие другие библиотеки / платформы OO, они будут вызываться много раз.
Вот что я имею в виду: Когда вы определяете слой и используете его в модели, код python, который вы пишете для переопределения метода call
, не будет вызываться напрямую при прямой или обратной передаче. Вместо этого он вызывается только один раз, когда вы звоните model.compile
. Он компилирует код python в вычислительный граф, и тот граф, в котором будут течь тензоры, - это то, что выполняет вычисления во время обучения и прогнозирования.
Вот почему, если вы хотите отладить свою модель, поставив print
заявление, что это не сработает; вам нужно использовать tf.print
, чтобы добавить команду печати к графику.
Это та же самая ситуация с переменной состояния, которую вы хотите иметь. Вместо простого присвоения old + update
для new
вам нужно вызвать функцию Keras, которая добавляет эту операцию к графу.
И обратите внимание, что тензоры являются неизменяемыми, поэтому вам нужно определить состояние как tf.Variable
в __init__
метод.
Так что я считаю, что этот код больше похож на то, что вы ищете:
class CustomLayer(tf.keras.layers.Layer):
def __init__(self, **kwargs):
super(CustomLayer, self).__init__(**kwargs)
self.state = tf.Variable(tf.zeros((3,3), 'float32'))
self.constant = tf.constant([[1,1,1],[1,0,-1],[-1,0,1]], 'float32')
self.extra_constant = tf.constant([[1,1,1],[1,0,-1],[-1,0,1]], 'float32')
self.trainable = False
def call(self, X):
m = self.constant
c = self.extra_constant
outputs = self.state + tf.matmul(X, m) + c
tf.keras.backend.update(self.state, tf.reduce_sum(outputs, axis=0))
return outputs