tensorflow / tensorflow/probability

Transformed Variable not trainable in Keras model

Open
#946 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

keras layers
Dominant language
Jupyter Notebook
Stars
4.4k
Forks
1.1k
PR merge metrics
No merged PRs in 30d

Description

Hi,
I am trying to train a positive variable using tfp.util.TransformedVariable as an attribute of a tf.keras.Model object. However, the model does not recognize it as a trainable variable, and it does not receive gradients. This behavior holds for tensorflow_probability==0.10.0 and tensorflow==2.2.0, as well as for the nightly builds of both.

Here is a colab notebook illustrating this behavior: https://colab.research.google.com/drive/1XGCcm8l0OGRiy35lr3XcHAyZMuBNpsIB?usp=sharing

In this example, we are trying to train both an unconstrained variable (loc) and a constrained variable (scale). Only the loc variable updates.

import numpy as np
import tensorflow as tf
import tensorflow_probability as tfp

class Model(tf.keras.Model):
  def __init__(self):
    super(Model, self).__init__()
    self.loc = tf.Variable(tf.ones(shape=[5]), name="loc")
    self.scale = tfp.util.TransformedVariable(
        tf.ones([5]),
        bijector=tfp.bijectors.Softplus(),
        name="scale") 
    self.distribution = tfp.distributions.Normal(loc=self.loc, scale=self.scale)

  def call(self, inputs):
    samples = self.distribution.sample()
    assigned_means = tf.gather(samples, inputs)
    return tfp.distributions.Normal(loc=assigned_means, scale=1.)

model = Model()
print(model.trainable_weights)  # only 'loc' shows up

optimizer = tf.keras.optimizers.Adam(learning_rate=0.1)
loss = lambda x, rv: -tf.reduce_sum(rv.log_prob(x))
inputs = np.array([0, 1, 2, 3, 4]).astype(np.int32)
outputs = np.array([0., 1., 2., 3., 4.]).astype(np.float32)
dataset = tf.data.Dataset.from_tensor_slices((inputs, outputs))
dataset = dataset.batch(5)
model.compile(optimizer=optimizer, loss=loss)
model.fit(dataset, epochs=100, verbose=0)

# Check if the location parameters have moved from their original values.
assert(not (np.isclose(model.loc.numpy(), np.ones(5))).all())  # Passes

# Check if the scale parameters have moved from their original values.
assert(not (np.isclose(model.scale.numpy(), np.ones(5))).all())  # Fails

Thanks!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked Colab notebook and reproduce the behavior using TensorFlow Probability 0.10.0 with TensorFlow 2.2.0 or the nightly builds. Inspect how TransformedVariable is tracked by the Keras model, comparing model.trainable_weights and gradients for loc and scale. Done means the constrained scale variable receives gradients and updates during fit, alongside loc.

Written by the indexing model from the issue text.

Assessment

Tech stack
keras, python
Domain
machine-learning
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.