#python #tensorflow #tensorflow2.0 #tensorflow-lite #quantization
Вопрос:
Я хочу использовать генератор для квантования модели LSTM.
Вопросы
Я начинаю с вопроса, так как это довольно длинный пост. Я на самом деле хочу знать, удалось ли вам квантовать (int8) модель LSTM с квантованием после обучения.
Я пробовал разные версии TF, но всегда сталкивался с ошибкой. Ниже приведены некоторые из моих попыток. Может быть, вы видите ошибку, которую я допустил, или у вас есть предложение. Спасибо
Рабочая часть
Входные данные ожидаются как (пакет,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')
Форма и типы dtypes переменной data
являются (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
Using TF 2.2 as often suggested in Git, I run into non-supported operators from tflite. Using a tf2.2 created model to assure version-support. Here, only TOCO conversion is supported.
Some of the operators in the model are not supported by the standard
TensorFlow Lite runtime and are not recognized by TensorFlow.
The error does not depend on converter.target_spec.supported_ops
options. I could not find a solution therefore. allow_custom_ops only shifts the problem.
There are quite some git issues(just some examples) on this out there, but all suggested options did not work.
One is to try the new MILR converter, however, in 2.2 the integer only conversion for MILR was not done yet.
So lets try a newer version
TensorFlow 2.5.0
Then I tried a well vetted version. Here, no matter the converter.target_spec.supported_ops
I run in following error using the MLIR conversion:
in the calibrator.py
ValueError: Failed to parse the model: pybind11::init(): factory
function returned nullptr.
The solution on Git is to use TF==2.2.0 version.
With TOCO conversion, I get the following error:
tensorflow/lite/toco/allocate_transient_arrays.cc:181] An array,
StatefulPartitionedCall/StatefulPartitionedCall/model/lstm/TensorArrayUnstack/TensorListFromTensor,
still does not have a known data type after all graph transformations
have run. Fatal Python error: Aborted
I did not find anything on this error.
Maybe it is solved in 2.6
TensorFlow 2.6.0
Здесь, независимо от того, какой converter.target_spec.supported_ops
Я использую, я сталкиваюсь со следующей ошибкой:
Ошибка значения: Не удалось проанализировать модель: Поддерживаются только модели с одним подграфом, в модели было 5 подграфов.
Модель представляет собой пятислойную модель. Таким образом, кажется, что каждый слой рассматривается как подграф. Я не нашел ответа о том, как объединить их в один подграф. Проблема, по-видимому, связана с 2.6.0 и решена в 2.7, Так что давайте попробуем ночную сборку.
TensorFlow 2.7-ночью (пробовал 2.7.0-dev20210914 и 2.7.0-dev20210921)
Здесь мы должны использовать Python 3.7, так как 3.6 больше не поддерживается
Здесь мы должны использовать
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
же время ожидается получение конкретных данных генератора. Начиная со строки 93 и далее в _feed_tensor()
функции генератору требуется либо диктант, либо список, либо кортеж. В описании tf.lite.RepresentativeDataset
функции или описании класса tflite указано, что набор данных должен выглядеть так же, как входные данные для модели. Что в моем случае (в большинстве случаев) является просто массивом numpy в правильных размерах.
Здесь я мог бы попытаться преобразовать свои данные в кортеж, однако это кажется неправильным. Или это действительно правильный путь?
Большое спасибо, что прочитали все это. Если я найду ответ, я, конечно, обновлю сообщение
Ответ №1:
Если возможно, вы можете попробовать изменить свой LSTM, чтобы его можно было преобразовать в объединенный оператор LSTM TFLite. https://www.tensorflow.org/lite/convert/rnn Он поддерживает полноцелочисленное квантование для базовых слитых операторов LSTM и однонаправленных последовательностей LSTM.