【问题标题】:tf.keras.models.load_model raise TypeError: 'module' object is not callabletf.keras.models.load_model raise TypeError: 'module' object is not callable
【发布时间】:2021-02-24 11:03:10
【问题描述】:

我正在使用 ssd_mobilenet 开发 object_detection 网络管道。该网络包含 tf Object_Detection API 和 ssd_keras repo(没关系)。
现在的问题是我想保存和加载整个模型,包括 weightsoptimizerloss_infos 所以我想使用model.save .但是当我使用tf.keras.models.load_model('save_path') 时,会引发此错误。
这是我的模型定义:

#! /usr/bin/python3

# this script is define the ssd_mobilenet model
# from object_dection and keras-ssd models

from __future__ import division
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Lambda, Activation, Conv2D, MaxPooling2D, ZeroPadding2D, Reshape, Concatenate
from tensorflow.keras.regularizers import l2
import tensorflow.keras.backend as K
from my_model.feature_extractors import choose_feature_extractor
import numpy as np

from ssd_keras.keras_layers.keras_layer_AnchorBoxes import AnchorBoxes
from ssd_keras.keras_layers.keras_layer_L2Normalization import L2Normalization
from ssd_keras.keras_layers.keras_layer_DecodeDetections import DecodeDetections
from ssd_keras.keras_layers.keras_layer_DecodeDetectionsFast import DecodeDetectionsFast

# to enable the version problem
# don't know why
config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.compat.v1.Session(config=config)
L2_REG = 0.00004

def class_conf(out_dim, name, **kwargs):
    # predict n_classes confidence values for each box
    if not kwargs:
        return Conv2D(out_dim, (3,3), padding='same', 
            kernel_initializer='he_normal', kernel_regularizer=l2(L2_REG), name=name)
    return Conv2D(out_dim, (3,3), padding='same', 
            kernel_initializer='he_normal', kernel_regularizer=l2(L2_REG), name=name)(kwargs['input'])

def box_cord(out_dim, name, **kwargs):
    # predict 4 box coordinates for each box
    if not kwargs:
        return Conv2D(out_dim, (3,3), padding='same', 
            kernel_initializer='he_normal', kernel_regularizer=l2(L2_REG), name=name)
    return Conv2D(out_dim, (3,3), padding='same', 
            kernel_initializer='he_normal', kernel_regularizer=l2(L2_REG), name=name)(kwargs['input'])


