【问题标题】:Int8 quantization of a LSTM model. No matter which version, I run into issuesLSTM 模型的 Int8 量化。无论哪个版本,我都会遇到问题
【发布时间】:2021-09-21 14:04:32
【问题描述】:

我想使用生成器来量化 LSTM 模型。

问题

我从这个问题开始,因为这是一篇很长的帖子。 我实际上想知道您是否已经设法通过训练后量化来量化(int8)LSTM 模型。

我尝试了不同的 TF 版本,但总是遇到错误。以下是我的一些尝试。也许您看到我犯的错误或有建议。 谢谢


工作部分

输入应为 (batch,1,45)。 使用未量化模型运行推理运行良好。模型和 csv 可以在这里找到:
csv 文件:https://mega.nz/file/5FciFDaR#Ev33Ij124vUmOF02jWLu0azxZs-Yahyp6PPGOqr8tok
模型文件:https://mega.nz/file/UAMgUBQA#oK-E0LjZ2YfShPlhHN3uKg8t7bALc2VAONpFirwbmys

import tensorflow as tf
import numpy as np
import pathlib as path
import pandas as pd  

def reshape_for_Lstm(data):    
    timesteps=1
    samples=int(np.floor(data.shape[0]/timesteps))
    data=data.reshape((samples,timesteps,data.shape[1]))   #samples, timesteps, sensors     
    return data

if __name__ == '__main__':

#GET DATA
    import pandas as pd
    data=pd.read_csv('./test_x_data_OOP3.csv', index_col=[0])
    data=np.array(data)
    data=reshape_for_Lstm(data)  
    
#LOAD MODEL
    saved_model_dir= path.Path.cwd() / 'model' / 'singnature_model_tf_2.7.0-dev20210914'    
    model=tf.keras.models.load_model(saved_model_dir)

# INFERENCE
    [yhat,yclass] = model.predict(data)    
    Yclass=[np.argmax(yclass[i],0) for i in range(len(yclass))] # get final class
    
    print('all good')

变量data的shape和dtypes是(20000,1,45), float64


哪里出错了

现在我想量化模型。但根据 TensorFlow 版本,我会遇到不同的错误。

我使用的代码选项合并如下:

    converter=tf.lite.TFLiteConverter.from_saved_model('./model/singnature_model_tf_2.7.0-dev20210914')
    converter.representative_dataset = batch_generator
    converter.optimizations = [tf.lite.Optimize.DEFAULT]         

    converter.experimental_new_converter = False  
   
    #converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] 
    converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8, tf.lite.OpsSet.TFLITE_BUILTINS]
    #converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS]
    
    #converter._experimental_lower_tensor_list_ops = False

    converter.target_spec.supported_types = [tf.int8]
    quantized_tflite_model = converter.convert()

TensorFlow 2.2

使用 Git 中经常建议的 TF 2.2,我遇到了 tflite 不支持的运算符。使用tf2.2 created model 来确保版本支持。这里只支持TOCO转换。

标准不支持模型中的某些运算符 TensorFlow Lite 运行时,TensorFlow 无法识别。

错误不依赖于converter.target_spec.supported_ops 选项。因此,我找不到解决方案。 allow_custom_ops 只会转移问题。 那里有quitesomegitissues(只是一些例子),但所有建议的选项都不起作用。
一种是尝试新的 MILR 转换器,然而,在 2.2 中,MILR was not done yet 的整数只转换。

让我们试试更新的版本


TensorFlow 2.5.0

然后我尝试了一个经过严格审查的版本。在这里,无论converter.target_spec.supported_ops 使用 MLIR 转换,我都会遇到以下错误:

in the calibrator.py

ValueError: 无法解析模型: pybind11::init(): factory 函数返回 nullptr。

solution on Git是使用TF==2.2.0版本的。

使用 TOCO 转换,我收到以下错误:

tensorflow/lite/toco/allocate_transient_arrays.cc:181] 一个数组, StatefulPartitionedCall/StatefulPartitionedCall/model/lstm/TensorArrayUnstack/TensorListFromTensor, 在所有图形转换之后仍然没有已知的数据类型 已经跑了。致命的 Python 错误:已中止

我没有找到有关此错误的任何信息。 也许它在 2.6 中解决了


TensorFlow 2.6.0

这里,无论我使用哪个converter.target_spec.supported_ops,都会遇到以下错误:

ValueError: 无法解析模型:只有具有单个 支持子图,模型有5个子图。

该模型是一个五层模型。所以似乎每一层都被视为一个子图。我没有找到关于如何将它们合并到一个子图中的答案。 The issue is apparently with 2.6.0is solved in 2.7 所以,让我们尝试夜间构建。


TensorFlow 2.7-nightly(已尝试 2.7.0-dev20210914 和 2.7.0-dev20210921)

这里我们必须使用 Python 3.7 作为3.6 is no longer supported

这里我们要使用

converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS]

然而,即使是这样说

converter._experimental_lower_tensor_list_ops = False

应该设置,好像没必要。

据我所知,这里的问题是tf.lite.OpsSet.SELECT_TF_OPS 调用calibrator.py。在calibrator.py 中,representative_dataset 需要特定的生成器数据。 From line 93 onwards_feed_tensor() 函数中,生成器需要字典、列表或元组。 在tf.lite.RepresentativeDataset 函数描述或tflite class description 中,它声明数据集应该与模型的输入看起来相同。在我的情况下(大多数情况下)只是一个正确尺寸的 numpy 数组。

在这里我可以尝试将我的数据转换为元组,但是,这似乎不对。 或者这实际上是要走的路?


非常感谢您阅读本文。如果我找到答案,我当然会更新帖子

【问题讨论】:

    标签: python tensorflow tensorflow2.0 tensorflow-lite quantization


    【解决方案1】:

    我和你有同样的问题,我仍在努力解决它,但我注意到我们的代码存在一些差异,因此分享它可能会很有用。

    我正在使用 TF 2.7.0,使用时转换工作正常:

    converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS, tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
    

    无论如何,据我所知,使用这些选项(如您所述)并不能保证您完全量化模型;因此,您可能无法像 Google Coral 一样将其完全部署在微控制器或 TPU 系统上。

    使用官方指南推荐的转换选项进行完整量化时:

    converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] 
    

    转换失败。

    我最近成功解决了这个问题!配置转换器的时候多加一行代码:

    converter.target_spec.supported_types = [tf.int8]
    

    这是我遵循的教程的链接:https://colab.research.google.com/github/google-coral/tutorials/blob/master/train_lstm_timeseries_ptq_tf2.ipynb#scrollTo=EBRDh9SZVBX1

    【讨论】:

    • 不错。我不再关注那个问题了,所以我目前无法测试它。但是太好了,您找到了解决方案。干杯
    【解决方案2】:

    如果可能,您可以尝试修改您的 LSTM,以便可以将其转换为 TFLite 的融合 LSTM 运算符。 https://www.tensorflow.org/lite/convert/rnn 支持基本融合 LSTM 和 UnidirectionalSequenceLSTM 算子的全整数量化。

    【讨论】:

      猜你喜欢
      • 2021-10-12
      • 2019-12-09
      • 2011-05-22
      • 2017-05-23
      • 2019-07-30
      • 2013-08-17
      • 1970-01-01
      • 2019-05-23
      • 2022-12-26
      相关资源
      最近更新 更多