class_docstr: A keras layer for dynamic graph convolutions.
  
  Dynamic GraphCNN for Learning on Point Clouds
  Yue Wang, Yongbin Sun, Ziwei Liu, Sanjay E. Sarma, Michael Bronstein, and
  Justin Solomon.
  https://arxiv.org/abs/1801.07829
  
  This layer implements an instance of the graph convolutional operation
  described in the paper above, specifically a graph convolution block with a
  single edge filtering layer. This implementation is intended to demonstrate
  how `graph_convolution.edge_convolution_template` can be wrapped to implement
  a variety of edge convolutional methods.
  
  This implementation is slightly generalized version to what is described in
  the paper in that here variable sized neighborhoods are allowed rather than
  forcing a fixed size k-neighbors. Users must provide the neighborhoods as
  input.
class_docstr_tok: ["A","keras","layer","for","dynamic","graph","convolutions",".","Dynamic","GraphCNN","for","Learning","on","Point","Clouds","Yue","Wang",",","Yongbin","Sun",",","Ziwei","Liu",",","Sanjay","E.","Sarma",",","Michael","Bronstein",",","and","Justin","Solomon",".","https",":","\/\/arxiv.org\/abs\/1801.07829","This","layer","implements","an","instance","of","the","graph","convolutional","operation","described","in","the","paper","above",",","specifically","a","graph","convolution","block","with","a","single","edge","filtering","layer",".","This","implementation","is","intended","to","demonstrate","how","`","graph_convolution.edge_convolution_template","`","can","be","wrapped","to","implement","a","variety","of","edge","convolutional","methods",".","This","implementation","is","slightly","generalized","version","to","what","is","described","in","the","paper","in","that","here","variable","sized","neighborhoods","are","allowed","rather","than","forcing","a","fixed","size","k-neighbors",".","Users","must","provide","the","neighborhoods","as","input","."]
docstr: Executes the convolution.
  
  The shorthands used below are
    `V`: The number of vertices.
    `C`: The number of channels in the input data.
  
  Note:
    In the following, A1 to An are optional batch dimensions.
  
  Args:
    inputs: A list of two tensors `[data, neighbors]`. `data` is a `float`
      tensor with shape `[A1, ..., An, V, C]`. `neighbors` is a `SparseTensor`
      with the same type as `data` and with shape `[A1, ..., An, V, V]`
      representing vertex neighborhoods. The neighborhood of a vertex defines
      the support region for convolution. For a mesh, a common choice for the
      neighborhood of vertex `i` would be the vertices in the K-ring of `i`
      (including `i` itself). Each vertex must have at least one neighbor. For
      `reduction='weighted'`, `neighbors` should be a row-normalized matrix:
      `sum(neighbors, axis=-1)[A1, ..., An, i] == 1.0` for all `i`, although
      this is not enforced in the implementation in case different neighbor
      weighting schemes are desired.
    **kwargs: A dictionary containing the key `sizes`, which is an `int`
      tensor of shape `[A1, ..., An]` indicating the true input sizes in case
      of padding (`sizes=None` indicates no padding).
      `sizes[A1, ..., An] <= V`. If `data` and `neighbors` are 2-D, `sizes`
      will be ignored. As an example usage of `sizes`, consider an input
      consisting of three graphs `G0`, `G1`, and `G2` with `V0`, `V1`, and
      `V2` vertices respectively. The padded input would have the shapes
      `data.shape = [3, V, C]`, and `neighbors.shape = [3, V, V]`,
      where `V = max([V0, V1, V2])`. The true sizes of each graph will be
      specified by `sizes=[V0, V1, V2]`. `data[i, :Vi, :]` and
      `neighbors[i, :Vi, :Vi]` will be the vertex and neighborhood data of
      graph `Gi`. The `SparseTensor` `neighbors` should have no nonzero
      entries in the padded regions.
  
  Returns:
    Tensor with shape `[A1, ..., An, V, num_output_channels]`.
