在Tensorflow Bijector中使用和修改变量

时间:2018-11-16 13:38:02

标签: python tensorflow machine-learning tensorflow-probability

在有关TensorFlow分布的参考文献paper(现在为Probability)中,提到了TensorFlow Variable可用于构造BijectorTransformedDistribution对象,即:

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变量(例如,我可以根据该shift计算某些似然函数的梯度并更新其值)

shift.assign(2.)
gx = myBij.forward(x)

我希望有gx=y+1,但我看到gx=y ...的确,myBij.shift仍然等于1

如果我尝试直接修改Bijector,即:

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'

我在这里想念什么?

编辑:我可以在图形/会话中使用它,所以似乎渴望执行有问题...

注意:我有tensorflow版本1.12.0和tensorflow_probability版本0.5.0

1 个答案:

答案 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