在进行对象识别时,经常使用来自ONNX模型动物园的网络模型。本文将探讨如何进一步优化这些网络模型。在神经网络模型中,一个常见的挑战是如何在可用资源和准确性之间找到正确的平衡。通常,如果模型变得更加复杂,它可能会更准确,但同时也会消耗更多的存储空间,执行时间更长,或者在下载时消耗更多的网络带宽。并非所有的优化都能在所有硬件上运行。
如果使用的是第三方提供的网络,提高性能的尝试可能从后训练优化开始。对于预训练网络,可以通过量化来改变网络。量化会降低网络参数的精度,这些参数通常是32位浮点数。应用量化后,可以将浮点运算转换为整数或16位浮点运算,这将提高运行速度,但精度略有降低。在本系列文章的早期部分,使用Python代码将模型从TensorFlow转换为TensorFlow Lite。稍作修改后,转换器在转换过程中也会执行8位整数量化:
import tensorflow as tf
saved_model_dir = '/dev/projects/models'
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.uint8
converter.inference_output_type = tf.uint8
tf_lite_model = converter.convert()
open('output.tflite', 'wb').write(tf_lite_model)
并非所有模型都可以这样转换。如果模型不兼容8位量化,上述代码将抛出错误。可能会想知道除了DEFAULT之外,还可以向converter.optimizations传递哪些其他值。在TensorFlow的早期版本中,可以在这里传递值以优化网络的大小或延迟。这些值目前已弃用,并且现在对结果没有影响。
如果32位浮点数到8位整数量化过于极端,可以将网络转换为使用16位浮点数:
import tensorflow as tf
saved_model_dir = '/dev/projects/models'
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_types = [tf.float16]
tf_lite_model = converter.convert()
open('output.tflite', 'wb').write(tf_lite_model)
通过上述模型量化,只有在模型在支持16位浮点数的硬件上执行时(例如GPU),才能体验到优势。如果在CPU上执行,网络权重将在执行前扩展为32位浮点数。在CPU上,与未优化的等效网络相比,会有轻微的精度损失,且性能没有提高。
为了优化网络的大小,可以考虑网络剪枝。在剪枝过程中,会移除对准确性贡献较小的网络部分,从而实现更紧密的网络压缩。要对网络进行剪枝,需要安装一个额外的tensorflow库:
pip install -q tensorflow-model-optimization
import tensorflow_model_optimization as tfmot
pruned_model = tfmot.sparsity.keras.prune_low_magnitude(source_model)