簡體   English   中英

將 SSD object 檢測 model 轉換為 TFLite 並將其從 float 量化為 uint8 用於 EdgeTPU

[英]Converting SSD object detection model to TFLite and quantize it from float to uint8 for EdgeTPU

我在將 SSD object 檢測 model 轉換為 EdgeTPU 的 uint8 TFLite 時遇到問題。

據我所知,我一直在不同的論壇、堆棧溢出線程和 github 問題中進行搜索,我認為我正在遵循正確的步驟。 我的 jupyter 筆記本上一定有問題,因為我無法實現我的建議。

我正在與您分享我在 Jupyter Notebook 上解釋的步驟。 我想會更清楚。

#!/usr/bin/env python
# coding: utf-8

設置

此步驟是克隆存儲庫。 如果你以前做過一次,你可以省略這一步。

import os
import pathlib

# Clone the tensorflow models repository if it doesn't already exist
if "models" in pathlib.Path.cwd().parts:
  while "models" in pathlib.Path.cwd().parts:
    os.chdir('..')
elif not pathlib.Path('models').exists():
  !git clone --depth 1 https://github.com/tensorflow/models

進口

需要的步驟:這僅用於進行導入

import matplotlib
import matplotlib.pyplot as plt
import pathlib
import os
import random
import io
import imageio
import glob
import scipy.misc
import numpy as np
from six import BytesIO
from PIL import Image, ImageDraw, ImageFont
from IPython.display import display, Javascript
from IPython.display import Image as IPyImage

import tensorflow as tf
import tensorflow_datasets as tfds


from object_detection.utils import label_map_util
from object_detection.utils import config_util
from object_detection.utils import visualization_utils as viz_utils
#from object_detection.utils import colab_utils
from object_detection.utils import config_util
from object_detection.builders import model_builder

%matplotlib inline

下載友好的model

對於 tflite,建議使用 SSD 網絡。 我已經下載了以下model,它是關於“物體檢測”的。 它適用於 320x320 圖像。
!tflite_convert --saved_model_dir=/home/jose/codeWorkspace-2.4.1/tf_2.4.1/tflite/saved_model --output_file=/home/jose/codeWorkspace-2.4.1/tf_2.4.1/tflite/model.tflite

用於為每個框添加正確 label 的字符串列表。

 PATH_TO_LABELS = '/home/jose/codeWorkspace-2.4.1/tf_2.4.1/models/research/object_detection/data/mscoco_label_map.pbtxt' category_index = label_map_util.create_category_index_from_labelmap(PATH_TO_LABELS, use_display_name=True)

使用 TFLite 導出和運行

Model轉換

在這一步中,我將 pb 保存的 model 轉換為.tflite

 .tflite_convert --saved_model_dir=/home/jose/codeWorkspace-2.4.1/tf_2.4.1/tflite/saved_model --output_file=/home/jose/codeWorkspace-2.4.1/tf_2.4.1/tflite/model.tflite

Model 量化(從浮點到 uint8)

一旦 model 被轉換,我需要量化它。 原來的 model 選擇一個浮點數作為張量輸入。 因為我想在 Edge TPU 上運行它,所以我需要輸入和 output 張量為 uint8。

生成校准數據集。

 def representative_dataset_gen(): folder = "/home/jose/codeWorkspace-2.4.1/tf_2.4.1/images_ssd_mb2_2" image_size = 320 raw_test_data = [] files = glob.glob(folder+'/*.jpeg') for file in files: image = Image.open(file) image = image.convert("RGB") image = image.resize((image_size, image_size)) #Quantizing the image between -1,1; image = (2.0 / 255.0) * np.float32(image) - 1.0 #image = np.asarray(image).astype(np.float32) image = image[np.newaxis,:,:,:] raw_test_data.append(image) for data in raw_test_data: yield [data]

(不要運行這個)。 這是上述步驟,但具有隨機值

