code: def link_choice_ids(layers, compile_params, extra_params, dimensions):
      """Update `extra_params` to include a "location" attribute on any descendants of
      :class:`space.Dimension`, specifying its position among all hyperparameters
  
      Parameters
      ----------
      layers: List
          A list of dicts, in which each dict describes a network layer
      compile_params: Dict
          A dict containing the hyperparameters supplied to the model's `compile` call
      extra_params: Dict
          A dict containing the hyperparameters for the model's extra methods, such as `fit`,
          `predict`, and `predict_proba`
      dimensions: List
          A list containing descendants of :class:`space.Dimension`, representing the entire
          hyperparameter search space
  
      Returns
      -------
      extra_params: Dict
          Mirrors the given `extra_params`, except any descendants of :class:`space.Dimension` now
          have a "location" attribute"""
  
      def visit_as(param_type):
          """Make visit func that prepends `param_type` to the "location" tuple added in `_visit`"""
          param_type = (
              (param_type,)
              if not isinstance(param_type, tuple)
              else param_type
          )
  
          def _visit(path, key, value):
              """If `value` is a descendant of :class:`space.Dimension`, add "location" to itself and
              its copy in `dimensions`"""
              if isinstance(value, (Real, Integer, Categorical)):
                  for i in range(len(dimensions)):
                      #################### Add `location` Attribute ####################
                      if dimensions[i].id == value.id:
                          setattr(
                              dimensions[i],
                              "location",
                              (param_type + path + (key,)),
                          )
                          setattr(
                              value,
                              "location",
                              (param_type + path + (key,)),
                          )
              return (key, value)
  
          return _visit
  
      #################### Enter Keras Callbacks ####################
      def _enter(path, key, value):
          """If `value` is in `keras.callbacks`, enter as a dict, iterating over non-magic attributes.
          Else, `default_enter`"""
          if isinstance(value, base_keras_callback):
              return dict(), [
                  (_, getattr(value, _))
                  for _ in dir(value)
                  if not _.startswith("__")
              ]
          return default_enter(path, key, value)
  
      #################### Enter Keras Initializer ####################
      def layer_enter(path, key, value):
          """If Keras `Initializer`, enter as dict, iterating over non-magic attributes"""
          if isinstance(value, BaseKerasInitializer):
              return (
                  dict(),
                  [
                      (_, getattr(value, _))
                      for _ in dir(value)
                      if _ != "__hh_previous_frame"
                      and not _.endswith("__")
                  ],
              )
          return default_enter(path, key, value)
  
      # TODO: Merge "__hh" attrs above into a single dict of attributes for initializers
      # TODO: Entering layer initializers like above will break matching when using default values
      # TODO: Currently, path is set to use "__hh_used_kwargs", which won't match if the default value is used
  
      # noinspection PyUnusedLocal
      _new_layers = remap(
          layers.copy(),
          visit=visit_as(("model_init_params", "layers")),
          enter=layer_enter,
      )
      # noinspection PyUnusedLocal
      _new_compile_params = remap(
          compile_params.copy(),
          visit=visit_as(("model_init_params", "compile_params")),
      )
      # noinspection PyUnusedLocal
      _extra_params = {
          k: v for k, v in extra_params.items() if k != "params"
      }
      # TODO: Replace above with `general_utils.subdict`
      _new_extra_params = remap(
          _extra_params,
          visit=visit_as("model_extra_params"),
          enter=_enter,
      )
  
      # `extra_params` has locations for `layers`, `compile_params`, `extra_params` - Of form expected by `build_fn` (less choices)
      return extra_params
  
imports: from hyperparameter_hunter.settings import G, TEMP_MODULES_DOT_PATH, TEMP_MODULES_DIR_PATH
  from hyperparameter_hunter.compat.keras_helper import parameterize_compiled_keras_model
  from hyperparameter_hunter.space.dimensions import Real, Integer, Categorical
  from hyperparameter_hunter.utils.boltons_utils import remap, default_enter
  from hyperparameter_hunter.utils.general_utils import deep_restricted_update, subdict
  from hyperparameter_hunter.utils.parsing_utils import stringify_model_builder, write_python, build_temp_model_file
  from collections import OrderedDict
  from copy import deepcopy
  from datetime import datetime
  from importlib.util import spec_from_file_location, module_from_spec
  import os
  import re
  import sys
  from types import FunctionType, MethodType
label_desc: Use image node_id 5 for calling a global function with example usage: link_choice_ids(layers, compile_params, extra_params, dimensions) and returns: extra_params, _visit, default_enter, default_enter, key,  value, dict,  unknown, dict,  unknown