Tf-model Quantization for edge NPU , TPU or GPU

一个简单的踩坑记录过程~

目标

在边缘设备使用AI加速硬件进行模型的加速,目前主流的边缘加速硬件有:npu,tpu,gpu。 由于边缘加速硬件的计算资源有限,这里一般指其一定精度的计算核数量。笔者手中的是只支持uint8类型模型的npu,
使用google的NNAPI代理来进行网络模型的加速。

量化过程(post training quantization)

可以参照官方给出的教程
目前tf2.x全整型量化只支持int8类型

问题

  1. 确定目标AI加速硬件支持的不同类型的tflite:f32,f16,uint8,int8
  2. 目前tf2.x的全整型模型量化API只能支持int8类型的模型的量化
  3. 如果需要量化为uint8的整型模型,需要构建tf1.x(<tf1.15)环境下的网络,并且进行训练,然后使用tf.compat.v1.lite(tf2.x):
    
    # Convert the model.
    converter = tf.compat.v1.lite.TFLiteConverter.from_frozen_graph(
        graph_def_file='/path/to/mobilenet_v1_1.0_224/frozen_graph.pb',
        input_arrays=['input'],
        input_shapes={'input' : [1, 224, 224,3]},
        output_arrays=['MobilenetV1/Predictions/Softmax'],
    )
    converter.quantized_input_stats = {'input' : (0., 1.)}  # mean, std_dev (input range is [-1, 1])
    converter.inference_type = tf.int8 # this is the recommended type.
    # converter.inference_input_type=tf.uint8 # optional
    # converter.inference_output_type=tf.uint8 # optional
    tflite_model = converter.convert()
    
    # Save the model.
    with open('quantized_model.tflite', 'wb') as f:
      f.write(tflite_model)
    
    或者直接使用tf1.x环境下的量化接口进行uint8类型的模型量化:
    
    saved_model_dir = "../../model_file/saved_model_dir"
    
    
    
    converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir,
                                                         input_arrays=["inputs"],
                                                         input_shapes={"inputs": [1, 256,256,3]},)
                                                         # output_arrays=["predictions"])
    converter.quantized_input_stats = {'inputs' : (0., 1.)}
    converter.inference_type = tf.uint8
    converter.default_ranges_stats=[-1,1]
    converter.inference_input_type=tf.uint8 # optional
    converter.inference_output_type=tf.uint8
    tflite_model = converter.convert()
    # open("tflite_model_v3/test_graph_uint8.tflite", "wb").write(tflite_model)
    
    # Save the model.
    with open('new_test_uint8.tflite', 'wb') as f:
      f.write(tflite_model)
    

4.可以选择在量化过程中对模型的输入和输出不做量化处理。 5.参考代码:https://github.com/CvHadesSun/Quantization_uint8
6.量化之后可以考虑使用google tensorflow模型量化教程中给出的测试工具开启NNAPI代理进行速度的测试

几个发现

  1. 首先是由于硬件NPU计算核的数量限制,如果量化之后的网络模型偏大(大于5MB),测试的结果显示,加速效果不好,这可能是在分配计算资源以及等待计算上耗费了大量的时间。

  2. 量化之后的网络模型能控制在5MB之内,对于分支比较多的网络(轻量型网络增加性能)还是加速效果不明显,此时硬件加速的效果和网络结构正相关,具体的测试结果可以参考下面的实验结果。

  3. 目前的测试效果,mobilienet几个版本的网络量化之后在NPU上加速明显,其结构特点:

    • 单分支的主干网络,没有多余的分支
    • 采用深度可分离卷积来保持较少的网络参数-->保证较小的网络模型

速度测试结果

测试环境:(Android9.0+tf1.13.1)
DM-AI-V1.1(haveing one NPU)

model name size(pre) size(post) NNAPI CPU quantization type
mobilenet_v1_224x224 - 4.3MB 8779.47us 25148.8us uint8
mobilenet_v1_0.25_224_quant - - 3545.98us 5657.02us uint8
mobilenet_v1_0.25_224_frozen_graph_uint8 - - 3580.18 5770.38 uint8
efficientnet_b0_224_integer_quant - 6.4MB 562020us 56277.3 uint8
blazepose_int8 3MB 1.8 MB 230055us 42359.3us int8
eval_lenet - 68KB 12495.2us 255.773us int8
blazepose_uint8 - 1.8MB 72155.5us 75281.5us uint8
mobilenet_v1_implement - 3.2MB 9566.68us 88748.4us uint8
resnet18 - 13.9MB 364117us 575283us uint8
resnet34 - 23.7MB 418595us 680163us uint8
resnet50 - 29.5MB 612458us 864814us uint8
dhrnet_model(paper) - 3.9MB 541260us 748692us uint8

之后会进行量化训练之后的模型量化,然后会进一步给出模型精度的损失~

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容