Day 20 : 模型优化 - 训练後量化 Post Training Quantization

  • 当我们训练模型需要部署在硬体较为受限的智慧型装置、IOT设备,模型运算在吃紧的硬体资源中显得笨重,此时可以采取模型优化策略改进。
  • 量化 Quantization 的好处:
    • 神经网路的参数真的很多也需要空间。
    • 减少档案大小。
    • 减少运算资源。
    • 达到更快更轻小的优化成果。

什麽是训练後量化 Post Training Quantization

  • 训练後量化 Post Training Quantization 是一种转换技术,可以减少模型大小,同时还可以改善 CPU 和硬件加速器的延迟,模型精度几乎没有下降。
  • 有多种训练後量化选项可供选择。以下是选择及其提供的好处的汇总表:
技术 好处 硬体
动态范围量化 小 4 倍,加速 2x-3x CPU
全INT量化 小 4 倍,加速 3x+ CPU、Edge TPU、微控制器
Float16 量化 小 2 倍,GPU 加速 CPU、GPU
  • 各种量化技术使用需求,TensorFlow Lite 文件整理出您可以透过以下决策树协助判断解决方案,帮助确定哪种训练後量化方法最适合您的用例:

如何进行训练後量化 Post Training Quantization

  • 当您使用TensorFlow Lite Converter将已训练的 TensorFlow 模型转换为 TensorFlow Lite 格式时,您可以对其进行量化 。

  • 另外 Pytorch 也有 QUANTIZATION 实作。

  • 以下实作范例可用 Colab 执行,另请注意 TensorFlow 版本需 >= 1.15 。

  • Colab 实作

建立基本模型

  • 模型采用tf.keras.datasets.mnist,用CNN进行建模。
  • 过程中储存基本模型权重档案baseline_weights.h5,储存量化前的模型non_quantized.h5,并记录模型大小与准确率,以进行训练後量化的比较。
  • 模型基本架构:

转为 TF Lite 格式

  • TensorFlow Lite 使用 *.tflite格式,用tf.lite.TFLiteConverter.from_keras_model转换先前建立的baseline_model。

    converter = tf.lite.TFLiteConverter.from_keras_model(baseline_model)
    
    tflite_model = converter.convert()
    
    with open('non_quantized.tflite', 'wb') as f:
        f.write(tflite_model)
    
  • 建立TF Lite 的评估模型准确率的函数,转档为tflite後需要特别撰写评估函数,参考并改写官方范例

    # A helper function to evaluate the TF Lite model using "test" dataset.
    # from: https://www.tensorflow.org/lite/performance/post_training_integer_quant_16x8#evaluate_the_models
    def evaluate_model(filemane):
      #Load the model into the interpreters
      interpreter = tf.lite.Interpreter(model_path=str(filemane))
      interpreter.allocate_tensors()
    
      input_index = interpreter.get_input_details()[0]["index"]
      output_index = interpreter.get_output_details()[0]["index"]
    
      # Run predictions on every image in the "test" dataset.
      prediction_digits = []
      for test_image in test_images:
        # Pre-processing: add batch dimension and convert to float32 to match with
        # the model's input data format.
        test_image = np.expand_dims(test_image, axis=0).astype(np.float32)
        interpreter.set_tensor(input_index, test_image)
    
        # Run inference.
        interpreter.invoke()
    
        # Post-processing: remove batch dimension and find the digit 
        # with highest probability.
        output = interpreter.tensor(output_index)
        digit = np.argmax(output()[0])
        prediction_digits.append(digit)
    
      # Compare prediction results with ground truth labels to calculate accuracy.
      accurate_count = 0
      for index in range(len(prediction_digits)):
        if prediction_digits[index] == test_labels[index]:
          accurate_count += 1
      accuracy = accurate_count * 1.0 / len(prediction_digits)
    
      return accuracy
    
  • 此时评估模型的准确率相近,模型尺寸减少。

    ACCURACY:
    {'baseline Keras model': 0.9581000208854675, 
     'non quantized tflite': 0.9581}
    
    MODEL_SIZE:
    {'baseline h5': 98136, 
     'non quantized tflite': 84688}
    

