Tensorflow 量化 - 无法解析模型:pybind11::init():工厂函数返回 nullptr
Tensorflow Quantization - Failed to parse the model: pybind11::init(): factory function returned nullptr
我正在研究要部署在嵌入式系统上的 TensorFlow 模型。为此,我需要将模型量化为 int8。
该模型由三个不同的模型组成:
- CNN 作为特征提取器
- 用于时间预测的 TCN
- FC/Dense 作为最后一个分类器。
我从 this post 开始实施了 TCN,并做了一些修改。本质上,TCN 只是一组一维卷积(带有一些 0 填充)加上一个加法运算。
## Define TCN newer
tcn_input = tf.keras.Input(shape=tf.keras.backend.int_shape(glue)[1:])
# first causal conv for channel adaptation
k=1; d=1; padding = (k - 1) * d
# tcn_input_p = tf.pad(tcn_input, tf.constant([(0,0), (1,0), (0,0)]) * padding)
temp_block_input = tf.keras.layers.Conv1D(32,k, padding='valid', data_format='channels_last', name='adapt_conv')(tcn_input)
# TEMPORAL BLOCK 1
k=2; d=1; padding = (k - 1) * d
# temp_block_input_p = tf.pad(temp_block_input, tf.constant([(0,0), (1,0), (0,0)]) * padding)
temp_block_input_p = tf.keras.layers.ZeroPadding1D((padding, 0))(temp_block_input)
x = tf.keras.layers.Conv1D(32,k, padding='valid', data_format='channels_last', dilation_rate=d, activation='relu', name='conv1')(temp_block_input_p)
temp_block_input = tf.keras.layers.Add()([temp_block_input, x])
# TEMPORAL BLOCK 2
k=2; d=2; padding = (k - 1) * d
# temp_block_input_p = tf.pad(temp_block_input, tf.constant([(0,0), (1,0), (0,0)]) * padding)
temp_block_input_p = tf.keras.layers.ZeroPadding1D((padding, 0))(temp_block_input)
x = tf.keras.layers.Conv1D(32,k, padding='valid', data_format='channels_last', dilation_rate=d, activation='relu', name='conv2')(temp_block_input_p)
temp_block_input = tf.keras.layers.Add()([temp_block_input, x])
# TEMPORAL BLOCK 3
k=2; d=4; padding = (k - 1) * d
# temp_block_input_p = tf.pad(temp_block_input, tf.constant([(0,0), (1,0), (0,0)]) * padding)
temp_block_input_p = tf.keras.layers.ZeroPadding1D((padding, 0))(temp_block_input)
x = tf.keras.layers.Conv1D(32,k, padding='valid', data_format='channels_last', dilation_rate=d, activation='relu', name='conv3')(temp_block_input_p)
x = tf.keras.layers.Add()([temp_block_input, x])
tcn = tf.keras.Model(tcn_input, x, name='tcn')
tcn.summary()
我尝试使用以下代码量化 TCN(适用于其他模型,例如 CNN)
converter = tf.lite.TFLiteConverter.from_keras_model(tcn)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8
converter.inference_output_type = tf.int8
def representative_dataset(): # generate the inputs
for sample in x_train:
yield [cnn(i) for i in sample]
converter.representative_dataset = representative_dataset
quant_model = converter.convert()
with open(os.path.join('models','tcn_q.bin'), 'wb') as f:
f.write(quant_model)
我收到以下错误。我也没有成功尝试以下:
- 使用格式 saved_model 然后
tf.lite.TFLiteConverter.from_saved_model(path)
- 使用
tf.Add
和 tf.pad
而不是 keras API
- 删除添加操作以使模型顺序化
Failed to parse the model: pybind11::init(): factory function returned nullptr.
到目前为止我找不到解决方案,但我相信应该可以量化这个网络,因为我使用的操作是基本的并且应该得到支持。
如果有任何想法,我也可以使用一些解决方法,但我想了解是哪一部分造成了问题。
作为侧节点,我还使用 netron.app 检查了网络,似乎使用一些额外的 Reshape、ExpandDims 和 BatchToSpace 层将 1D 卷积转换为 2D 卷积。不过我不确定这是否是个问题。
根据@JaesungChung的建议,问题似乎可以使用 tf-nightly 解决(我在 2.5.0-dev20210325 上测试过)。
在 2.4.0 中使用变通方法将 Conv1D 转换为宽度为 1 的 Conv2D 并使用扁平内核 (1, kernel_size) 可以获得相同的效果。
我正在研究要部署在嵌入式系统上的 TensorFlow 模型。为此,我需要将模型量化为 int8。 该模型由三个不同的模型组成:
- CNN 作为特征提取器
- 用于时间预测的 TCN
- FC/Dense 作为最后一个分类器。
我从 this post 开始实施了 TCN,并做了一些修改。本质上,TCN 只是一组一维卷积(带有一些 0 填充)加上一个加法运算。
## Define TCN newer
tcn_input = tf.keras.Input(shape=tf.keras.backend.int_shape(glue)[1:])
# first causal conv for channel adaptation
k=1; d=1; padding = (k - 1) * d
# tcn_input_p = tf.pad(tcn_input, tf.constant([(0,0), (1,0), (0,0)]) * padding)
temp_block_input = tf.keras.layers.Conv1D(32,k, padding='valid', data_format='channels_last', name='adapt_conv')(tcn_input)
# TEMPORAL BLOCK 1
k=2; d=1; padding = (k - 1) * d
# temp_block_input_p = tf.pad(temp_block_input, tf.constant([(0,0), (1,0), (0,0)]) * padding)
temp_block_input_p = tf.keras.layers.ZeroPadding1D((padding, 0))(temp_block_input)
x = tf.keras.layers.Conv1D(32,k, padding='valid', data_format='channels_last', dilation_rate=d, activation='relu', name='conv1')(temp_block_input_p)
temp_block_input = tf.keras.layers.Add()([temp_block_input, x])
# TEMPORAL BLOCK 2
k=2; d=2; padding = (k - 1) * d
# temp_block_input_p = tf.pad(temp_block_input, tf.constant([(0,0), (1,0), (0,0)]) * padding)
temp_block_input_p = tf.keras.layers.ZeroPadding1D((padding, 0))(temp_block_input)
x = tf.keras.layers.Conv1D(32,k, padding='valid', data_format='channels_last', dilation_rate=d, activation='relu', name='conv2')(temp_block_input_p)
temp_block_input = tf.keras.layers.Add()([temp_block_input, x])
# TEMPORAL BLOCK 3
k=2; d=4; padding = (k - 1) * d
# temp_block_input_p = tf.pad(temp_block_input, tf.constant([(0,0), (1,0), (0,0)]) * padding)
temp_block_input_p = tf.keras.layers.ZeroPadding1D((padding, 0))(temp_block_input)
x = tf.keras.layers.Conv1D(32,k, padding='valid', data_format='channels_last', dilation_rate=d, activation='relu', name='conv3')(temp_block_input_p)
x = tf.keras.layers.Add()([temp_block_input, x])
tcn = tf.keras.Model(tcn_input, x, name='tcn')
tcn.summary()
我尝试使用以下代码量化 TCN(适用于其他模型,例如 CNN)
converter = tf.lite.TFLiteConverter.from_keras_model(tcn)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8
converter.inference_output_type = tf.int8
def representative_dataset(): # generate the inputs
for sample in x_train:
yield [cnn(i) for i in sample]
converter.representative_dataset = representative_dataset
quant_model = converter.convert()
with open(os.path.join('models','tcn_q.bin'), 'wb') as f:
f.write(quant_model)
我收到以下错误。我也没有成功尝试以下:
- 使用格式 saved_model 然后
tf.lite.TFLiteConverter.from_saved_model(path)
- 使用
tf.Add
和tf.pad
而不是 keras API - 删除添加操作以使模型顺序化
Failed to parse the model: pybind11::init(): factory function returned nullptr.
到目前为止我找不到解决方案,但我相信应该可以量化这个网络,因为我使用的操作是基本的并且应该得到支持。 如果有任何想法,我也可以使用一些解决方法,但我想了解是哪一部分造成了问题。
作为侧节点,我还使用 netron.app 检查了网络,似乎使用一些额外的 Reshape、ExpandDims 和 BatchToSpace 层将 1D 卷积转换为 2D 卷积。不过我不确定这是否是个问题。
根据@JaesungChung的建议,问题似乎可以使用 tf-nightly 解决(我在 2.5.0-dev20210325 上测试过)。
在 2.4.0 中使用变通方法将 Conv1D 转换为宽度为 1 的 Conv2D 并使用扁平内核 (1, kernel_size) 可以获得相同的效果。