一个简单的踩坑记录过程~
目标
在边缘设备使用AI加速硬件进行模型的加速,目前主流的边缘加速硬件有:npu,tpu,gpu。 由于边缘加速硬件的计算资源有限,这里一般指其一定精度的计算核数量。笔者手中的是只支持uint8类型模型的npu,
使用google的NNAPI代理来进行网络模型的加速。
量化过程(post training quantization)
可以参照官方给出的教程,
目前tf2.x全整型量化只支持int8类型
问题
- 确定目标AI加速硬件支持的不同类型的tflite:f32,f16,uint8,int8
- 目前tf2.x的全整型模型量化API只能支持int8类型的模型的量化
- 如果需要量化为uint8的整型模型,需要构建tf1.x(<tf1.15)环境下的网络,并且进行训练,然后使用
tf.compat.v1.lite
(tf2.x):
或者直接使用tf1.x环境下的量化接口进行uint8类型的模型量化:# 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)
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代理进行速度的测试
几个发现
首先是由于硬件NPU计算核的数量限制,如果量化之后的网络模型偏大(大于5MB),测试的结果显示,加速效果不好,这可能是在分配计算资源以及等待计算上耗费了大量的时间。
量化之后的网络模型能控制在5MB之内,对于分支比较多的网络(轻量型网络增加性能)还是加速效果不明显,此时硬件加速的效果和网络结构正相关,具体的测试结果可以参考下面的实验结果。
-
目前的测试效果,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 |
之后会进行量化训练之后的模型量化,然后会进一步给出模型精度的损失~