code: def _virtual_adv_regularizer(
      input_layer,
      embedding_fn,
      virtual_adv_config,
      embedding,
      seed_perturbation,
  ):
      """Function to calculate virtual adversarial loss without randomness."""
      neighbor_config = virtual_adv_config.adv_neighbor_config
  
      def normalize_with_mask(perturbation):
          perturbation = utils.apply_feature_mask(
              perturbation, neighbor_config.feature_mask
          )
          return utils.normalize(
              perturbation, neighbor_config.adv_grad_norm
          )
  
      def loss_fn(embedding, perturbed_embedding):
          return distances.pairwise_distance_wrapper(
              sources=embedding,
              targets=perturbed_embedding,
              distance_config=virtual_adv_config.distance_config,
          )
  
      perturbation = normalize_with_mask(seed_perturbation)
  
      # Uses the power iteration method and the finite difference method to
      # approximate the direction which increases virtual adversarial loss the most.
      for _ in range(virtual_adv_config.num_approx_steps):
          with tf.GradientTape() as tape:
              scaled_perturbation = (
                  virtual_adv_config.approx_difference * perturbation
              )
              tape.watch(scaled_perturbation)
              virtual_adv_embedding = embedding_fn(
                  input_layer + scaled_perturbation
              )
              virtual_adv_loss = loss_fn(
                  embedding, virtual_adv_embedding
              )
          grad = tape.gradient(virtual_adv_loss, scaled_perturbation)
          perturbation = tf.stop_gradient(normalize_with_mask(grad))
  
      final_perturbation = neighbor_config.adv_step_size * perturbation
      virtual_adv_embedding = embedding_fn(
          input_layer + final_perturbation
      )
      # The gradient shouldn't be populated through the original embedding because
      # our goal is to drag the embedding of the virtual adversarial example to be
      # as close as that of the original example, but not the other way around.
      original_embedding = tf.stop_gradient(embedding)
      return loss_fn(original_embedding, virtual_adv_embedding)
  
imports: from neural_structured_learning.lib import distances
  from neural_structured_learning.lib import utils
  import tensorflow
label_desc: Use image node_id 2 for calling a global function with example usage: _virtual_adv_regularizer(input_layer, embedding_fn, virtual_adv_config, embedding, seed_perturbation) and returns: loss_fn, utils, distances