如果您沒有數據集,您也可以引入隨機生成的值,就像它是圖像一樣。 這是我以前這樣做的代碼:
 ####THIS IS A RANDOM-GENERATED DATASET#### def representative_dataset_gen(): for _ in range(320): data = np.random.rand(1, 320, 320, 3) yield [data.astype(np.float32)]

要求model轉換

converter = tf.lite.TFLiteConverter.from_saved_model('/home/jose/codeWorkspace-2.4.1/tf_2.4.1/tflite/saved_model') converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8, tf.lite.OpsSet.SELECT_TF_OPS] converter.inference_input_type = tf.uint8 converter.inference_output_type = tf.uint8 converter.allow_custom_ops = True converter.representative_dataset = representative_dataset_gen tflite_model = converter.convert()

警告:

轉換步驟返回警告。

警告:absl:對於包含無法量化的不受支持的操作的 model 輸入, inference_input_type屬性將默認為原始類型。 警告:absl:對於包含無法量化的不受支持的操作的 model 輸出, inference_output_type屬性將默認為原始類型。

這讓我覺得轉換是不正確的。

保存 model

 with open('/home/jose/codeWorkspace-2.4.1/tf_2.4.1/tflite/model_full_integer_quant.tflite'.format('/home/jose/codeWorkspace-2.4.1/tf_2.4.1/tflite/saved_model'), 'wb') as w: w.write(tflite_model) print("tflite convert complete. - {}/home/jose/codeWorkspace-2.4.1/tf_2.4.1/tflite/model_full_integer_quant.tflite".format('/home/jose/codeWorkspace-2.4.1/tf_2.4.1/tflite/saved_model'))

測試

測試一:獲取TensorFlow版本

我讀到建議為此使用 nightly 。 所以就我而言,版本是 2.6.0

 print(tf.version.VERSION)

測試 2:獲取輸入/輸出張量詳細信息

interpreter = tf.lite.Interpreter(model_path="/home/jose/codeWorkspace-2.4.1/tf_2.4.1/tflite/model_full_integer_quant.tflite") interpreter.allocate_tensors() print(interpreter.get_input_details()) print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@") print(interpreter.get_output_details())

測試 2 結果:

我得到以下信息:

[{'name': 'serving_default_input:0', 'index': 0, 'shape': array([ 1, 320, 320, 3], dtype=int32), 'shape_signature': array([ 1, 320, 320, 3], dtype=int32), 'dtype': <class 'numpy.uint8'>, 'quantization': (0.007843137718737125, 127), 'quantization_parameters': {'scales': array([0.00784314], dtype= float32), 'zero_points': 數組([127], dtype=int32), 'quantized_dimension': 0}, 'sparsity_parameters': {}}] @@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@

[{'name': 'StatefulPartitionedCall:31', 'index': 377, 'shape': array([ 1, 10, 4], dtype=int32), 'shape_signature': array([ 1, 10, 4] , dtype=int32), 'dtype': <class 'numpy.float32'>, 'quantization': (0.0, 0), 'quantization_parameters': {'scales': array([], dtype=float32), 'zero_points ': array([], dtype=int32), 'quantized_dimension': 0}, 'sparsity_parameters': {}}, {'name': 'StatefulPartitionedCall:32', 'index': 378, 'shape': array( [ 1, 10], dtype=int32), 'shape_signature': array([ 1, 10], dtype=int32), 'dtype': <class 'numpy.float32'>, 'quantization': (0.0, 0) , 'quantization_parameters': {'scales': array([], dtype=float32), 'zero_points': array([], dtype=int32), 'quantized_dimension': 0}, 'sparsity_parameters': {}}, { 'name': 'StatefulPartitionedCall:33', 'index': 379, 'shape': array([ 1, 10], dtype=int32), 'shape_signature': array([ 1, 10], dtype=int32), 'dtype': <class 'numpy.float32'>, 'quantization': (0.0, 0), 'quantization_parameters': {'scales': array([], dtype=float32), 'zero_poin ts': array([], dtype=int32), 'quantized_dimension': 0}, 'sparsity_parameters': {}}, {'name': 'StatefulPartitionedCall:34', 'index': 380, 'shape': array ([1], dtype=int32), 'shape_signature': array([1], dtype=int32), 'dtype': <class 'numpy.float32'>, 'quantization': (0.0, 0), 'quantization_parameters ': {'scales': array([], dtype=float32), 'zero_points': array([], dtype=int32), 'quantized_dimension': 0}, 'sparsity_parameters': {}}]

