docstr: :param data: could be a tuple with numpy ndarray with form (x, y) or
         a data creator takes a config dict as parameter and returns a tf.data.Dataset.
  :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",")","or","a","data","creator","takes","a","config","dict","as","parameter","and","returns","a","tf.data.Dataset",".",":","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,
      resources_per_trial=None,
      **config,
  ):
      """
      :param data: could be a tuple with numpy ndarray with form (x, y) or
             a data creator takes a config dict as parameter and returns a tf.data.Dataset.
      :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
      """
  
      def update_config():
          if isinstance(data, tuple) and isinstance(
              data[0], np.ndarray
          ):
              x, y = data
              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 = copy.copy(self.config)
          tmp_config.update(config)
          self._check_config(**tmp_config)
          self.config.update(config)
  
      # get train_dataset and validation_dataset
      if isinstance(data, types.FunctionType):
          train_dataset = data(self.config)
          if validation_data:
              validation_dataset = validation_data(self.config)
          else:
              validation_dataset = validation_data
      else:
          if not isinstance(data, tuple):
              invalidInputError(
                  False,
                  f"data/validation_data should be a tuple of numpy array "
                  f"or a data creator function but found {type(data)}",
              )
          if validation_data:
              invalidInputError(
                  isinstance(validation_data, tuple),
                  f"validation_data should be a tuple or"
                  f" data creator function but found {type(validation_data)}",
              )
  
          batch_size = int(self.config.get("batch_size", 32))
          train_dataset = KerasBaseModel._np_to_dataset(
              data, batch_size=batch_size
          )
          if validation_data:
              validation_dataset = KerasBaseModel._np_to_dataset(
                  validation_data, batch_size
              )
          else:
              validation_dataset = validation_data
  
      hist = self.model.fit(
          train_dataset,
          validation_data=validation_dataset,
          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:
                  invalidInputError(
                      False,
                      f"Got multiple metrics in compile: {compiled_metric_names}. "
                      f"Please choose one target metric for automl optimization",
                  )
          else:
              if metric in compiled_metric_names:
                  metric_name = metric
              else:
                  try:
                      hist_metric_name = tf.keras.metrics.get(
                          metric
                      ).__name__
                  except:
                      invalidInputError(
                          False,
                          f"get invalid metric name {metric} for tf.keras",
                      )
                  if hist_metric_name in compiled_metric_names:
                      metric_name = hist_metric_name
                  else:
                      invalidInputError(
                          False,
                          f"Input metric in fit_eval should be one of the metrics "
                          f"that are used to compile the model. Got metric value"
                          f" of {metric} and the metrics in compile are "
                          f"{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 = data[0]
              val_y = data[1]
          y_pred = self.predict(val_x)
          result = metric_func(val_y, y_pred)
          return {metric_name: result}
  
imports: from bigdl.orca.automl.model.abstract import BaseModel, ModelBuilder
  import numpy
  from bigdl.orca.automl.metrics import Evaluator
  from bigdl.orca.common import SafePickle
  import copy
  import tensorflow
  from tensorflow.keras import backend
  import types
  from bigdl.dllib.utils.log4Error import *
label_desc: Use image node_id 4 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, resources_per_trial) and returns: dict, dict