docstr: :param data: could be a tuple with numpy ndarray with form (x, y)
  :param validation_data: could be a tuple with numpy ndarray with form (x, y)
  fit_eval will build a model at the first time it is built
  config will be updated for the second or later times with only non-model-arch
  params be functional
  TODO: check the updated params and decide if the model is needed to be rebuilt
docstr_tok: [":","param","data",":","could","be","a","tuple","with","numpy","ndarray","with","form","(","x",",","y",")",":","param","validation_data",":","could","be","a","tuple","with","numpy","ndarray","with","form","(","x",",","y",")","fit_eval","will","build","a","model","at","the","first","time","it","is","built","config","will","be","updated","for","the","second","or","later","times","with","only","non-model-arch","params","be","functional","TODO",":","check","the","updated","params","and","decide","if","the","model","is","needed","to","be","rebuilt"]
code: def fit_eval(
      self,
      data,
      validation_data=None,
      mc=False,
      verbose=0,
      epochs=1,
      metric=None,
      metric_func=None,
      **config,
  ):
      """
      :param data: could be a tuple with numpy ndarray with form (x, y)
      :param validation_data: could be a tuple with numpy ndarray with form (x, y)
      fit_eval will build a model at the first time it is built
      config will be updated for the second or later times with only non-model-arch
      params be functional
      TODO: check the updated params and decide if the model is needed to be rebuilt
      """
      x, y = data[0], data[1]
  
      def update_config():
          config.setdefault("input_dim", x.shape[-1])
          config.setdefault("output_dim", y.shape[-1])
          if metric and not metric_func:
              config.update({"metric": metric})
  
      if not self.model_built:
          update_config()
          self.build(config)
      else:
          tmp_config = self.config.copy()
          tmp_config.update(config)
          self._check_config(**tmp_config)
          self.config.update(config)
  
      hist = self.model.fit(
          x,
          y,
          validation_data=validation_data,
          batch_size=self.config.get("batch_size", 32),
          epochs=epochs,
          verbose=verbose,
      )
  
      # model.metrics_names are available only after a keras model has been trained/evaluated
      compiled_metric_names = self.model.metrics_names.copy()
      compiled_metric_names.remove("loss")
      if not metric_func:
          # check input metric value
          if not metric:
              if len(compiled_metric_names) == 1:
                  metric = compiled_metric_names[0]
                  metric_name = metric
              else:
                  raise ValueError(
                      f"Got multiple metrics in compile: {compiled_metric_names}. "
                      f"Please choose one target metric for automl optimization"
                  )
          else:
              hist_metric_name = tf.keras.metrics.get(metric).__name__
              if hist_metric_name in compiled_metric_names:
                  metric_name = hist_metric_name
              elif metric in compiled_metric_names:
                  metric_name = metric
              else:
                  raise ValueError(
                      f"Input metric in fit_eval should be one of the metrics that "
                      f"are used to compile the model. Got metric value of {metric} "
                      f"and the metrics in compile are {compiled_metric_names}"
                  )
          if validation_data is None:
              result = hist.history.get(metric_name)[-1]
          else:
              result = hist.history.get("val_" + metric_name)[-1]
          return {metric: result}
      else:
          metric_name = metric or metric_func.__name__
          if validation_data is not None:
              val_x = validation_data[0]
              val_y = validation_data[1]
          else:
              val_x = x
              val_y = y
          y_pred = self.predict(val_x)
          result = metric_func(val_y, y_pred)
          return {metric_name: result}
  
imports: from zoo.orca.automl.model.abstract import BaseModel, ModelBuilder
  import numpy
  from zoo.orca.automl.metrics import Evaluator
  import pickle
  import tensorflow
  from tensorflow.keras import backend
label_desc: Use image node_id 3 for calling the KerasBaseModel obj's underlying member method code with example usage: obj.fit_eval(data, validation_data, mc, verbose, epochs, metric, metric_func) and returns: dict, dict