我正在使用我自己的数据集训练一个 keras 模型。然而,加载权重后,摘要显示 None 作为第一个维度(批量大小)。
我想知道将形状修复为批量大小为 1 的过程,因为我必须修复它,以便我可以将模型转换为具有 GPU 支持的 tflite。
对我有用的是指定输入层的批量大小,如下所示:
input = layers.Input(shape=input_shape, batch_size=1, dtype='float32', name='images')
然后这将贯穿其余各层。
坏消息是,尽管进行了“修复”,tfl 运行时仍然抱怨动态张量。 logcat 运行时我收到这些非致命错误:
E/tflite: third_party/tensorflow/lite/core/subgraph.cc:801 tensor.data.raw != nullptr was not true.
E/tflite: Attempting to use a delegate that only supports static-sized tensors with a graph that has dynamic-sized tensors (tensor#26 is a dynamic-sized tensor).
E/tflite: Ignoring failed application of the default TensorFlow Lite delegate indexed at 0.
好消息是,尽管存在这些错误,但根据性能测试,它似乎仍在使用 GPU。
我正在使用:
tensorflow-lite-support:0.2.0'
tensorflow-lite-metadata:0.2.1'
tensorflow-lite:2.6.0'
tensorflow:tensorflow-lite-gpu:2.3.0'
希望他们能够修复运行时问题,这样批量大小是否为“无”并不重要。进行推理应该没有关系。
我遇到了同样的问题,但在任何地方都找不到解决方案。不过,我设法通过一些解决方法解决了这个问题。
首先,您需要获取模型的配置:
model.get_config()
你会看到一个
batch_input_shape
{'name': 'sequential',
'layers': [{'class_name': 'InputLayer',
'config': {'batch_input_shape': (None, 28, 28, 1),
'dtype': 'float32',
'sparse': False,
...
接下来,您需要将
None
值更改为所需的批量大小。例如这样(改为1):
for layer in conf['layers']:
if 'batch_input_shape' in layer['config']:
shape = layer['config']['batch_input_shape']
shape = (1, *shape[1:])
layer['config']['batch_input_shape'] = shape
现在配置字典应该如下所示:
{'name': 'sequential',
'layers': [{'class_name': 'InputLayer',
'config': {'batch_input_shape': (1, 28, 28, 1),
'dtype': 'float32',
'sparse': False,
...
最后一步是根据新配置创建模型并根据初始模型设置权重。
new_model = model.from_config(conf)
new_model.set_weights(model.get_weights())
查看摘要,我们发现它有效:
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (1, 26, 26, 32) 320
max_pooling2d (MaxPooling2D) (1, 13, 13, 32) 0
@maciek97x 的答案帮助我找到了类似问题的替代方案,但它不适用于我试图在另一个场景中训练的预训练模型。此外,仅更改输入形状图层是不够的。我用TF测试过
2.15.0
正如您提到的,您使用自己的数据集训练了模型,我假设您拥有可用的模型定义。所以,对我有用的是:
加载预训练模型和自定义对象(如果适用)。
import re
import tensorflow as tf
# Model with old batch size
pre_trained_model = tf.keras.models.load_model(path_to_model_folder, custom_objects={"SomeCustomLayer": SomeCustomLayer})
生成具有相同定义的另一个模型,但将自定义层之外的操作替换为 TF 版本,例如将“+”和“*”替换为
tf.add(..)
和 tf.multiply(...)
。
batch_size = 1
data_input_layer = tf.keras.layers.Input(
shape=[128, 128, 3],
batch_size=batch_size,
)
# model definition ...
new_model = tf.keras.Model(
inputs=[data_input_layer],
outputs=[output],
)
将预训练的权重加载到新模型中
layer_dict = dict([(layer.name, layer) for layer in pre_trained_model.layers])
for i, layer in enumerate(model_full.layers):
# Check if there is any weights for the layer
if layer.get_weights():
# Get name without '_1', '_2', that can happen when you create two models with the same definition
name_filtered = re.sub(r'_\d+', '', layer.name)
pre_trained_weights = layer_dict[name_filtered].get_weights()
new_model.get_layer(layer.name).set_weights(pre_trained_weights)