def ssd_model(image_size,
                n_classes,
                base_model,
                is_training=True,
                aspect_ratios_global=None,
                two_boxes_for_ar1=True,
                scales=None,
                aspect_ratios_per_layer=None,
                steps=[8,6,32,64,100,300],
                clip_boxes=False,
                variances=[0.1, 0.1, 0.2, 0.2],
                coords='centroids',
                normalize_coords=True,
                offsets=None,
                iou_threshold=0.50,
                confidence_thresh=0.01,
                top_k=200,
                nms_max_output_size=400,
                fine_tuning=False):

    n_predictor_layers = 6
    n_classes += 1
    img_height, img_width, img_channels = image_size[0], image_size[1], image_size[2] 

    # define aspect_ratios and num_boxes
    if aspect_ratios_per_layer:
        aspect_ratios = aspect_ratios_per_layer
    else:
        aspect_ratios = [aspect_ratios_global] * n_predictor_layers

    if aspect_ratios_per_layer:
        n_boxes = []
        for ar in aspect_ratios_per_layer:
            if (1 in ar) & two_boxes_for_ar1:
                n_boxes.append(len(ar) + 1) # +1 for the second box for aspect ratio 1
            else:
                n_boxes.append(len(ar))
    else: # If only a global aspect ratio list was passed, then the number of boxes is the same for each predictor layer
        if (1 in aspect_ratios_global) & two_boxes_for_ar1:
            n_boxes = len(aspect_ratios_global) + 1
        else:
            n_boxes = len(aspect_ratios_global)
        n_boxes = [n_boxes] * n_predictor_layers
    # used to instantiate a keras tensorm, a symbolic tensor object

    X = Input(shape=(img_height, img_width, img_channels))
    # Backbone
    feature_extractor = choose_feature_extractor(base_model=base_model,
                                        is_training=is_training,
                                        fine_tuning=fine_tuning)

    resized_image = feature_extractor.preprocess(X)
    feature_maps = feature_extractor(resized_image)

    conf_1 = class_conf(out_dim=n_boxes[0]*n_classes, name='conf_1', input=feature_maps[0])
    conf_2 = class_conf(out_dim=n_boxes[1]*n_classes, name='conf_2', input=feature_maps[1])
    conf_3 = class_conf(out_dim=n_boxes[2]*n_classes, name='conf_3', input=feature_maps[2])
    conf_4 = class_conf(out_dim=n_boxes[3]*n_classes, name='conf_4', input=feature_maps[3])
    conf_5 = class_conf(out_dim=n_boxes[4]*n_classes, name='conf_5', input=feature_maps[4])
    conf_6 = class_conf(out_dim=n_boxes[5]*n_classes, name='conf_6', input=feature_maps[5])

    loc_1 = box_cord(out_dim=n_boxes[0]*4, name='loc_1', input=feature_maps[0])
    loc_2 = box_cord(out_dim=n_boxes[1]*4, name='loc_2', input=feature_maps[1])
    loc_3 = box_cord(out_dim=n_boxes[2]*4, name='loc_3', input=feature_maps[2])
    loc_4 = box_cord(out_dim=n_boxes[3]*4, name='loc_4', input=feature_maps[3])
    loc_5 = box_cord(out_dim=n_boxes[4]*4, name='loc_5', input=feature_maps[4])
    loc_6 = box_cord(out_dim=n_boxes[5]*4, name='loc_6', input=feature_maps[5])

    box_1 = AnchorBoxes(img_height, img_width, this_scale=scales[0], next_scale=scales[1], aspect_ratios=aspect_ratios[0],
                                             two_boxes_for_ar1=two_boxes_for_ar1, this_steps=steps[0], this_offsets=offsets[0], clip_boxes=clip_boxes,
                                             variances=variances, coords=coords, normalize_coords=normalize_coords, name='box_1')(loc_1)
    box_2 = AnchorBoxes(img_height, img_width, this_scale=scales[1], next_scale=scales[2], aspect_ratios=aspect_ratios[1],
                                    two_boxes_for_ar1=two_boxes_for_ar1, this_steps=steps[1], this_offsets=offsets[1], clip_boxes=clip_boxes,
                                    variances=variances, coords=coords, normalize_coords=normalize_coords, name='box_2')(loc_2)
    box_3 = AnchorBoxes(img_height, img_width, this_scale=scales[2], next_scale=scales[3], aspect_ratios=aspect_ratios[2],
                                        two_boxes_for_ar1=two_boxes_for_ar1, this_steps=steps[2], this_offsets=offsets[2], clip_boxes=clip_boxes,
                                        variances=variances, coords=coords, normalize_coords=normalize_coords, name='box_3')(loc_3)
    box_4 = AnchorBoxes(img_height, img_width, this_scale=scales[3], next_scale=scales[4], aspect_ratios=aspect_ratios[3],
                                        two_boxes_for_ar1=two_boxes_for_ar1, this_steps=steps[3], this_offsets=offsets[3], clip_boxes=clip_boxes,
                                        variances=variances, coords=coords, normalize_coords=normalize_coords, name='box_4')(loc_4)
    box_5 = AnchorBoxes(img_height, img_width, this_scale=scales[4], next_scale=scales[5], aspect_ratios=aspect_ratios[4],
                                        two_boxes_for_ar1=two_boxes_for_ar1, this_steps=steps[4], this_offsets=offsets[4], clip_boxes=clip_boxes,
                                        variances=variances, coords=coords, normalize_coords=normalize_coords, name='box_5')(loc_5)
    box_6 = AnchorBoxes(img_height, img_width, this_scale=scales[5], next_scale=scales[6], aspect_ratios=aspect_ratios[5],
                                        two_boxes_for_ar1=two_boxes_for_ar1, this_steps=steps[5], this_offsets=offsets[5], clip_boxes=clip_boxes,
                                        variances=variances, coords=coords, normalize_coords=normalize_coords, name='box_6')(loc_6)

    # reshape
    confs = [conf_1, conf_2, conf_3, conf_4, conf_5, conf_6]
    locs = [loc_1, loc_2, loc_3, loc_4, loc_5, loc_6]
    boxes = [box_1, box_2, box_3, box_4, box_5, box_6]
    for i, value in enumerate(confs):
        confs[i] = Reshape((-1, n_classes), name='conf_reshape_'+str(i))(value)
    for i, value in enumerate(locs):
        locs[i] = Reshape((-1, 4), name='loc_reshape_'+str(i))(value)
    for i,value in enumerate(boxes):
        boxes[i] = Reshape((-1, 8), name='box_reshape_'+str(i))(value)
    
    mbox_conf = Concatenate(axis=1, name='mbox_conf')(confs)
    mbox_loc = Concatenate(axis=1, name='mbox_loc')(locs)
    mbox_priorbox = Concatenate(axis=1, name='mbox_priorbox')(boxes)

    mbox_conf_softmax = Activation('softmax', name='mbox_conf_softmax')(mbox_conf)
    predictions = Concatenate(axis=2, name='predictions')([mbox_conf_softmax, mbox_loc, mbox_priorbox])

    if is_training:
        model = Model(inputs=X, outputs=predictions)

    return model

并且 feature_extractor 是 ssd_mobilenet_v2_keras_feature_extractor.py 中定义的 object_detection API 中的一个子类模型
我注意到要启用model.save(),我需要覆盖模型子类中的 get_config() 函数。但是我不知道要添加什么,所以我只是在 self.parameters 中添加参数遵循一些教程,像这样:

## in ssd_meta_arch.SSDKerasFeatureExtractor
def get_config(self):
        return {'is_training': self._is_training,
                'depth_multiplier': self._depth_multiplier,
                'min_depth': self._min_depth,
                'pad_to_multiple': self._pad_to_multiple,
                # 'conv_hyperparams': self._conv_hyperparams,  # raise TypeError: 'Not JSON Serializable:' 
                'freeze_batchnorm': self._freeze_batchnorm,
                'inplace_batchnorm_update': self._inplace_batchnorm_update,
                'use_explicit_padding': self._use_explicit_padding,
                'use_depthwise': self._use_depthwise,
                'num_layers': self._num_layers,
                'override_base_feature_extractor_hyperparams': self._override_base_feature_extractor_hyperparams}
## in SSDMobileNetV2KerasFeatureExtractor
def get_config(self):
        config = super(SSDMobileNetV2KerasFeatureExtractor, self).get_config()
        config.update({'fine_tuning':self.fine_tuning,
                      #  'classification_backbone':self.classification_backbone,
                      #  'feature_map_generator':self.feature_map_generator
                      })
        
        return config

我可以通过ModelCheckpoint(save_weights_only=False,...) 保存模型,但是在加载时我遇到了这个错误:

Traceback (most recent call last):
  File "train.py", line 37, in <module>
    model = tf.keras.models.load_model(args.load_checkpoint)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/saving/save.py", line 207, in load_model
    return saved_model_load.load(filepath, compile, options)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/saving/saved_model/load.py", line 158, in load
    keras_loader.finalize_objects()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/saving/saved_model/load.py", line 623, in finalize_objects
    self._reconstruct_all_models()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/saving/saved_model/load.py", line 642, in _reconstruct_all_models
    self._reconstruct_model(model_id, model, layers)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/saving/saved_model/load.py", line 689, in _reconstruct_model
    config, created_layers={layer.name: layer for layer in layers})
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/functional.py", line 1295, in reconstruct_from_config
    process_node(layer, node_data)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/functional.py", line 1243, in process_node
    output_tensors = layer(input_tensors, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/base_layer.py", line 965, in __call__
    input_list)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/base_layer.py", line 1104, in _functional_construction_call
    inputs, input_masks, args, kwargs)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/base_layer.py", line 834, in _keras_tensor_symbolic_call
    return self._infer_output_signature(inputs, args, kwargs, input_masks)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/base_layer.py", line 875, in _infer_output_signature
    outputs = call_fn(inputs, *args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/layers/core.py", line 916, in call
    result = self.function(inputs, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/dispatch.py", line 210, in wrapper
    result = dispatch(wrapper, args, kwargs)
TypeError: 'module' object is not callable

有点复杂(笑),感谢您的帮助。

【问题讨论】:

标签: tensorflow keras object-detection-api


【解决方案1】:

问题是您将其保存为一种格式并尝试将其读取为另一种格式。

ModelCheckpoint 回调以检查点格式保存 tf 模型,而 tf.keras.models.load_model('model') 以 savedModel 格式读取。

如果您想坚持检查点格式,请使用 model.load_weights(checkpoint_path) 加载权重,或者如果您想切换到保存的模型格式,请在保存模型时使用 model.save('saved_model/my_model') 并它应该可以正常工作。

仅需要覆盖 get_config() 才能以 hdf5 格式保存。请参考https://www.tensorflow.org/tutorials/keras/save_and_load中的“保存自定义对象”

【讨论】:

  • 抱歉,问题依旧。我使用了model.save,但情况没有改变。另外,我检查了ModelCheckpoint,当设置save_weights_only为False时,它会调用model.save()函数。
  • 你能添加一个简单的模型来重现错误吗?
猜你喜欢
  • 2018-03-31
  • 2019-04-07
  • 2022-12-26
  • 2020-12-31
  • 1970-01-01
  • 2021-07-29
  • 1970-01-01
  • 2020-03-27
  • 2019-03-13
相关资源
最近更新 更多