class_docstr: A layer for computing a pairwise distance in Keras models.
  
  With `Model.add_loss`, this layer can be used to build a Keras model with
  graph regularization.
  
  Example:
  
  ```python
  def regularize_model(unregularized_model, inputs):
    features, neighbors, neighbor_weights = inputs
    # Standard logistic regression.
    logits = unregularized_model(features)
    model = tf.keras.Model(inputs=inputs, outputs=logits)
    # Add regularization.
    regularizer = layers.PairwiseDistance(
        configs.DistanceConfig(sum_over_axis=-1))
    graph_loss = regularizer(
        sources=logits,
        targets=unregularized_model(neighbors),
        weights=neighbor_weights)
    model.add_loss(graph_loss)
    model.add_metric(graph_loss, aggregation="mean", name="graph_loss")
    return model
  ```
  
  This layer makes some assumptions about how the input is shaped. Either (a)
  the first dimension of `sources` should divide the first dimension of
  `targets`, with the rest of dimensions being equal or (b) `targets` should
  have an additional neighborhood size dimension at axis -2, the last dimension
  of `sources` and `targets` should match, and all other dimensions of `sources`
  should also match with corresponding dimensions in `targets`. See
  `_replicate_sources` for details.
class_docstr_tok: ["A","layer","for","computing","a","pairwise","distance","in","Keras","models",".","With","`","Model.add_loss","`",",","this","layer","can","be","used","to","build","a","Keras","model","with","graph","regularization",".","Example",":","``","`","python","def","regularize_model","(","unregularized_model",",","inputs",")",":","features",",","neighbors",",","neighbor_weights","=","inputs","#","Standard","logistic","regression",".","logits","=","unregularized_model","(","features",")","model","=","tf.keras.Model","(","inputs=inputs",",","outputs=logits",")","#","Add","regularization",".","regularizer","=","layers.PairwiseDistance","(","configs.DistanceConfig","(","sum_over_axis=-1",")",")","graph_loss","=","regularizer","(","sources=logits",",","targets=unregularized_model","(","neighbors",")",",","weights=neighbor_weights",")","model.add_loss","(","graph_loss",")","model.add_metric","(","graph_loss",",","aggregation=","''","mean","''",",","name=","''","graph_loss","''",")","return","model","``","`","This","layer","makes","some","assumptions","about","how","the","input","is","shaped",".","Either","(","a",")","the","first","dimension","of","`","sources","`","should","divide","the","first","dimension","of","`","targets","`",",","with","the","rest","of","dimensions","being","equal","or","(","b",")","`","targets","`","should","have","an","additional","neighborhood","size","dimension","at","axis","-2",",","the","last","dimension","of","`","sources","`","and","`","targets","`","should","match",",","and","all","other","dimensions","of","`","sources","`","should","also","match","with","corresponding","dimensions","in","`","targets","`",".","See","`","_replicate_sources","`","for","details","."]
docstr: Replicates `sources` to match the shape of `targets`.
  
  `targets` should either have an additional neighborhood size dimension at
  axis -2 or be of the same rank as `sources`. If `targets` has an additional
  dimension and `sources` has rank k, the first k - 1 dimensions and last
  dimension of `sources` and `targets` should match. If `sources` and
  `targets` have the same rank, the last k - 1 dimensions should match and the
  first dimension of `targets` should be a multiple of the first dimension of
  `sources`. This multiple represents the fixed neighborhood size of each
  sample.
  
  Args:
    sources: Tensor with shape [..., feature_size] from which distance will be
      calculated.
    targets: Either a tensor with shape [..., neighborhood_size, feature_size]
      or [sources.shape[0] * neighborhood_size] + sources.shape[1:].
  
  Returns:
    `sources` replicated to be shape-compatible with `targets`.
docstr_tok: ["Replicates","`","sources","`","to","match","the","shape","of","`","targets","`",".","`","targets","`","should","either","have","an","additional","neighborhood","size","dimension","at","axis","-2","or","be","of","the","same","rank","as","`","sources","`",".","If","`","targets","`","has","an","additional","dimension","and","`","sources","`","has","rank","k",",","the","first","k","-","1","dimensions","and","last","dimension","of","`","sources","`","and","`","targets","`","should","match",".","If","`","sources","`","and","`","targets","`","have","the","same","rank",",","the","last","k","-","1","dimensions","should","match","and","the","first","dimension","of","`","targets","`","should","be","a","multiple","of","the","first","dimension","of","`","sources","`",".","This","multiple","represents","the","fixed","neighborhood","size","of","each","sample",".","Args",":","sources",":","Tensor","with","shape","[","...",",","feature_size","]","from","which","distance","will","be","calculated",".","targets",":","Either","a","tensor","with","shape","[","...",",","neighborhood_size",",","feature_size","]","or","[","sources.shape","[","0","]","*","neighborhood_size","]","+","sources.shape","[","1",":","]",".","Returns",":","`","sources","`","replicated","to","be","shape-compatible","with","`","targets","`","."]
code: def _replicate_sources(self, sources, targets):
      """Replicates `sources` to match the shape of `targets`.
  
      `targets` should either have an additional neighborhood size dimension at
      axis -2 or be of the same rank as `sources`. If `targets` has an additional
      dimension and `sources` has rank k, the first k - 1 dimensions and last
      dimension of `sources` and `targets` should match. If `sources` and
      `targets` have the same rank, the last k - 1 dimensions should match and the
      first dimension of `targets` should be a multiple of the first dimension of
      `sources`. This multiple represents the fixed neighborhood size of each
      sample.
  
      Args:
        sources: Tensor with shape [..., feature_size] from which distance will be
          calculated.
        targets: Either a tensor with shape [..., neighborhood_size, feature_size]
          or [sources.shape[0] * neighborhood_size] + sources.shape[1:].
  
      Returns:
        `sources` replicated to be shape-compatible with `targets`.
      """
      # Depending on the rank of `sources` and `targets`, decide to broadcast
      # first, or replicate directly.
      if (
          sources.shape.ndims is not None
          and targets.shape.ndims is not None
          and sources.shape.ndims + 1 == targets.shape.ndims
      ):
          return tf.broadcast_to(
              tf.expand_dims(sources, axis=-2), tf.shape(targets)
          )
  
      return utils.replicate_embeddings(
          sources, tf.shape(targets)[0] // tf.shape(sources)[0]
      )
  
file_path: neural-structured-learning/neural_structured_learning/keras/layers/pairwise_distance.py
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import attr
  import enum
  import neural_structured_learning.configs
  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 the PairwiseDistance obj's underlying member method code with example usage: obj._replicate_sources(sources, targets) and returns: utils, tf