class_docstr: Class of experiment configuration. Check the reference_ for explaination of each field.
  
  When used in Python experiment API, it can be constructed in two favors:
  
  1. Create an empty project then set each field
  
  .. code-block:: python
  
      config = ExperimentConfig('local')
      config.search_space = {...}
      config.tuner.name = 'random'
      config.training_service.use_active_gpu = True
  
   2. Use kwargs directly
  
   .. code-block:: python
  
      config = ExperimentConfig(
          search_space = {...},
          tuner = AlgorithmConfig(name='random'),
          training_service = LocalConfig(
              use_active_gpu = True
          )
      )
  
  .. _reference: https://nni.readthedocs.io/en/stable/reference/experiment_config.html
class_docstr_tok: ["Class","of","experiment","configuration",".","Check","the","reference_","for","explaination","of","each","field",".","When","used","in","Python","experiment","API",",","it","can","be","constructed","in","two","favors",":","1",".","Create","an","empty","project","then","set","each","field","..","code-block",":",":","python","config","=","ExperimentConfig","(","'local","'",")","config.search_space","=","{","...","}","config.tuner.name","=","'random'","config.training_service.use_active_gpu","=","True","2",".","Use","kwargs","directly","..","code-block",":",":","python","config","=","ExperimentConfig","(","search_space","=","{","...","}",",","tuner","=","AlgorithmConfig","(","name='random","'",")",",","training_service","=","LocalConfig","(","use_active_gpu","=","True",")",")","..","_reference",":","https",":","\/\/nni.readthedocs.io\/en\/stable\/reference\/experiment_config.html"]
code: def _canonicalize(self, _parents):
      if self.log_level is None:
          self.log_level = "debug" if self.debug else "info"
      self.tuner_gpu_indices = utils.canonical_gpu_indices(
          self.tuner_gpu_indices
      )
  
      for algo_type in ["tuner", "assessor", "advisor"]:
          algo = getattr(self, algo_type)
  
          # TODO: need a more universal solution for similar problems
          if isinstance(algo, dict):
              # the base class should have converted it to `_AlgorithmConfig` if feasible
              # it is a `dict` here means an exception was raised during the convertion attempt
              # we do the convertion again to show user the error message
              _AlgorithmConfig(**algo)  # pylint: disable=not-a-mapping
  
          if algo is not None and algo.name == "_none_":  # type: ignore
              setattr(self, algo_type, None)
  
      if self.advisor is not None:
          assert (
              self.tuner is None
          ), '"advisor" is deprecated. You should only set "tuner".'
          self.tuner = self.advisor
          self.advisor = None
  
      super()._canonicalize([self])
  
      if self.search_space_file is not None:
          yaml_error = None
          try:
              self.search_space = _load_search_space_file(
                  self.search_space_file
              )
          except Exception as e:
              yaml_error = repr(e)
          if (
              yaml_error is not None
          ):  # raise it outside except block to make stack trace clear
              msg = f'ExperimentConfig: Failed to load search space file "{self.search_space_file}": {yaml_error}'
              raise ValueError(msg)
  
      if self.nni_manager_ip is None:
          # show a warning if user does not set nni_manager_ip. we have many issues caused by this
          # the simple detection logic won't work for hybrid, but advanced users should not need it
          # ideally we should check accessibility of the ip, but it need much more work
          platform = getattr(self.training_service, "platform")
          has_ip = isinstance(
              getattr(self.training_service, "nni_manager_ip"), str
          )  # not None or MISSING
          if platform and platform != "local" and not has_ip:
              ip = utils.get_ipv4_address()
              msg = f"nni_manager_ip is not set, please make sure {ip} is accessible from training machines"
              logging.getLogger("nni.experiment.config").warning(msg)
  
file_path: nni/nni/experiment/config/experiment_config.py
imports: from dataclasses import dataclass
  import json
  import logging
  from pathlib import Path
  from typing import Any, List, Optional, Union
  from typing_extensions import Literal
  import yaml
  from .algorithm import _AlgorithmConfig
  from .base import ConfigBase
  from .shared_storage import SharedStorageConfig
  from .training_service import TrainingServiceConfig
  from .None import utils
label_desc: Use image node_id 3 for calling the ExperimentConfig obj's underlying member method code with example usage: obj._canonicalize(_parents) without return types