docstr: Convert a `ivy.Module` module instance to a `tf.keras.Model`
  instance.
  
  Returns
  -------
  ret
      The new trainable `tf.keras.Model` instance.
docstr_tok: ["Convert","a","`","ivy.Module","`","module","instance","to","a","`","tf.keras.Model","`","instance",".","Returns","--","--","--","-","ret","The","new","trainable","`","tf.keras.Model","`","instance","."]
code: def to_keras_module(self):
      """Convert a `ivy.Module` module instance to a `tf.keras.Model`
      instance.
  
      Returns
      -------
      ret
          The new trainable `tf.keras.Model` instance.
      """
      try:
          import tensorflow as tf
      except ModuleNotFoundError as exc:
          raise ModuleNotFoundError(
              "`tensorflow` was not found installed on your system. Please proceed "
              "to install it and restart your interpreter to see the changes."
          ) from exc
  
      class KerasModel(tf.keras.Model):
          def __init__(self, ivy_module):
              super().__init__()
              self._ivy_module = ivy_module
              self._parameters = {}
              self._assign_variables()
              self._populate_params()
              self._propagate_params()
  
          def _assign_variables(self):
              ivy.set_backend("tensorflow")
  
              self._ivy_module.v = self._ivy_module.v.cont_map(
                  lambda x, kc: (
                      ivy.to_new_backend(x.ivy_array.data, native=True)
                      if hasattr(x, "_ivy_array")
                      else ivy.to_new_backend(x, native=True)
                  ),
              )
              self._ivy_module.v.cont_map(
                  lambda x, kc: (
                      self.add_weight(
                          name=kc,
                          shape=x.shape,
                          dtype=x.dtype,
                          trainable=True,
                      )
                      if x is not None
                      else x
                  )
              )
              model_weights = []
              self._ivy_module.v.cont_map(
                  lambda x, kc: (
                      model_weights.append(ivy.to_numpy(x))
                      if x is not None
                      else x
                  )
              )
              self.set_weights(model_weights)
  
              ivy.previous_backend()
  
          def _populate_params(self):
              self._parameters = {
                  re.sub(r":([0-9]+)$", "", param.name).replace(
                      f"{self.name}/", ""
                  ): param
                  for param in self.variables
              }
  
          def _propagate_params(self):
              def __update_param(ivy_module, x, kc):
                  if kc not in self._parameters:
                      return x
                  # Update param in the underneath ivy module
                  module = ivy_module
                  keys = re.split("[/.]", kc)
                  for key in keys[:-1]:
                      module = module.__getattribute__(key)
                  if hasattr(module, "_update_v"):
                      module._update_v({keys[-1]: self._parameters[kc]})
                  return self._parameters[kc]
  
              self._ivy_module.v = self._ivy_module.v.cont_map(
                  functools.partial(__update_param, self._ivy_module),
                  inplace=True,
              )
  
          def call(self, *args, training=None, **kwargs):
              ret = self._ivy_module(*args, **kwargs)
              ret = ivy.nested_map(
                  lambda x: (
                      x.ivy_array.data
                      if hasattr(x, "_ivy_array")
                      else ivy.to_native(x)
                  ),
                  ret,
              )
              return ret
  
          def __call__(self, *args, **kwargs):
              if ivy.backend != "tensorflow":
                  ivy.set_backend("tensorflow")
                  args, kwargs = ivy.args_to_new_backend(
                      *args, native=True, **kwargs
                  )
                  ivy.previous_backend()
              else:
                  args, kwargs = ivy.args_to_new_backend(
                      *args, native=True, **kwargs
                  )
              return super().__call__(*args, **kwargs)
  
          def to_device(self, device):
              self._ivy_module._module_graph.to_device(device)
              model_weights = ivy.nested_map(
                  lambda x: (
                      ivy.to_native(ivy.to_device(x, device))
                      if ivy.is_array(x)
                      else x
                  ),
                  self.weights,
              )
              self.set_weights(model_weights)
  
      keras_module = KerasModel(self)
      return keras_module
  
file_path: ivy/ivy/stateful/converters.py
imports: import functools
  from typing import Optional, Dict, List
  import re
  import inspect
  import ivy
  from ivy.utils.backend import current_backend
label_desc: Use image node_id 6 for calling the ModuleConverters obj's underlying member method code with example usage: obj.to_keras_module() and returns: keras_module, ret, super, self, x