docstr_tok: ["Executes","the","convolution",".","The","shorthands","used","below","are","`","V","`",":","The","number","of","vertices",".","`","C","`",":","The","number","of","channels","in","the","input","data",".","Note",":","In","the","following",",","A1","to","An","are","optional","batch","dimensions",".","Args",":","inputs",":","A","list","of","two","tensors","`","[","data",",","neighbors","]","`",".","`","data","`","is","a","`","float","`","tensor","with","shape","`","[","A1",",","...",",","An",",","V",",","C","]","`",".","`","neighbors","`","is","a","`","SparseTensor","`","with","the","same","type","as","`","data","`","and","with","shape","`","[","A1",",","...",",","An",",","V",",","V","]","`","representing","vertex","neighborhoods",".","The","neighborhood","of","a","vertex","defines","the","support","region","for","convolution",".","For","a","mesh",",","a","common","choice","for","the","neighborhood","of","vertex","`","i","`","would","be","the","vertices","in","the","K-ring","of","`","i","`","(","including","`","i","`","itself",")",".","Each","vertex","must","have","at","least","one","neighbor",".","For","`","reduction='weighted","'","`",",","`","neighbors","`","should","be","a","row-normalized","matrix",":","`","sum","(","neighbors",",","axis=-1",")","[","A1",",","...",",","An",",","i","]","==","1.0","`","for","all","`","i","`",",","although","this","is","not","enforced","in","the","implementation","in","case","different","neighbor","weighting","schemes","are","desired",".","*","*","kwargs",":","A","dictionary","containing","the","key","`","sizes","`",",","which","is","an","`","int","`","tensor","of","shape","`","[","A1",",","...",",","An","]","`","indicating","the","true","input","sizes","in","case","of","padding","(","`","sizes=None","`","indicates","no","padding",")",".","`","sizes","[","A1",",","...",",","An","]","<","=","V","`",".","If","`","data","`","and","`","neighbors","`","are","2-D",",","`","sizes","`","will","be","ignored",".","As","an","example","usage","of","`","sizes","`",",","consider","an","input","consisting","of","three","graphs","`","G0","`",",","`","G1","`",",","and","`","G2","`","with","`","V0","`",",","`","V1","`",",","and","`","V2","`","vertices","respectively",".","The","padded","input","would","have","the","shapes","`","data.shape","=","[","3",",","V",",","C","]","`",",","and","`","neighbors.shape","=","[","3",",","V",",","V","]","`",",","where","`","V","=","max","(","[","V0",",","V1",",","V2","]",")","`",".","The","true","sizes","of","each","graph","will","be","specified","by","`","sizes=","[","V0",",","V1",",","V2","]","`",".","`","data","[","i",",",":","Vi",",",":","]","`","and","`","neighbors","[","i",",",":","Vi",",",":","Vi","]","`","will","be","the","vertex","and","neighborhood","data","of","graph","`","Gi","`",".","The","`","SparseTensor","`","`","neighbors","`","should","have","no","nonzero","entries","in","the","padded","regions",".","Returns",":","Tensor","with","shape","`","[","A1",",","...",",","An",",","V",",","num_output_channels","]","`","."]
code: def call(self, inputs, **kwargs):
      # pyformat: disable
      """Executes the convolution.
  
      The shorthands used below are
        `V`: The number of vertices.
        `C`: The number of channels in the input data.
  
      Note:
        In the following, A1 to An are optional batch dimensions.
  
      Args:
        inputs: A list of two tensors `[data, neighbors]`. `data` is a `float`
          tensor with shape `[A1, ..., An, V, C]`. `neighbors` is a `SparseTensor`
          with the same type as `data` and with shape `[A1, ..., An, V, V]`
          representing vertex neighborhoods. The neighborhood of a vertex defines
          the support region for convolution. For a mesh, a common choice for the
          neighborhood of vertex `i` would be the vertices in the K-ring of `i`
          (including `i` itself). Each vertex must have at least one neighbor. For
          `reduction='weighted'`, `neighbors` should be a row-normalized matrix:
          `sum(neighbors, axis=-1)[A1, ..., An, i] == 1.0` for all `i`, although
          this is not enforced in the implementation in case different neighbor
          weighting schemes are desired.
        **kwargs: A dictionary containing the key `sizes`, which is an `int`
          tensor of shape `[A1, ..., An]` indicating the true input sizes in case
          of padding (`sizes=None` indicates no padding).
          `sizes[A1, ..., An] <= V`. If `data` and `neighbors` are 2-D, `sizes`
          will be ignored. As an example usage of `sizes`, consider an input
          consisting of three graphs `G0`, `G1`, and `G2` with `V0`, `V1`, and
          `V2` vertices respectively. The padded input would have the shapes
          `data.shape = [3, V, C]`, and `neighbors.shape = [3, V, V]`,
          where `V = max([V0, V1, V2])`. The true sizes of each graph will be
          specified by `sizes=[V0, V1, V2]`. `data[i, :Vi, :]` and
          `neighbors[i, :Vi, :Vi]` will be the vertex and neighborhood data of
          graph `Gi`. The `SparseTensor` `neighbors` should have no nonzero
          entries in the padded regions.
  
      Returns:
        Tensor with shape `[A1, ..., An, V, num_output_channels]`.
      """
  
      # pyformat: enable
      def _edge_convolution(vertices, neighbors, conv1d_layer):
          r"""The edge filtering op passed to `edge_convolution_template`.
  
          This instance implements the edge function
          $$h_{\theta}(x, y) = MLP_{\theta}([x, y - x])$$
  
          Args:
            vertices: A 2-D Tensor with shape `[D1, D2]`.
            neighbors: A 2-D Tensor with the same shape and type as `vertices`.
            conv1d_layer: A callable 1d convolution layer.
  
          Returns:
            A 2-D Tensor with shape `[D1, D3]`.
          """
          concat_features = tf.concat(
              values=[vertices, neighbors - vertices], axis=-1
          )
          concat_features = tf.expand_dims(concat_features, 0)
          convolved_features = conv1d_layer(concat_features)
          convolved_features = tf.squeeze(
              input=convolved_features, axis=(0,)
          )
          return convolved_features
  
      sizes = kwargs.get("sizes", None)
      return gc.edge_convolution_template(
          data=inputs[0],
          neighbors=inputs[1],
          sizes=sizes,
          edge_function=_edge_convolution,
          reduction=self._reduction,
          edge_function_kwargs={"conv1d_layer": self._conv1d_layer},
      )
  
file_path: graphics/tensorflow_graphics/nn/layer/graph_convolution.py
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import tensorflow
  import tensorflow_graphics.geometry.convolution.graph_convolution
  from tensorflow_graphics.util import export_api
label_desc: Use image node_id 3 for calling the DynamicGraphConvolutionKerasLayer obj's underlying member method code with example usage: obj.call(inputs) and returns: gc, convolved_features