tensorflow_probability/python/mcmc/nuts.py
def _loop_build_sub_tree(self,
                           directions,
                           integrator,
                           current_step_meta_info,
                           iter_,
                           energy_diff_sum_previous,
                           momentum_cumsum_previous,
                           leapfrogs_taken,
                           prev_tree_state,
                           candidate_tree_state,
                           continue_tree_previous,
                           not_divergent_previous,
                           momentum_state_memory):
    """Base case in tree doubling."""
    with tf.name_scope('loop_build_sub_tree'):
      # Take one leapfrog step in the direction v and check divergence
      [
          next_momentum_parts,
          next_state_parts,
          next_target,
          next_target_grad_parts
      ] = integrator(prev_tree_state.momentum,
                     prev_tree_state.state,
                     prev_tree_state.target,
                     prev_tree_state.target_grad_parts)

      next_tree_state = TreeDoublingState(
          momentum=next_momentum_parts,
          state=next_state_parts,
          target=next_target,
          target_grad_parts=next_target_grad_parts)
      momentum_cumsum = [p0 + p1 for p0, p1 in zip(momentum_cumsum_previous,
                                                   next_momentum_parts)]
      # If the tree have not yet terminated previously, we count this leapfrog.
      leapfrogs_taken = tf.where(
          continue_tree_previous, leapfrogs_taken + 1, leapfrogs_taken)

      write_instruction = current_step_meta_info.write_instruction
      read_instruction = current_step_meta_info.read_instruction
      init_energy = current_step_meta_info.init_energy

      # Save state and momentum at odd step, check U turn at even step.
      # Note that here we also write to a Placeholder at even step
      write_index = tf.where(
          tf.equal(iter_ % 2, 0),
          write_instruction.gather([iter_ // 2]),
          self.max_tree_depth)

      if GENERALIZED_UTURN:
        state_to_write = momentum_cumsum
      else:
        state_to_write = next_state_parts

      momentum_state_memory = MomentumStateSwap(
          momentum_swap=[
              tf.tensor_scatter_nd_update(old, [write_index], [new])
              for old, new in zip(momentum_state_memory.momentum_swap,
                                  next_momentum_parts)
          ],
          state_swap=[
              tf.tensor_scatter_nd_update(old, [write_index], [new])
              for old, new in zip(momentum_state_memory.state_swap,
                                  state_to_write)
          ])
      batch_shape = prefer_static.shape(next_target)
      has_not_u_turn_at_even_step = tf.ones(batch_shape, dtype=tf.bool)

      read_index = read_instruction.gather([iter_ // 2])[0]
      no_u_turns_within_tree = tf.cond(
          tf.equal(iter_ % 2, 0),
          lambda: has_not_u_turn_at_even_step,
          lambda: has_not_u_turn_at_odd_step(  # pylint: disable=g-long-lambda
              read_index, directions, momentum_state_memory,
              next_momentum_parts, state_to_write,
              has_not_u_turn_at_even_step,
              log_prob_rank=prefer_static.rank(next_target)))

      energy = compute_hamiltonian(next_target, next_momentum_parts)
      current_energy = tf.where(tf.math.is_nan(energy),
                                tf.constant(-np.inf, dtype=energy.dtype),
                                energy)
      energy_diff = current_energy - init_energy

      if MULTINOMIAL_SAMPLE:
        not_divergent = -energy_diff < self.max_energy_diff
        weight_sum = log_add_exp(candidate_tree_state.weight, energy_diff)
        log_accept_thresh = energy_diff - weight_sum
      else:
        log_slice_sample = current_step_meta_info.log_slice_sample
        not_divergent = log_slice_sample - energy_diff < self.max_energy_diff
        # Uniform sampling on the trajectory within the subtree across valid
        # samples.
        is_valid = log_slice_sample <= energy_diff
        weight_sum = tf.where(is_valid,
                              candidate_tree_state.weight + 1,
                              candidate_tree_state.weight)
        log_accept_thresh = tf.where(
            is_valid,
            -tf.math.log(tf.cast(weight_sum, dtype=tf.float32)),
            tf.constant(-np.inf, dtype=tf.float32))
      u = tf.math.log1p(-tf.random.uniform(
          shape=batch_shape,
          dtype=log_accept_thresh.dtype,
          seed=self._seed_stream()))
      is_sample_accepted = u <= log_accept_thresh

      next_candidate_tree_state = TreeDoublingStateCandidate(
          state=[
              tf.where(  # pylint: disable=g-complex-comprehension
                  _rightmost_expand_to_rank(is_sample_accepted,
                                            prefer_static.rank(s0)),
                  s0, s1)
              for s0, s1 in zip(next_state_parts, candidate_tree_state.state)
          ],
          target=tf.where(
              _rightmost_expand_to_rank(is_sample_accepted,
                                        prefer_static.rank(next_target)),
              next_target, candidate_tree_state.target),
          target_grad_parts=[
              tf.where(  # pylint: disable=g-complex-comprehension
                  _rightmost_expand_to_rank(is_sample_accepted,
                                            prefer_static.rank(grad0)),
                  grad0, grad1)
              for grad0, grad1 in zip(next_target_grad_parts,
                                      candidate_tree_state.target_grad_parts)
          ],
          energy=tf.where(
              _rightmost_expand_to_rank(is_sample_accepted,
                                        prefer_static.rank(next_target)),
              current_energy, init_energy),
          weight=weight_sum)

      continue_tree = not_divergent & continue_tree_previous
      continue_tree_next = no_u_turns_within_tree & continue_tree

      not_divergent_tokeep = tf.where(continue_tree_previous,
                                      not_divergent,
                                      tf.ones(batch_shape, dtype=tf.bool))

      # min(1., exp(energy_diff)).
      exp_energy_diff = tf.clip_by_value(tf.exp(energy_diff), 0., 1.)
      energy_diff_sum = tf.where(continue_tree,
                                 energy_diff_sum_previous + exp_energy_diff,
                                 energy_diff_sum_previous)

      return (
          iter_ + 1,
          energy_diff_sum,
          momentum_cumsum,
          leapfrogs_taken,
          next_tree_state,
          next_candidate_tree_state,
          continue_tree_next,
          not_divergent_previous & not_divergent_tokeep,
          momentum_state_memory,
      )
Base case in tree doubling.
Base case in tree doubling.
Base case in tree doubling .
def _loop_build_sub_tree(self,
                           directions,
                           integrator,
                           current_step_meta_info,
                           iter_,
                           energy_diff_sum_previous,
                           momentum_cumsum_previous,
                           leapfrogs_taken,
                           prev_tree_state,
                           candidate_tree_state,
                           continue_tree_previous,
                           not_divergent_previous,
                           momentum_state_memory):
    with tf.name_scope('loop_build_sub_tree'):
      [
          next_momentum_parts,
          next_state_parts,
          next_target,
          next_target_grad_parts
      ] = integrator(prev_tree_state.momentum,
                     prev_tree_state.state,
                     prev_tree_state.target,
                     prev_tree_state.target_grad_parts)
      next_tree_state = TreeDoublingState(
          momentum=next_momentum_parts,
          state=next_state_parts,
          target=next_target,
          target_grad_parts=next_target_grad_parts)
      momentum_cumsum = [p0 + p1 for p0, p1 in zip(momentum_cumsum_previous,
                                                   next_momentum_parts)]
      leapfrogs_taken = tf.where(
          continue_tree_previous, leapfrogs_taken + 1, leapfrogs_taken)
      write_instruction = current_step_meta_info.write_instruction
      read_instruction = current_step_meta_info.read_instruction
      init_energy = current_step_meta_info.init_energy
      write_index = tf.where(
          tf.equal(iter_ % 2, 0),
          write_instruction.gather([iter_ // 2]),
          self.max_tree_depth)
      if GENERALIZED_UTURN:
        state_to_write = momentum_cumsum
      else:
        state_to_write = next_state_parts
      momentum_state_memory = MomentumStateSwap(
          momentum_swap=[
              tf.tensor_scatter_nd_update(old, [write_index], [new])
              for old, new in zip(momentum_state_memory.momentum_swap,
                                  next_momentum_parts)
          ],
          state_swap=[
              tf.tensor_scatter_nd_update(old, [write_index], [new])
              for old, new in zip(momentum_state_memory.state_swap,
                                  state_to_write)
          ])
      batch_shape = prefer_static.shape(next_target)
      has_not_u_turn_at_even_step = tf.ones(batch_shape, dtype=tf.bool)
      read_index = read_instruction.gather([iter_ // 2])[0]
      no_u_turns_within_tree = tf.cond(
          tf.equal(iter_ % 2, 0),
          lambda: has_not_u_turn_at_even_step,
          lambda: has_not_u_turn_at_odd_step(  
              read_index, directions, momentum_state_memory,
              next_momentum_parts, state_to_write,
              has_not_u_turn_at_even_step,
              log_prob_rank=prefer_static.rank(next_target)))
      energy = compute_hamiltonian(next_target, next_momentum_parts)
      current_energy = tf.where(tf.math.is_nan(energy),
                                tf.constant(-np.inf, dtype=energy.dtype),
                                energy)
      energy_diff = current_energy - init_energy
      if MULTINOMIAL_SAMPLE:
        not_divergent = -energy_diff < self.max_energy_diff
        weight_sum = log_add_exp(candidate_tree_state.weight, energy_diff)
        log_accept_thresh = energy_diff - weight_sum
      else:
        log_slice_sample = current_step_meta_info.log_slice_sample
        not_divergent = log_slice_sample - energy_diff < self.max_energy_diff
        is_valid = log_slice_sample <= energy_diff
        weight_sum = tf.where(is_valid,
                              candidate_tree_state.weight + 1,
                              candidate_tree_state.weight)
        log_accept_thresh = tf.where(
            is_valid,
            -tf.math.log(tf.cast(weight_sum, dtype=tf.float32)),
            tf.constant(-np.inf, dtype=tf.float32))
      u = tf.math.log1p(-tf.random.uniform(
          shape=batch_shape,
          dtype=log_accept_thresh.dtype,
          seed=self._seed_stream()))
      is_sample_accepted = u <= log_accept_thresh
      next_candidate_tree_state = TreeDoublingStateCandidate(
          state=[
              tf.where(  
                  _rightmost_expand_to_rank(is_sample_accepted,
                                            prefer_static.rank(s0)),
                  s0, s1)
              for s0, s1 in zip(next_state_parts, candidate_tree_state.state)
          ],
          target=tf.where(
              _rightmost_expand_to_rank(is_sample_accepted,
                                        prefer_static.rank(next_target)),
              next_target, candidate_tree_state.target),
          target_grad_parts=[
              tf.where(  
                  _rightmost_expand_to_rank(is_sample_accepted,
                                            prefer_static.rank(grad0)),
                  grad0, grad1)
              for grad0, grad1 in zip(next_target_grad_parts,
                                      candidate_tree_state.target_grad_parts)
          ],
          energy=tf.where(
              _rightmost_expand_to_rank(is_sample_accepted,
                                        prefer_static.rank(next_target)),
              current_energy, init_energy),
          weight=weight_sum)
      continue_tree = not_divergent & continue_tree_previous
      continue_tree_next = no_u_turns_within_tree & continue_tree
      not_divergent_tokeep = tf.where(continue_tree_previous,
                                      not_divergent,
                                      tf.ones(batch_shape, dtype=tf.bool))
      exp_energy_diff = tf.clip_by_value(tf.exp(energy_diff), 0., 1.)
      energy_diff_sum = tf.where(continue_tree,
                                 energy_diff_sum_previous + exp_energy_diff,
                                 energy_diff_sum_previous)
      return (
          iter_ + 1,
          energy_diff_sum,
          momentum_cumsum,
          leapfrogs_taken,
          next_tree_state,
          next_candidate_tree_state,
          continue_tree_next,
          not_divergent_previous & not_divergent_tokeep,
          momentum_state_memory,
      )
def _loop_build_sub_tree ( self , directions , integrator , current_step_meta_info , iter_ , energy_diff_sum_previous , momentum_cumsum_previous , leapfrogs_taken , prev_tree_state , candidate_tree_state , continue_tree_previous , not_divergent_previous , momentum_state_memory ) : with tf . name_scope ( 'loop_build_sub_tree' ) : [ next_momentum_parts , next_state_parts , next_target , next_target_grad_parts ] = integrator ( prev_tree_state . momentum , prev_tree_state . state , prev_tree_state . target , prev_tree_state . target_grad_parts ) next_tree_state = TreeDoublingState ( momentum = next_momentum_parts , state = next_state_parts , target = next_target , target_grad_parts = next_target_grad_parts ) momentum_cumsum = [ p0 + p1 for p0 , p1 in zip ( momentum_cumsum_previous , next_momentum_parts ) ] leapfrogs_taken = tf . where ( continue_tree_previous , leapfrogs_taken + 1 , leapfrogs_taken ) write_instruction = current_step_meta_info . write_instruction read_instruction = current_step_meta_info . read_instruction init_energy = current_step_meta_info . init_energy write_index = tf . where ( tf . equal ( iter_ % 2 , 0 ) , write_instruction . gather ( [ iter_ // 2 ] ) , self . max_tree_depth ) if GENERALIZED_UTURN : state_to_write = momentum_cumsum else : state_to_write = next_state_parts momentum_state_memory = MomentumStateSwap ( momentum_swap = [ tf . tensor_scatter_nd_update ( old , [ write_index ] , [ new ] ) for old , new in zip ( momentum_state_memory . momentum_swap , next_momentum_parts ) ] , state_swap = [ tf . tensor_scatter_nd_update ( old , [ write_index ] , [ new ] ) for old , new in zip ( momentum_state_memory . state_swap , state_to_write ) ] ) batch_shape = prefer_static . shape ( next_target ) has_not_u_turn_at_even_step = tf . ones ( batch_shape , dtype = tf . bool ) read_index = read_instruction . gather ( [ iter_ // 2 ] ) [ 0 ] no_u_turns_within_tree = tf . cond ( tf . equal ( iter_ % 2 , 0 ) , lambda : has_not_u_turn_at_even_step , lambda : has_not_u_turn_at_odd_step ( read_index , directions , momentum_state_memory , next_momentum_parts , state_to_write , has_not_u_turn_at_even_step , log_prob_rank = prefer_static . rank ( next_target ) ) ) energy = compute_hamiltonian ( next_target , next_momentum_parts ) current_energy = tf . where ( tf . math . is_nan ( energy ) , tf . constant ( - np . inf , dtype = energy . dtype ) , energy ) energy_diff = current_energy - init_energy if MULTINOMIAL_SAMPLE : not_divergent = - energy_diff < self . max_energy_diff weight_sum = log_add_exp ( candidate_tree_state . weight , energy_diff ) log_accept_thresh = energy_diff - weight_sum else : log_slice_sample = current_step_meta_info . log_slice_sample not_divergent = log_slice_sample - energy_diff < self . max_energy_diff is_valid = log_slice_sample <= energy_diff weight_sum = tf . where ( is_valid , candidate_tree_state . weight + 1 , candidate_tree_state . weight ) log_accept_thresh = tf . where ( is_valid , - tf . math . log ( tf . cast ( weight_sum , dtype = tf . float32 ) ) , tf . constant ( - np . inf , dtype = tf . float32 ) ) u = tf . math . log1p ( - tf . random . uniform ( shape = batch_shape , dtype = log_accept_thresh . dtype , seed = self . _seed_stream ( ) ) ) is_sample_accepted = u <= log_accept_thresh next_candidate_tree_state = TreeDoublingStateCandidate ( state = [ tf . where ( _rightmost_expand_to_rank ( is_sample_accepted , prefer_static . rank ( s0 ) ) , s0 , s1 ) for s0 , s1 in zip ( next_state_parts , candidate_tree_state . state ) ] , target = tf . where ( _rightmost_expand_to_rank ( is_sample_accepted , prefer_static . rank ( next_target ) ) , next_target , candidate_tree_state . target ) , target_grad_parts = [ tf . where ( _rightmost_expand_to_rank ( is_sample_accepted , prefer_static . rank ( grad0 ) ) , grad0 , grad1 ) for grad0 , grad1 in zip ( next_target_grad_parts , candidate_tree_state . target_grad_parts ) ] , energy = tf . where ( _rightmost_expand_to_rank ( is_sample_accepted , prefer_static . rank ( next_target ) ) , current_energy , init_energy ) , weight = weight_sum ) continue_tree = not_divergent & continue_tree_previous continue_tree_next = no_u_turns_within_tree & continue_tree not_divergent_tokeep = tf . where ( continue_tree_previous , not_divergent , tf . ones ( batch_shape , dtype = tf . bool ) ) exp_energy_diff = tf . clip_by_value ( tf . exp ( energy_diff ) , 0. , 1. ) energy_diff_sum = tf . where ( continue_tree , energy_diff_sum_previous + exp_energy_diff , energy_diff_sum_previous ) return ( iter_ + 1 , energy_diff_sum , momentum_cumsum , leapfrogs_taken , next_tree_state , next_candidate_tree_state , continue_tree_next , not_divergent_previous & not_divergent_tokeep , momentum_state_memory , )
Base case in tree doubling.
Base case in tree doubling .
"""Base case in tree doubling.""" # Take one leapfrog step in the direction v and check divergence # If the tree have not yet terminated previously, we count this leapfrog. # Save state and momentum at odd step, check U turn at even step. # Note that here we also write to a Placeholder at even step # pylint: disable=g-long-lambda # Uniform sampling on the trajectory within the subtree across valid # samples. # pylint: disable=g-complex-comprehension # pylint: disable=g-complex-comprehension # min(1., exp(energy_diff)).
self
directions
integrator
current_step_meta_info
iter_
energy_diff_sum_previous
momentum_cumsum_previous
leapfrogs_taken
prev_tree_state
candidate_tree_state
continue_tree_previous
not_divergent_previous
momentum_state_memory