Результаты модели tensorflow lite выглядят как StatefulPartitionedCall:n, чего не ожидается

#opencv #raspberry-pi #object-detection #tensorflow-lite #transfer-learning

Вопрос:

Мне нужно создать модель обнаружения объектов для использования с raspberry pi 4 и камерой. Для этого я создаю модель глубокого обучения с использованием обучения с передачей, основанную на модели ssd_mobilenet_v2_fpnlite_640x640_coco17_tpu-8. Документацию по этой модели можно найти здесь : документация по модели ssd_mobilenet_v2_fpnlite_640x640_coco17_tpu-8

Я использую tensorflow 2.5.0, и выходная модель (тип saved_model) работает хорошо. Когда я хочу проверить это в своей книге jupyter с изображением, точность действительно хорошая.

Проблема возникает, когда я пытаюсь преобразовать свою модель tensorflow (.pb) в tensorflow lite. Преобразование работает, но выходы не совпадают с моделью .pb, и я не нахожу никакой документации о 8 выходах этой модели .tflite.

Как вы можете видеть в документации выше, существует 8 выходных данных, содержащих num_detections, detection_boxes, detection_classes и т.д… и это прекрасно работает с использованием модели тензорного потока. Но когда я пытаюсь интерпретировать выходные данные модели tensorflow lite, выходные данные выглядят так :

 [{'dtype': <class 'numpy.float32'>,
  'index': 428,
  'name': 'StatefulPartitionedCall:7',
  'quantization': (0.0, 0),
  'quantization_parameters': {'quantized_dimension': 0,
                              'scales': array([], dtype=float32),
                              'zero_points': array([], dtype=int32)},
  'shape': array([    1, 51150,     4]),
  'shape_signature': array([    1, 51150,     4]),
  'sparsity_parameters': {}},
 {'dtype': <class 'numpy.float32'>,
  'index': 586,
  'name': 'StatefulPartitionedCall:4',
  'quantization': (0.0, 0),
  'quantization_parameters': {'quantized_dimension': 0,
                              'scales': array([], dtype=float32),
                              'zero_points': array([], dtype=int32)},
  'shape': array([1, 1]),
  'shape_signature': array([ 1, -1]),
  'sparsity_parameters': {}},
 {'dtype': <class 'numpy.float32'>,
  'index': 411,
  'name': 'StatefulPartitionedCall:6',
  'quantization': (0.0, 0),
  'quantization_parameters': {'quantized_dimension': 0,
                              'scales': array([], dtype=float32),
                              'zero_points': array([], dtype=int32)},
  'shape': array([    1, 51150,     4]),
  'shape_signature': array([    1, 51150,     4]),
  'sparsity_parameters': {}},
 {'dtype': <class 'numpy.float32'>,
  'index': 569,
  'name': 'StatefulPartitionedCall:5',
  'quantization': (0.0, 0),
  'quantization_parameters': {'quantized_dimension': 0,
                              'scales': array([], dtype=float32),
                              'zero_points': array([], dtype=int32)},
  'shape': array([1]),
  'shape_signature': array([1]),
  'sparsity_parameters': {}},
 {'dtype': <class 'numpy.float32'>,
  'index': 657,
  'name': 'StatefulPartitionedCall:1',
  'quantization': (0.0, 0),
  'quantization_parameters': {'quantized_dimension': 0,
                              'scales': array([], dtype=float32),
                              'zero_points': array([], dtype=int32)},
  'shape': array([1, 1, 1]),
  'shape_signature': array([ 1, -1, -1]),
  'sparsity_parameters': {}},
 {'dtype': <class 'numpy.float32'>,
  'index': 639,
  'name': 'StatefulPartitionedCall:2',
  'quantization': (0.0, 0),
  'quantization_parameters': {'quantized_dimension': 0,
                              'scales': array([], dtype=float32),
                              'zero_points': array([], dtype=int32)},
  'shape': array([1, 1]),
  'shape_signature': array([ 1, -1]),
  'sparsity_parameters': {}},
 {'dtype': <class 'numpy.float32'>,
  'index': 622,
  'name': 'StatefulPartitionedCall:3',
  'quantization': (0.0, 0),
  'quantization_parameters': {'quantized_dimension': 0,
                              'scales': array([], dtype=float32),
                              'zero_points': array([], dtype=int32)},
  'shape': array([1, 1, 1]),
  'shape_signature': array([ 1, -1, -1]),
  'sparsity_parameters': {}},
 {'dtype': <class 'numpy.float32'>,
  'index': 604,
  'name': 'StatefulPartitionedCall:0',
  'quantization': (0.0, 0),
  'quantization_parameters': {'quantized_dimension': 0,
                              'scales': array([], dtype=float32),
                              'zero_points': array([], dtype=int32)},
  'shape': array([1, 1]),
  'shape_signature': array([ 1, -1]),
  'sparsity_parameters': {}}]
 

Что такое ключ «StatefulPartitionedCall:n»? и как его использовать в отношении документации ?

Для информации я использую этот github для запуска своей модели : github, и с родной моделью он работает нормально, но не с моей :

 Traceback (most recent call last):
  File "TFLite_detection_webcam.py", line 219, in <module>
    if ((scores[i] > min_conf_threshold) and (scores[i] <= 1.0)):
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
 

Я полагаю, что методы анализа выходных данных не совпадают, и я действительно не знаю, как их анализировать.

Спасибо, что уделили мне время. Я потратил много времени, чтобы понять, почему это не работает, и я должен признать, что нахожусь перед стеной.

Ответ №1:

Это связано с тем, что имена тензоров в исходной модели отличаются от имен тензоров после сохранения модели. TFLite использует имена, найденные в сохраненной модели во время преобразования.

Вместо этого вы должны использовать SignatureDefs в TFLite, которые должны предоставлять значимые имена для доступа к входам и выходам. Смотрите полный пример здесь

Комментарии:

1. Большое спасибо, я попробую это и вернусь как можно скорее !