Все еще не уверен, что я точно понимаю, что здесь происходит, но, по крайней мере, я могу заставить свой пример работать сейчас.
По какой-то причине поведение будет другим, если я заключу его в класс, унаследованный от tf.keras.Model:
class BijectorModel(tf.keras.Model):
def __init__(self):
super().__init__()
self.shift = tf.Variable(initial_value=tf.convert_to_tensor([1.5], dtype=tf.float32), trainable=True, name='shift_var')
self.bijector = tfp.bijectors.Shift(shift=self.shift)
def call(self, input):
return self.bijector(input)
Я сделал функцию для обучающей итерации, хотя в этом нет необходимости:
def training_iteration(model, input, target):
optimizer = tf.optimizers.SGD(learning_rate=0.1)
with tf.GradientTape() as tape:
loss = tf.math.square(tf.math.abs(model(input) - target))
gradients = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))
Выполнение как это
x = tf.convert_to_tensor(np.array([0]), dtype=tf.float32)
target = tf.convert_to_tensor(np.array([2]), dtype=tf.float32)
model = BijectorModel()
nsteps = 10
for _ in range(nsteps):
training_iteration(model, x, target)
print('Iteration {}: Output {}'.format(_, model(x)))
дает ожидаемый / желаемый результат:
Iteration 0: Output [1.6]
Iteration 1: Output [1.6800001]
Iteration 2: Output [1.7440001]
Iteration 3: Output [1.7952001]
Iteration 4: Output [1.8361601]
Iteration 5: Output [1.8689281]
Iteration 6: Output [1.8951424]
Iteration 7: Output [1.916114]
Iteration 8: Output [1.9328911]
Iteration 9: Output [1.9463129]
Я пришел к выводу, что обучаемые переменные обрабатываются иначе, когда они являются частью модели, по сравнению с доступом через объект-биектор.