Keras 加载 SavedModel 失败:TypeError 'module' object is not callable
Keras failed to load SavedModel: TypeError 'module' object is not callable
我使用 TensorFlow Object Detection API with TensorFlow 2 and then converted the trained model into a SavedModel. Now I need to convert the SavedModel to a FrozenGraph in order to make the model compatible with external libraries like OpenCV. I use this example 训练了一个 SSD MobileNet v2 网络进行转换,但我什至无法加载 Keras 模型。
from keras.models import load_model
model = load_model("training/model/saved_model")
调用load_model()
产生异常:
Exception has occurred: TypeError
'module' object is not callable
Full traceback:
Traceback (most recent call last):
File "path\to\tensorflow\python\util\dispatch.py", line 201, in wrapper
return target(*args, **kwargs)
TypeError: 'str' object is not callable
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "path\to\saved_model_to_frozen_graph.py", line 17, in <module>
model = load_model("saved_model")
File "path\to\tensorflow\python\keras\saving\save.py", line 187, in load_model
return saved_model_load.load(filepath, compile, options)
File "path\to\tensorflow\python\keras\saving\saved_model\load.py", line 121, in load
path, options=options, loader_cls=KerasObjectLoader)
File "path\to\tensorflow\python\saved_model\load.py", line 633, in load_internal
ckpt_options)
File "path\to\tensorflow\python\keras\saving\saved_model\load.py", line 194, in __init__
super(KerasObjectLoader, self).__init__(*args, **kwargs)
File "path\to\tensorflow\python\saved_model\load.py", line 130, in __init__
self._load_all()
File "path\to\tensorflow\python\keras\saving\saved_model\load.py", line 221, in _load_all
self._finalize_objects()
File "path\to\tensorflow\python\keras\saving\saved_model\load.py", line 530, in _finalize_objects
self._reconstruct_all_models()
File "path\to\tensorflow\python\keras\saving\saved_model\load.py", line 548, in _reconstruct_all_models
self._reconstruct_model(model_id, model, layers)
File "path\to\tensorflow\python\keras\saving\saved_model\load.py", line 589, in _reconstruct_model
config, created_layers={layer.name: layer for layer in layers})
File "path\to\tensorflow\python\keras\engine\functional.py", line 1215, in reconstruct_from_config
process_node(layer, node_data)
File "path\to\tensorflow\python\keras\engine\functional.py", line 1163, in process_node
output_tensors = layer(input_tensors, **kwargs)
File "path\to\tensorflow\python\keras\engine\base_layer.py", line 926, in __call__
input_list)
File "path\to\tensorflow\python\keras\engine\base_layer.py", line 1117, in _functional_construction_call
outputs = call_fn(cast_inputs, *args, **kwargs)
File "path\to\tensorflow\python\keras\layers\core.py", line 903, in call
result = self.function(inputs, **kwargs)
File "path\to\tensorflow\python\util\dispatch.py", line 205, in wrapper
result = dispatch(wrapper, args, kwargs)
TypeError: 'module' object is not callable
type(layer) = <class 'tensorflow.python.keras.layers.core.Lambda'>
有人知道如何解决这个问题吗?
附加信息:
Windows10,Python3.7,TensorFlow 2.3.1,Keras 2.4.3
# Train the network
python model_main_tf2.py --model_dir="training" --pipeline_config_path="training/pipeline.config"
# Export the network
python exporter_main_v2.py --input_type=image_tensor --pipeline_config_path="training/pipeline.config" --trained_checkpoint_dir="training" --output_directory="training/model"
文件夹结构:
training/
-> label_map.pbtxt
-> pipeline.config
-> model
. -> checkpoint
. -> saved_model
. . -> assets
. . -> variables
. . -> saved_model.pb
-> checkpoint
-> ckpt.x.data-00000-of-00001
-> ckpt.x.index
我找到了一种无需 Keras 即可转换模型的方法,这对我很有用。
https://github.com/opencv/opencv/issues/16879
import tensorflow as tf
from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2
loaded = tf.saved_model.load('training/model/saved_model')
infer = loaded.signatures['serving_default']
f = tf.function(infer).get_concrete_function(input_tensor=tf.TensorSpec(shape=[1, None, None, 3], dtype=tf.uint8))
f2 = convert_variables_to_constants_v2(f)
graph_def = f2.graph.as_graph_def()
# Export frozen graph
with tf.io.gfile.GFile('frozen_graph.pb', 'wb') as f:
f.write(graph_def.SerializeToString())
原因可能是您模型中的 lambda 层。
在加载带有 lambda 层的模型时,Keras 中存在一些可能会引发 TypeError(str is not callable or module is not callable)
的问题。
要解决此问题,请不要使用 model.save 保存模型。相反,保存模型权重并使用代码重新创建模型架构,然后加载权重。
例子:
model.save_weights('model_weights.h5')
或
ModelCheckPoint(file,save_weights_only=True)#this will call save_weights
创建模型后,然后:
model.load_weights('model_weights.h5')
注:
将模型架构另存为JSON文件无法解决错误
我使用 TensorFlow Object Detection API with TensorFlow 2 and then converted the trained model into a SavedModel. Now I need to convert the SavedModel to a FrozenGraph in order to make the model compatible with external libraries like OpenCV. I use this example 训练了一个 SSD MobileNet v2 网络进行转换,但我什至无法加载 Keras 模型。
from keras.models import load_model
model = load_model("training/model/saved_model")
调用load_model()
产生异常:
Exception has occurred: TypeError
'module' object is not callable
Full traceback:
Traceback (most recent call last):
File "path\to\tensorflow\python\util\dispatch.py", line 201, in wrapper
return target(*args, **kwargs)
TypeError: 'str' object is not callable
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "path\to\saved_model_to_frozen_graph.py", line 17, in <module>
model = load_model("saved_model")
File "path\to\tensorflow\python\keras\saving\save.py", line 187, in load_model
return saved_model_load.load(filepath, compile, options)
File "path\to\tensorflow\python\keras\saving\saved_model\load.py", line 121, in load
path, options=options, loader_cls=KerasObjectLoader)
File "path\to\tensorflow\python\saved_model\load.py", line 633, in load_internal
ckpt_options)
File "path\to\tensorflow\python\keras\saving\saved_model\load.py", line 194, in __init__
super(KerasObjectLoader, self).__init__(*args, **kwargs)
File "path\to\tensorflow\python\saved_model\load.py", line 130, in __init__
self._load_all()
File "path\to\tensorflow\python\keras\saving\saved_model\load.py", line 221, in _load_all
self._finalize_objects()
File "path\to\tensorflow\python\keras\saving\saved_model\load.py", line 530, in _finalize_objects
self._reconstruct_all_models()
File "path\to\tensorflow\python\keras\saving\saved_model\load.py", line 548, in _reconstruct_all_models
self._reconstruct_model(model_id, model, layers)
File "path\to\tensorflow\python\keras\saving\saved_model\load.py", line 589, in _reconstruct_model
config, created_layers={layer.name: layer for layer in layers})
File "path\to\tensorflow\python\keras\engine\functional.py", line 1215, in reconstruct_from_config
process_node(layer, node_data)
File "path\to\tensorflow\python\keras\engine\functional.py", line 1163, in process_node
output_tensors = layer(input_tensors, **kwargs)
File "path\to\tensorflow\python\keras\engine\base_layer.py", line 926, in __call__
input_list)
File "path\to\tensorflow\python\keras\engine\base_layer.py", line 1117, in _functional_construction_call
outputs = call_fn(cast_inputs, *args, **kwargs)
File "path\to\tensorflow\python\keras\layers\core.py", line 903, in call
result = self.function(inputs, **kwargs)
File "path\to\tensorflow\python\util\dispatch.py", line 205, in wrapper
result = dispatch(wrapper, args, kwargs)
TypeError: 'module' object is not callable
type(layer) = <class 'tensorflow.python.keras.layers.core.Lambda'>
有人知道如何解决这个问题吗?
附加信息:
Windows10,Python3.7,TensorFlow 2.3.1,Keras 2.4.3
# Train the network
python model_main_tf2.py --model_dir="training" --pipeline_config_path="training/pipeline.config"
# Export the network
python exporter_main_v2.py --input_type=image_tensor --pipeline_config_path="training/pipeline.config" --trained_checkpoint_dir="training" --output_directory="training/model"
文件夹结构:
training/
-> label_map.pbtxt
-> pipeline.config
-> model
. -> checkpoint
. -> saved_model
. . -> assets
. . -> variables
. . -> saved_model.pb
-> checkpoint
-> ckpt.x.data-00000-of-00001
-> ckpt.x.index
我找到了一种无需 Keras 即可转换模型的方法,这对我很有用。 https://github.com/opencv/opencv/issues/16879
import tensorflow as tf
from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2
loaded = tf.saved_model.load('training/model/saved_model')
infer = loaded.signatures['serving_default']
f = tf.function(infer).get_concrete_function(input_tensor=tf.TensorSpec(shape=[1, None, None, 3], dtype=tf.uint8))
f2 = convert_variables_to_constants_v2(f)
graph_def = f2.graph.as_graph_def()
# Export frozen graph
with tf.io.gfile.GFile('frozen_graph.pb', 'wb') as f:
f.write(graph_def.SerializeToString())
原因可能是您模型中的 lambda 层。
在加载带有 lambda 层的模型时,Keras 中存在一些可能会引发 TypeError(str is not callable or module is not callable)
的问题。
要解决此问题,请不要使用 model.save 保存模型。相反,保存模型权重并使用代码重新创建模型架构,然后加载权重。
例子:
model.save_weights('model_weights.h5')
或
ModelCheckPoint(file,save_weights_only=True)#this will call save_weights
创建模型后,然后:
model.load_weights('model_weights.h5')
注: 将模型架构另存为JSON文件无法解决错误