Error while compile yolov5 from onnx to hef

i have a custom yolov5 model with single class

i feel i need to make changes in .alls

pls help

hailomz compile yolov5s --hw-arch hailo8l --har /home/kenny/yolov5s.har --calib-path /home/kenny/images
Start run for network yolov5s …
Initializing the hailo8l runner…
Preparing calibration data…
[info] Loading model script commands to yolov5s from /home/kenny/hailo_model_zoo/hailo_model_zoo/cfg/alls/generic/yolov5s.alls
Traceback (most recent call last):
File “/home/kenny/hailodfc/bin/hailomz”, line 33, in
sys.exit(load_entry_point(‘hailo-model-zoo’, ‘console_scripts’, ‘hailomz’)())
File “/home/kenny/hailo_model_zoo/hailo_model_zoo/main.py”, line 122, in main
run(args)
File “/home/kenny/hailo_model_zoo/hailo_model_zoo/main.py”, line 111, in run
return handlersargs.command
File “/home/kenny/hailo_model_zoo/hailo_model_zoo/main_driver.py”, line 250, in compile
runner = _ensure_optimized(runner, logger, args, network_info)
File “/home/kenny/hailo_model_zoo/hailo_model_zoo/main_driver.py”, line 91, in _ensure_optimized
optimize_model(
File “/home/kenny/hailo_model_zoo/hailo_model_zoo/core/main_utils.py”, line 351, in optimize_model
optimize_full_precision_model(runner, calib_feed_callback, logger, model_script, resize, input_conversion, classes)
File “/home/kenny/hailo_model_zoo/hailo_model_zoo/core/main_utils.py”, line 337, in optimize_full_precision_model
runner.optimize_full_precision(calib_data=calib_feed_callback)
File “/home/kenny/hailodfc/lib/python3.10/site-packages/hailo_sdk_common/states/states.py”, line 16, in wrapped_func
return func(self, *args, **kwargs)
File “/home/kenny/hailodfc/lib/python3.10/site-packages/hailo_sdk_client/runner/client_runner.py”, line 2031, in optimize_full_precision
self._optimize_full_precision(calib_data=calib_data, data_type=data_type)
File “/home/kenny/hailodfc/lib/python3.10/site-packages/hailo_sdk_client/runner/client_runner.py”, line 2034, in _optimize_full_precision
self._sdk_backend.optimize_full_precision(calib_data=calib_data, data_type=data_type)
File “/home/kenny/hailodfc/lib/python3.10/site-packages/hailo_sdk_client/sdk_backend/sdk_backend.py”, line 1591, in optimize_full_precision
model, params = self._apply_model_modification_commands(model, params, update_model_and_params)
File “/home/kenny/hailodfc/lib/python3.10/site-packages/hailo_sdk_client/sdk_backend/sdk_backend.py”, line 1482, in _apply_model_modification_commands
model, params = command.apply(model, params, hw_consts=self.hw_arch.consts)
File “/home/kenny/hailodfc/lib/python3.10/site-packages/hailo_sdk_client/sdk_backend/script_parser/nms_postprocess_command.py”, line 397, in apply
self._update_config_file(hailo_nn)
File “/home/kenny/hailodfc/lib/python3.10/site-packages/hailo_sdk_client/sdk_backend/script_parser/nms_postprocess_command.py”, line 557, in _update_c
onfig_file self._layers_scope_addition(hailo_nn)
File “/home/kenny/hailodfc/lib/python3.10/site-packages/hailo_sdk_client/sdk_backend/script_parser/nms_postprocess_command.py”, line 600, in _layers_s
cope_addition bbox_decoder[field.value] = hailo_nn.get_layer_by_name(bbox_decoder[field.value]).name
File “/home/kenny/hailodfc/lib/python3.10/site-packages/hailo_sdk_common/hailo_nn/hailo_nn.py”, line 537, in get_layer_by_name
raise HailoNNException(f"The layer named {layer_name} doesn’t exist in the HN")
hailo_sdk_common.hailo_nn.exceptions.HailoNNException: The layer named conv63 doesn’t exist in the HN

Hey @user98,

The error hailo_sdk_common.hailo_nn.exceptions.HailoNNException: The layer named conv63 doesn't exist in the HN indicates that your compilation process is trying to reference a layer (conv63) that doesn’t exist in your custom YOLOv5 model.

You’ll need to modify your ALLS file to reference the correct layer name in your model. This typically happens when layer names have been changed during your training or conversion process.

To resolve this:

  1. Update the layer name in your ALLS file to match your model’s actual layer naming
  2. If you need assistance, please share your current ALLS file and information about the conv layers in your model

Also, did you run the optimization step after parsing and before compiling? This is a crucial step in the workflow that shouldn’t be skipped.

I was running into a pretty much identical error, and suspect others may too if they’re using yolo5 with DFC

My parsing step is as follows, with the start/end nodes based on what I found when opening in netron.app - you’ll find these final conv nodes right at the end of the model:

runner = ClientRunner(hw_arch=chosen_hw_arch)
hn, npz = runner.translate_onnx_model(
    onnx_path,
    onnx_model_name,
    start_node_names=["/model.0/conv/Conv"],
    end_node_names=["/model.24/m.2/Conv", 
                   "/model.24/m.1/Conv",
                   "/model.24/m.0/Conv"],
    net_input_shapes={"/model.0/conv/Conv": [1, 3, 640, 640]},
)

my alls script looks like:

alls =  """
normalization1 = normalization([0.0, 0.0, 0.0], [255.0, 255.0, 255.0])
change_output_activation(sigmoid)
nms_postprocess("/local/shared_with_docker/visdrone/postprocess_config/yolov5s_nms_config.json", yolov5, engine=cpu)
model_optimization_config(calibration, batch_size=1)
"""

I’ve pull this from the hailomz repo and edited only the nms path. The nms config I’ve copied from the repo and left unchanged

The original model was obtained by running the docker image, then running a simple:

python train.py --img 640 --batch 16 --epochs 300 --data coco128.yaml --weights yolov5s.pt --cfg models/yolov5s.yaml

python export.py --data=coco128.yaml --weights=yolov5s.pt --opset=14 --include onnx

However I wa getting ths ‘layer not found’ error when I ran:

runner.load_model_script(alls)
runner.optimize_full_precision()

Layer 63 is clearly used for box decoding in the nms file I linked above. I did’t understand why this isn’t found in my model

Though I recalled a guide for yolo11 and dfc here, they helpfully recommended using this to inspect your parsed model, because the nodes will get renamed. And indeed, when I checked for the original names of my end nodes, they’d been renamed. I needed to amend the nms_config file to match these layers:

from hailo_sdk_client import ClientRunner

# Load the HAR file
har_path = hailo_model_har_name

runner = ClientRunner(har=har_path)

from pprint import pprint

try:
    # Access the HailoNet as an OrderedDict
    hn_dict = runner.get_hn()  # Or use runner._hn if get_hn() is unavailable
    print("Inspecting layers from HailoNet (OrderedDict):")

    # Pretty-print each layer
    for key, value in hn_dict.items():
        print(f"Key: {key}")
        pprint(value)
        print("\n" + "="*80 + "\n")  # Add a separator between layers for clarity

except Exception as e:
    print(f"Error while inspecting hn_dict: {e}")

This yields the entire model dict, an example of which here:

 ('yolo5s/conv60',
              OrderedDict([('type', 'conv'),
                           ('input', ['yolo5s/conv59']),
                           ('output', ['yolo5s/output_layer3']),
                           ('input_shapes', [[-1, 20, 20, 512]]),
                           ('output_shapes', [[-1, 20, 20, 255]]),
                           ('original_names', ['/model.24/m.2/Conv']),
                           ('compilation_params', {}),
                           ('quantization_params', {}),
                           ('params',
                            OrderedDict([('kernel_shape', [1, 1, 512, 255]),
                                         ('strides', [1, 1, 1, 1]),
                                         ('dilations', [1, 1, 1, 1]),
                                         ('padding', 'VALID'),
                                         ('groups', 1),
                                         ('layer_disparity', 1),
                                         ('input_disparity', 1),
                                         ('batch_norm', False),
                                         ('elementwise_add', False),
                                         ('activation', 'linear')]))])),

here you’ll see that one of my final output layers is actually now called yolo5s/conv60 - yet this is absent in the nms_config file (which instead had conv63 listed, a layer I couldn’t see in the dict)

The fix was simple in the end, just map the output conv nodes to the ‘new name’, then ensure the nms file matches these. For example, in the case of this conv60 layer, I updated my nms as such:

        {
            "name": "bbox_decoder60",
            "w": [
                116,
                156,
                373
            ],
            "h": [
                90,
                198,
                326
            ],
            "stride": 32,
            "encoded_layer": "conv60"
        }

This seems to work as expected, I optimized the model and it has valid predictions. My question for @omria is why the yolo5s nms config file in the repo has different box decoder layer names to this yolo5s model I’ve used (since it wasn’t customised on any new data or amended otherwise)?

full error message which might help direct others here, since it doesn’t seem like a terribly common problem

---------------------------------------------------------------------------
HailoNNException                          Traceback (most recent call last)
Cell In [36], line 8
      1 alls =  """
      2 normalization1 = normalization([0.0, 0.0, 0.0], [255.0, 255.0, 255.0])
      3 change_output_activation(sigmoid)
      4 nms_postprocess("/local/shared_with_docker/visdrone/postprocess_config/yolov5s_nms_config.json", yolov5, engine=cpu)
      5 model_optimization_config(calibration, batch_size=1)
      6 """
      7 runner.load_model_script(alls)
----> 8 runner.optimize_full_precision()
     10 # runner.optimize(calib_dataset)

File /local/workspace/hailo_virtualenv/lib/python3.10/site-packages/hailo_sdk_common/states/states.py:16, in allowed_states.<locals>.wrap.<locals>.wrapped_func(self, *args, **kwargs)
     12 if self._state not in states:
     13     raise InvalidStateException(
     14         f"The execution of {func.__name__} is not available under the state: {self._state.value}",
     15     )
---> 16 return func(self, *args, **kwargs)

File /local/workspace/hailo_virtualenv/lib/python3.10/site-packages/hailo_sdk_client/runner/client_runner.py:2031, in ClientRunner.optimize_full_precision(self, calib_data, data_type)
   2022 if calib_data is None and not (
   2023     self._sdk_backend.calibration_data or self._sdk_backend.calibration_data_random_max
   2024 ):
   2025     self._logger.deprecation_warning(
   2026         "Optimizing in full precision will require calibration data "
   2027         "in the near future, to allow more accurate optimization "
   2028         "algorithms which require inference on actual data.",
   2029         DeprecationVersion.JUL2024,
   2030     )
-> 2031 self._optimize_full_precision(calib_data=calib_data, data_type=data_type)

File /local/workspace/hailo_virtualenv/lib/python3.10/site-packages/hailo_sdk_client/runner/client_runner.py:2034, in ClientRunner._optimize_full_precision(self, calib_data, data_type)
   2033 def _optimize_full_precision(self, calib_data=None, data_type=None):
-> 2034     self._sdk_backend.optimize_full_precision(calib_data=calib_data, data_type=data_type)
   2035     self._state = States.FP_OPTIMIZED_MODEL

File /local/workspace/hailo_virtualenv/lib/python3.10/site-packages/hailo_sdk_client/sdk_backend/sdk_backend.py:1591, in SDKBackendQuantization.optimize_full_precision(self, update_model_and_params, calib_data, data_type)
   1588         params = ModelParams({})
   1589     params.set_params_kind(ParamsKinds.FP_OPTIMIZED)
-> 1591 model, params = self._apply_model_modification_commands(model, params, update_model_and_params)
   1592 if calib_data is None:
   1593     self._logger.debug("Use random calibration data for full precision optimization")

File /local/workspace/hailo_virtualenv/lib/python3.10/site-packages/hailo_sdk_client/sdk_backend/sdk_backend.py:1482, in SDKBackendQuantization._apply_model_modification_commands(self, model, params, update_model_and_params)
   1474     self._logger.warning(
   1475         "Be advised the Dataflow Compiler default YUV to RGB/BGR conversion uses YUV601 standard, which is different than ISP and may cause accuracy degradation."
   1476         "For better results consider using yuv_full_range_to_rgb/bgr instead."
   1477     )
   1478     self._logger.warning(
   1479         "The Dataflow Compiler default YUV to RGB/BGR will be changed to yuv_full_range_to_rgb/bgr in the next version.",
   1480     )
-> 1482 model, params = command.apply(model, params, hw_consts=self.hw_arch.consts)
   1483 if update_model_and_params:
   1484     for layer_name in command.meta_data:

File /local/workspace/hailo_virtualenv/lib/python3.10/site-packages/hailo_sdk_client/sdk_backend/script_parser/nms_postprocess_command.py:397, in NMSPostprocessCommand.apply(self, hailo_nn, params, hw_consts)
    391 if self.engine == PostprocessTarget.NN_CORE.value:
    392     logger.warning(
    393         "Currently `nn-core` performs only score threshold. In the near future it will perform score"
    394         " + IoU threshold. If you want to apply IoU threshold please use `cpu` or `auto` instead",
    395     )
--> 397 self._update_config_file(hailo_nn)
    398 self.validate_nms_config_json()
    399 pp_creator = create_nms_postprocess(
    400     hailo_nn,
    401     params,
   (...)
    408     self.dfl_on_nn_core,
    409 )

File /local/workspace/hailo_virtualenv/lib/python3.10/site-packages/hailo_sdk_client/sdk_backend/script_parser/nms_postprocess_command.py:557, in NMSPostprocessCommand._update_config_file(self, hailo_nn)
    555 self._update_config_file_by_engine()
    556 self._update_command_args_in_config_file()
--> 557 self._layers_scope_addition(hailo_nn)
    558 self._update_config_layers(hailo_nn)

File /local/workspace/hailo_virtualenv/lib/python3.10/site-packages/hailo_sdk_client/sdk_backend/script_parser/nms_postprocess_command.py:600, in NMSPostprocessCommand._layers_scope_addition(self, hailo_nn)
    598 scope_addition_fields = [field for field in fields_with_layer_name if bbox_decoder.get(field.value)]
    599 for field in scope_addition_fields:
--> 600     bbox_decoder[field.value] = hailo_nn.get_layer_by_name(bbox_decoder[field.value]).name

File /local/workspace/hailo_virtualenv/lib/python3.10/site-packages/hailo_sdk_common/hailo_nn/hailo_nn.py:537, in HailoNN.get_layer_by_name(self, layer_name)
    532 if len(potential_matches) > 1:
    533     raise HailoNNException(
    534         f"The layer named {layer_name} exist under multiple scopes in the HN {[layer.scope for layer in potential_matches]}",
    535     )
--> 537 raise HailoNNException(f"The layer named {layer_name} doesn't exist in the HN")

HailoNNException: The layer named conv63 doesn't exist in the HN

Forgot to link the yolo11 guide I for the code snippit from.

Also for any future users coming across this - for clarity, my error, and looking at the OP’s error message, it is coming from the optimization step, not the compile to hef step as the title might suggest.

Additioanlly (this site badly needs an edit comment function) - I was using DFC while OP is using hailomz - however the errors are the same and would suggest a similar fix by inspecting your model’s renamed layers, finding the ‘correct’ endnode names then checking the nsm_config file that hailomz uses has the matching conv layers, if it doesn’t, copy and edit the file and point to your new, copied nsm_config