训练後量化 Post-Training Quantization

  • 本范例示范训练後量化之动态范围量化 Dynamic range quantization ,您也可以尝试固定float8、float16量化。
    # Dynamic range quantization
    converter = tf.lite.TFLiteConverter.from_keras_model(baseline_model)
    converter.optimizations = [tf.lite.Optimize.DEFAULT] #增加此设定
    tflite_model = converter.convert()
    
    with open('post_training_quantized.tflite', 'wb') as f:
        f.write(tflite_model)
    
  • 模型大小下降为原来1/4,精准度相近。
    ACCURACY:
    {'baseline Keras model': 0.9581000208854675,
     'non quantized tflite': 0.9581,
     'post training quantized tflite': 0.9582}
    
    MODEL_SIZE:
    {'baseline h5': 98136,
     'non quantized tflite': 84688,
     'post training quantized tflite': 24096} 
    

(选用)量化感知训练 Quantization Aware Training

  • 当训练後量化导致您的准确率下降多到无法接受,可以考虑在量化模型之前进行量化感知训练 Quantization Aware Training
  • 此方法为在训练期间在模型中插入假量化节点来模拟精度损失,让模型学会适应精度损失,以获得更准确的预测。
  • 需额外安装 tensorflow_model_optimization 模组,该模组提供 quantize_model() 完成任务。
  • 在 Colab 的示范中,是使用先前初步训练的 'baseline_weights.h5' 模型权重进行优化。您会发现模型增加了些假结点与 Layer。另训练经过感知训练的模型,您可以自行调整 epochs,范例只用 epochs = 1
  • 先感知训练後,模型经度略为改变,尺寸略增。
    ACCURACY:
    {'baseline Keras model': 0.9581000208854675,
     'non quantized tflite': 0.9581,
     'post training quantized tflite': 0.9582,
     'quantization aware non-quantized': 0.1005999967455864}
    
    MODEL_SIZE:
    {'baseline h5': 98136,
     'non quantized tflite': 84688,
     'post training quantized tflite': 24096,
     'quantization aware non-quantized': 115680} 
    
  • 调整後再执行 Post-Training Quantization 可舒缓准确率下降的问题,但本案例没有明显的精度损失,您有需要再试即可。

小结

  • 透过 Post Training Quantization 可以很明显的发现档案比单纯转换为 TensorFlow Lite 档案更小,会是未转换前的1/4,对IOT设备压力减轻很多,也是您可以采用的优化方案。本篇也提供了可以减缓转换过程精度损失过大的优化方式,供您参考。
  • 明日也会再与您分享与实作另一种优化方式-剪枝,我们下回见。

参考


<<:  用React刻自己的投资Dashboard Day5 - 多张图表渲染(Rendering lists)

>>:  Day 20:县市乡镇小工具包(util)

Day14. 时光时光慢些吧,让世界慢下来 - TimeScale

昨天看到运镜这词,大家是不是会想到拍电影呢?今天的主题也是跟电影有关的(?),大家看电影的时候,遇到...

那些被忽略但很好用的 Web API / 前言

Web API -- Application Programming Interface for ...

Day10:今天来讲一下microsoft defender for endpoint的装置执行动作

在我们导入microsoft defender for endpoint後,我们主要工作是修复事件。...

Day03-搞懂传址、传值? 电脑如何储存资料?

前言 昨日我们学习了资料的型态,今天我们要来了解变数的参考。 Pass by Value ? Str...

【从零开始的 C 语言笔记】第十九篇-While Loop(1)

不怎麽重要的前言 上一篇介绍了for loop的概念,让大家面对在有重复性、明确次数的处理时,可以使...