Использование и изменение переменных в биекторах тензорного потока
В справочном документе по распределению TensorFlow (теперь вероятности) упоминается, что TensorFlow Variable
s может быть использован для построения Bijector
а также TransformedDistribution
объекты, то есть:
import tensorflow as tf
import tensorflow_probability as tfp
tfd = tfp.distributions
tf.enable_eager_execution()
shift = tf.Variable(1., dtype=tf.float32)
myBij = tfp.bijectors.Affine(shift=shift)
# Normal distribution centered in zero, then shifted to 1 using the bijection
myDistr = tfd.TransformedDistribution(
distribution=tfd.Normal(loc=0., scale=1.),
bijector=myBij,
name="test")
# 2 samples of a normal centered at 1:
y = myDistr.sample(2)
# 2 samples of a normal centered at 0, obtained using inverse transform of myBij:
x = myBij.inverse(y)
Теперь я хотел бы изменить переменную сдвига (скажем, я мог бы вычислить градиенты некоторой функции правдоподобия как функцию сдвига и обновить ее значение), поэтому я делаю
shift.assign(2.)
gx = myBij.forward(x)
Я ожидаю, что gx=y+1
но я вижу что gx=y
... И действительно, myBij.shift
до сих пор 1
,
Если я попытаюсь изменить биектор напрямую, то есть:
myBij.shift.assign(2.)
я получил
AttributeError: 'tensorflow.python.framework.ops.EagerTensor' object has no attribute 'assign'
Вычисление градиентов также не работает должным образом:
with tf.GradientTape() as tape:
gx = myBij.forward(x)
grad = tape.gradient(gx, shift)
Урожайность None
, а также это исключение при завершении скрипта:
Exception ignored in: <bound method GradientTape.__del__ of <tensorflow.python.eager.backprop.GradientTape object at 0x7f529c4702e8>>
Traceback (most recent call last):
File "~/.local/lib/python3.6/site-packages/tensorflow/python/eager/backprop.py", line 765, in __del__
AttributeError: 'NoneType' object has no attribute 'context'
Что мне здесь не хватает?
Редактировать: у меня это работает с графиком / сессией, так что, похоже, есть проблема с нетерпением выполнения...
Примечание: у меня есть версия tenorflow 1.12.0 и версия tenorflow_probability 0.5.0
1 ответ
Если вы используете активный режим, вам нужно пересчитать все из переменной вперед. Лучше всего захватить эту логику в функции;
import tensorflow as tf
import tensorflow_probability as tfp
tfd = tfp.distributions
tf.enable_eager_execution()
shift = tf.Variable(1., dtype=tf.float32)
def f():
myBij = tfp.bijectors.Affine(shift=shift)
# Normal distribution centered in zero, then shifted to 1 using the bijection
myDistr = tfd.TransformedDistribution(
distribution=tfd.Normal(loc=0., scale=1.),
bijector=myBij,
name="test")
# 2 samples of a normal centered at 1:
y = myDistr.sample(2)
# 2 samples of a normal centered at 0, obtained using inverse
# transform of myBij:
x = myBij.inverse(y)
return x, y
x, y = f()
shift.assign(2.)
gx, _ = f()
Что касается градиентов, вам нужно будет обернуть вызовы f()
в GradientTape