code: def objective(self, params):
      # 1. Setup an config for a specific estimator process
      estimator_path = self.setup_estimator_config(params)
      self.logger.info("Searching params: {} ".format(params))
  
      # 2. Use subprocess to do the estimator program, this process will wait until subprocess finish
      sub_fails = subprocess.call(
          "estimator -c {}".format(estimator_path), shell=True
      )
      if sub_fails:
          # If this subprocess failed, ignore this evaluation step
          self.logger.info(
              "Estimator experiment failed when using this searching parameters"
          )
          return {"loss": np.nan, "status": STATUS_FAIL}
  
      # 3. Fetch the result of subprocess, and check whether the result is Nan
      res = self.fetch_result()
      if np.isnan(res):
          status = STATUS_FAIL
      else:
          status = STATUS_OK
  
      # 4. Save the best score and params
      if self.best_res is None or self.best_res > res:
          self.best_res = res
          self.best_params = params
  
      # 5. Return the result as optim objective
      return {"loss": res, "status": status}
  
imports: import os
  import yaml
  import json
  import copy
  import pickle
  import logging
  import importlib
  import subprocess
  import pandas
  import numpy
  from abc import abstractmethod
  from ...log import get_module_logger, TimeInspector
  from hyperopt import fmin, tpe
  from hyperopt import STATUS_OK, STATUS_FAIL
label_desc: Use image node_id 1 for calling the QLibTuner obj's underlying member method code with example usage: obj.objective(params) and returns: dict, dict