def video_objective_tower(self, input_frames, target_frames, init=False):
    """Returns the bits-per-pixel of the video.

    Args:
      input_frames: 5-D Tensor of shape (N, 1, H, W, C)
      target_frames: 5-D Tensor of shape (N, T, H, W, C)
      init: Whether or not to run data-dependent initialization.
    Returns:
      objective: bits-per-pixel.
    """
    # The arg_scope call ensures that the actnorm parameters are set such that
    # the per-channel output activations have zero mean and unit variance
    # ONLY during the first step. After that the parameters are learned
    # through optimisation.
    num_input_frames = (self.hparams.video_num_input_frames +
                        int(self.hparams.cond_first_frame))

    # Set num total frames to average the objective.
    total_frames = self.get_num_train_frames()

    # Compute the log-likelihood of target_frames at both train and predict
    # time.
    all_frames = self.get_all_frames(input_frames, target_frames)
    all_frames = tf.unstack(all_frames, axis=1)

    cond_level_latents, cond_top_latents = None, None
    total_objective = 0.0
    ops = [glow_ops.get_variable_ddi, glow_ops.actnorm, glow_ops.get_dropout]

    with arg_scope(ops, init=init):
      for frame_ind, frame in enumerate(all_frames):

        # Get current set of cond latents of non-top levels.
        cond_level, cond_level_latents = get_cond_latents(
            self.all_level_latents, self.hparams)

        # Get current set of cond latents of the top-level
        cond_top, cond_top_latents = get_cond_latents(
            self.all_top_latents, self.hparams)

        # Superscript -> level, Subscript -> Time.
        # (z^{0}_t, z^{1..l}_t) = Glow(X_{t}, z^{1..l}_{cond_t})
        frame_obj, curr_top_latent, curr_level_latents = self.glow_encoder(
            frame, condition=cond_level, cond_latents=cond_level_latents,
            init=init)

        # z^0_t ~ N(f(z^0_{t-1}))
        # cond_top_latents is None when
        # latent_dist_encoder is conv_net and frame_ind < num_cond_frames.
        prior_dist = self.top_prior(
            condition=cond_top, cond_latents=cond_top_latents)
        prior_objective = tf.reduce_sum(
            prior_dist.log_prob(curr_top_latent), axis=[1, 2, 3])
        frame_obj += prior_objective

        # Loss computation.
        # Do not model the probabililty of the input frames by default.
        # Consistent with other video models.
        if (frame_ind > num_input_frames - 1 or self.hparams.model_input or
            self.hparams.gen_mode == "unconditional"):
          total_objective += frame_obj
        self.all_level_latents.append(curr_level_latents)
        self.all_top_latents.append(curr_top_latent)

      # During prediction time, store z_sample ~ N(f(z_{num_input_frames}))
      # to generate the first target frame.
      if self.is_predicting:
        # Get current set of cond_top_latents
        cond_top, cond_top_latents = get_cond_latents(
            self.all_top_latents, self.hparams)
        prior_dist = self.top_prior(
            condition=cond_top, cond_latents=cond_top_latents)
        self.z_sample = prior_dist.sample()
        self.all_top_latents.append(self.z_sample)

      # Converts log-probability to bits-per-pixel.
      hwc = np.prod(self.hparams.problem.frame_shape)
      total_objective = -total_objective / (np.log(2) * hwc * total_frames)
    return total_objective
Returns the bits-per-pixel of the video.

    Args:
      input_frames: 5-D Tensor of shape (N, 1, H, W, C)
      target_frames: 5-D Tensor of shape (N, T, H, W, C)
      init: Whether or not to run data-dependent initialization.
    Returns:
      objective: bits-per-pixel.
    
tensor2tensor/models/video/next_frame_glow.py