所以,我認為它沒有正確量化它

將生成的 model 轉換為 EdgeTPU

 .edgetpu_compiler -s /home/jose/codeWorkspace-2.4.1/tf_2.4.1/tflite/model_full_integer_quant.tflite

jose@jose-VirtualBox:~/python-envs$ edgetpu_compiler -s /home/jose/codeWorkspace-2.4.1/tf_2.4.1/tflite/model_full_integer_quant.tflite Edge TPU 編譯器版本 15.0.340273435

Model 在 1136 毫秒內編譯成功。

Input model: /home/jose/codeWorkspace-2.4.1/tf_2.4.1/tflite/model_full_integer_quant.tflite Input size: 3.70MiB Output model: model_full_integer_quant_edgetpu.tflite Output size: 4.21MiB On-chip memory used for caching model parameters: 3.42 MiB On-chip memory remaining for caching model parameters: 4.31MiB Off-chip memory used for streaming uncached model parameters: 0.00B Number of Edge TPU subgraphs: 1 Total number of operations: 162 Operation log: model_full_integer_quant_edgetpu.log

Model 編譯成功,但 Edge TPU 並不支持所有操作。 model 的一部分將在 CPU 上運行,這會更慢。 如果可能,請考慮更新您的 model 以僅使用 Edge TPU 支持的操作。 有關詳細信息,請訪問 g.co/coral/model-reqs。 將在 Edge TPU 上運行的操作數:112 將在 CPU 上運行的操作數:50

操作員計數狀態

LOGISTIC 1 操作在其他方面受支持,但由於某些未指定的限制而未映射 DEPTHWISE_CONV_2D 14 不支持多個子圖 DEPTHWISE_CONV_2D 37 映射到邊緣 TPU QUANTIZE 1 映射到邊緣 TPU QUANTIZE 4 否則支持操作,但由於某些未指定而未映射限制 CONV_2D
58 映射到邊緣 TPU CONV_2D 14
不支持多個子圖 DEQUANTIZE
1 操作正在處理不受支持的數據類型 DEQUANTIZE 1 操作在其他方面受支持,但由於某些未指定的限制而未映射 CUSTOM 1
操作正在處理不受支持的數據類型 ADD
2 不支持多於一個子圖 ADD
10 映射到邊緣 TPU 連接 1
否則支持操作,但由於某些未指定的限制而未映射 CONCATENATION 1 不支持多個子圖 RESHAPE 2
否則支持操作,但由於某些未指定的限制而未映射 RESHAPE 6
映射到邊緣 TPU RESHAPE 4 不支持多個子圖 PACK 4
張量的等級不受支持(最多映射 3 個最內層維度)

我准備的jupyter notebook可以在以下鏈接找到: https://github.com/jagumiel/Artificial-Intelligence/blob/main/tensorflow-scripts/Step-by-step-explaining-problems.ipynb

有沒有我遺漏的步驟? 為什么沒有導致我的轉換?

非常感謝您提前。

正如@JaesungChung 回答的那樣,這個過程做得很好。

我的問題出在運行 .tflite model 的應用程序上。 我將我的 model output 量化為 uint8,因此我必須重新調整獲得的值以獲得正確的結果。

即我有 10 個對象,因為我要求所有檢測到的對象得分高於 0.5。 我的結果沒有按比例縮放,因此檢測到的對象分數可能是完美的 104。我必須重新縮放該數字除以 255。

繪制我的結果時也發生了同樣的情況。 所以我不得不把這個數字除以高度和寬度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM