首页 > 解决方案 > 如何序列化keras模型的类对象

问题描述

我试图保存 keras 完整模型,但遇到了这个错误

Traceback (most recent call last):
  File "d:/Workspace/College/Semester 8/Tugas Akhir/Keras-RFCN-master/Keras-RFCN-master/testing.py", line 133, in <module>
    main()
  File "d:/Workspace/College/Semester 8/Tugas Akhir/Keras-RFCN-master/Keras-RFCN-master/testing.py", line 96, in main
    model.save("D:/weight.h5")
  File "d:\Workspace\College\Semester 8\Tugas Akhir\Keras-RFCN-master\Keras-RFCN-master\KerasRFCN\Model\Model.py", line 560, in save
    self.model.save(save_path)
  File "C:\Users\kevin\anaconda3\envs\tf-gpu\lib\site-packages\keras\engine\network.py", line 1139, in save
    save_model(self, filepath, overwrite, include_optimizer)
  File "C:\Users\kevin\anaconda3\envs\tf-gpu\lib\site-packages\keras\engine\saving.py", line 415, in save_wrapper
    save_function(obj, filepath, overwrite, *args, **kwargs)
  File "C:\Users\kevin\anaconda3\envs\tf-gpu\lib\site-packages\keras\engine\saving.py", line 507, in save_model
    _serialize_model(model, h5dict, include_optimizer)
  File "C:\Users\kevin\anaconda3\envs\tf-gpu\lib\site-packages\keras\engine\saving.py", line 101, in _serialize_model
    model_config = json.dumps(model_config, default=get_json_type)
  File "C:\Users\kevin\anaconda3\envs\tf-gpu\lib\json\__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "C:\Users\kevin\anaconda3\envs\tf-gpu\lib\json\encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "C:\Users\kevin\anaconda3\envs\tf-gpu\lib\json\encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "C:\Users\kevin\anaconda3\envs\tf-gpu\lib\site-packages\keras\engine\saving.py", line 91, in get_json_type
    raise TypeError('Not JSON Serializable: %s' % (obj,))
TypeError: Not JSON Serializable: <KerasRFCN.Config.Config object at 0x0000029B0A3BD248>

通过该错误,很明显 JSON 无法序列化我的类,该类返回一个名为 config 的对象。那么如何确保 Keras 可以序列化我的配置..??

我认为在init中定义的所有定义都可以序列化。

我真的是 python、Keras 和 TensorFlow 的新手。

我正在使用 tensorflow-GPU 1.15.2、Keras 2.2.5 和 python 3.7,这是我在 def init中定义所有变量之前的配置代码:

class Config(object):
    NAME = "BDD"  # Override in sub-classes

    # Backbone model
    BACKBONE = "resnet50"

    # NUMBER OF GPUs to use. For CPU training, use 1
    GPU_COUNT = 1

    # Number of images to train with on each GPU.
    IMAGES_PER_GPU = 2

    # Number of training steps per epoch
    STEPS_PER_EPOCH = 1000

    # Number of validation steps to run at the end of every training epoch.
    VALIDATION_STEPS = 50

    # The strides of each layer of the FPN Pyramid.
    # Like BACKBONE_STRIDES = [4, 8, 16, 16, 16]
    BACKBONE_STRIDES = [4, 8, 16, 32, 64]

    # Number of classification classes (including background)
    NUM_CLASSES = 1  # Override in sub-classes

    # Length of square anchor side in pixels
    RPN_ANCHOR_SCALES = (32, 64, 128, 256, 512)

    # Ratios of anchors at each cell (width/height)
    # A value of 1 represents a square anchor, and 0.5 is a wide anchor
    RPN_ANCHOR_RATIOS = [0.5, 1, 2]

    # Anchor stride
    # If 1 then anchors are created for each cell in the backbone feature map.
    # If 2, then anchors are created for every other cell, and so on.
    RPN_ANCHOR_STRIDE = 1

    # Non-max suppression threshold to filter RPN proposals.
    # You can reduce this during training to generate more propsals.
    RPN_NMS_THRESHOLD = 0.7

    # How many anchors per image to use for RPN training
    RPN_TRAIN_ANCHORS_PER_IMAGE = 256

    # ROIs kept after non-maximum supression (training and inference)
    POST_NMS_ROIS_TRAINING = 2000
    POST_NMS_ROIS_INFERENCE = 1000

    # Input image resing
    # Images are resized such that the smallest side is >= IMAGE_MIN_DIM and
    # the longest side is <= IMAGE_MAX_DIM. In case both conditions can't
    # be satisfied together the IMAGE_MAX_DIM is enforced.
    IMAGE_MIN_DIM = 800
    IMAGE_MAX_DIM = 1024
    # If True, pad images with zeros such that they're (max_dim by max_dim)
    IMAGE_PADDING = True  # currently, the False option is not supported

    # Image mean (RGB)
    MEAN_PIXEL = np.array([123.7, 116.8, 103.9])

    # Number of ROIs per image to feed to classifier
    TRAIN_ROIS_PER_IMAGE = 200

    # Percent of positive ROIs used to train classifier/mask heads
    ROI_POSITIVE_RATIO = 0.33

    # Pooled ROIs
    POOL_SIZE = 3

    # Maximum number of ground truth instances to use in one image
    MAX_GT_INSTANCES = 100

    # Bounding box refinement standard deviation for RPN and final detections.
    RPN_BBOX_STD_DEV = np.array([0.1, 0.1, 0.2, 0.2])
    BBOX_STD_DEV = np.array([0.1, 0.1, 0.2, 0.2])

    # Max number of final detections
    DETECTION_MAX_INSTANCES = 100

    # Minimum probability value to accept a detected instance
    # ROIs below this threshold are skipped
    DETECTION_MIN_CONFIDENCE = 0.8

    # Non-maximum suppression threshold for detection
    DETECTION_NMS_THRESHOLD = 0.3

    # Learning rate and momentum
    LEARNING_RATE = 0.001
    LEARNING_MOMENTUM = 0.9

    # Weight decay regularization
    WEIGHT_DECAY = 0.0005

    USE_RPN_ROIS = True

    K = 3

    def __init__(self):
        """Set values of computed attributes."""
        # Effective batch size
        self.BATCH_SIZE = self.IMAGES_PER_GPU * self.GPU_COUNT

        # Input image size
        self.IMAGE_SHAPE = np.array(
            [self.IMAGE_MAX_DIM, self.IMAGE_MAX_DIM, 3])

        # Compute backbone size from input image size
        self.BACKBONE_SHAPES = np.array(
            [[int(math.ceil(self.IMAGE_SHAPE[0] / stride)),
              int(math.ceil(self.IMAGE_SHAPE[1] / stride))]
             for stride in self.BACKBONE_STRIDES])

    def display(self):
        """Display Configuration values."""
        print("\nConfigurations:")
        for a in dir(self):
            if not a.startswith("__") and not callable(getattr(self, a)):
                print("{:30} {}".format(a, getattr(self, a)))
        print("\n")

标签: pythontensorflowkeras

解决方案


如果您使用的是子类模型,那么在定义模型之后,您需要在一些数据上调用模型,例如model.predict(x)这将创建权重并使模型能够使用model.save或'model.save_weights andload_weights`保存

首先,一个从未使用过的子类模型是无法保存的。

这是因为需要在某些数据上调用子类模型才能创建其权重。

在调用模型之前,它不知道它应该期望的输入数据的形状和 dtype,因此无法创建其权重变量。

有关该方法的更多详细信息,请参见此处的示例


推荐阅读