class_docstr: A Tuner class based on KerasTuner for AutoKeras.
  
  Different from KerasTuner's Tuner class. AutoTuner's not only tunes the
  Hypermodel which can be directly built into a Keras model, but also the
  preprocessors. Therefore, a HyperGraph stores the overall search space
  containing both the Preprocessors and Hypermodel. For every trial, the
  HyperGraph builds the PreprocessGraph and KerasGraph with the provided
  HyperParameters.
  
  The AutoTuner uses EarlyStopping for acceleration during the search and
  fully trains the model with full epochs and with both training and
  validation data.  The fully trained model is the best model to be used by
  AutoModel.
  
  # Arguments
      oracle: keras_tuner Oracle.
      hypermodel: keras_tuner HyperModel.
      **kwargs: The args supported by KerasTuner.
docstr: Search for the best HyperParameters.
  
  If there is not early-stopping in the callbacks, the early-stopping
  callback is injected to accelerate the search process. At the end of the
  search, the best model will be fully trained with the specified number
  of epochs.
  
  # Arguments
      callbacks: A list of callback functions. Defaults to None.
      validation_split: Float.
docstr_tok: ["Search","for","the","best","HyperParameters",".","If","there","is","not","early-stopping","in","the","callbacks",",","the","early-stopping","callback","is","injected","to","accelerate","the","search","process",".","At","the","end","of","the","search",",","the","best","model","will","be","fully","trained","with","the","specified","number","of","epochs",".","#","Arguments","callbacks",":","A","list","of","callback","functions",".","Defaults","to","None",".","validation_split",":","Float","."]
code: def search(
      self,
      epochs=None,
      callbacks=None,
      validation_split=0,
      verbose=1,
      **fit_kwargs,
  ):
      """Search for the best HyperParameters.
  
      If there is not early-stopping in the callbacks, the early-stopping
      callback is injected to accelerate the search process. At the end of the
      search, the best model will be fully trained with the specified number
      of epochs.
  
      # Arguments
          callbacks: A list of callback functions. Defaults to None.
          validation_split: Float.
      """
      if self._finished:
          return
  
      if callbacks is None:
          callbacks = []
  
      self.hypermodel.set_fit_args(validation_split, epochs=epochs)
  
      # Insert early-stopping for adaptive number of epochs.
      epochs_provided = True
      if epochs is None:
          epochs_provided = False
          epochs = 1000
          if not utils.contain_instance(
              callbacks, tf_callbacks.EarlyStopping
          ):
              callbacks.append(
                  tf_callbacks.EarlyStopping(
                      patience=10, min_delta=1e-4
                  )
              )
  
      # Insert early-stopping for acceleration.
      early_stopping_inserted = False
      new_callbacks = self._deepcopy_callbacks(callbacks)
      if not utils.contain_instance(
          callbacks, tf_callbacks.EarlyStopping
      ):
          early_stopping_inserted = True
          new_callbacks.append(
              tf_callbacks.EarlyStopping(patience=10, min_delta=1e-4)
          )
  
      # Populate initial search space.
      hp = self.oracle.get_space()
      self._prepare_model_build(hp, **fit_kwargs)
      self._try_build(hp)
      self.oracle.update_space(hp)
      super().search(
          epochs=epochs,
          callbacks=new_callbacks,
          verbose=verbose,
          **fit_kwargs,
      )
  
      # Train the best model use validation data.
      # Train the best model with enough number of epochs.
      if validation_split > 0 or early_stopping_inserted:
          copied_fit_kwargs = copy.copy(fit_kwargs)
  
          # Remove early-stopping since no validation data.
          # Remove early-stopping since it is inserted.
          copied_fit_kwargs["callbacks"] = self._remove_early_stopping(
              callbacks
          )
  
          # Decide the number of epochs.
          copied_fit_kwargs["epochs"] = epochs
          if not epochs_provided:
              copied_fit_kwargs[
                  "epochs"
              ] = self._get_best_trial_epochs()
  
          # Concatenate training and validation data.
          if validation_split > 0:
              copied_fit_kwargs["x"] = copied_fit_kwargs[
                  "x"
              ].concatenate(fit_kwargs["validation_data"])
              copied_fit_kwargs.pop("validation_data")
  
          self.hypermodel.set_fit_args(
              0, epochs=copied_fit_kwargs["epochs"]
          )
          copied_fit_kwargs["verbose"] = verbose
          pipeline, model, history = self.final_fit(**copied_fit_kwargs)
      else:
          # TODO: Add return history functionality in Keras Tuner
          model = self.get_best_models()[0]
          history = None
          pipeline = pipeline_module.load_pipeline(
              self._pipeline_path(
                  self.oracle.get_best_trials(1)[0].trial_id
              )
          )
  
      model.save(self.best_model_path)
      pipeline.save(self.best_pipeline_path)
      self._finished = True
      return history
  
imports: import collections
  import copy
  import os
  import keras_tuner
  from tensorflow import keras
  from tensorflow import nest
  from tensorflow.keras import callbacks
  from tensorflow.keras.layers.experimental import preprocessing
  from autokeras import pipeline
  from autokeras.utils import data_utils
  from autokeras.utils import utils
label_desc: Use image node_id 9 for calling the AutoTuner obj's underlying member method code with example usage: obj.search(epochs, callbacks, validation_split, verbose) and returns: history