【问题标题】:tf.keras.callbacks.ModelCheckpoint Type Error : Unable to serialize 1.0000000656873453e-05 to JSONtf.keras.callbacks.ModelCheckpoint 类型错误:无法将 1.0000000656873453e-05 序列化为 JSON
【发布时间】:2021-11-08 10:49:12
【问题描述】:

我正在使用移动网络预训练层创建我的自定义层 tf.keras 模型。模型训练运行良好,但在保存最佳选择模型时出现错误。下面是我使用的代码的sn-p

pretrained_model = tf.keras.applications.MobileNetV2(
                                                    weights='imagenet',
                                                    include_top=False,
                                                    input_shape=[*IMAGE_SIZE, IMG_CHANNELS])
pretrained_model.trainable = True #fine tuning
model = tf.keras.Sequential([
                            tf.keras.layers.Lambda(# Convert image from int[0, 255] to the format expect by this model
                            lambda data:tf.keras.applications.mobilenet.preprocess_input(
                                tf.cast(data, tf.float32)), input_shape=[*IMAGE_SIZE, 3]),
                            pretrained_model,
                            tf.keras.layers.GlobalAveragePooling2D()])

model.add(tf.keras.layers.Dense(64, name='object_dense',kernel_regularizer=tf.keras.regularizers.l2(l2=0.001)))
model.add(tf.keras.layers.BatchNormalization(scale=False, center = False))
model.add(tf.keras.layers.Activation('relu', name='relu_dense_64'))
model.add(tf.keras.layers.Dropout(rate=0.2, name='dropout_dense_64'))
model.add(tf.keras.layers.Dense(32, name='object_dense_2',kernel_regularizer=tf.keras.regularizers.l2(l2=0.01)))
model.add(tf.keras.layers.BatchNormalization(scale=False, center = False))
model.add(tf.keras.layers.Activation('relu', name='relu_dense_32'))
model.add(tf.keras.layers.Dropout(rate=0.2, name='dropout_dense_32'))
model.add(tf.keras.layers.Dense(16, name='object_dense_16', kernel_regularizer=tf.keras.regularizers.l2(l2=0.01)))
model.add(tf.keras.layers.Dense(len(CLASS_NAMES), activation='softmax', name='object_prob'))
m1 = tf.keras.metrics.CategoricalAccuracy()
m2 = tf.keras.metrics.Recall()
m3 = tf.keras.metrics.Precision()



optimizers = [
    tfa.optimizers.AdamW(learning_rate=lr * .001 , weight_decay=wd),
    tfa.optimizers.AdamW(learning_rate=lr, weight_decay=wd)
           ]

optimizers_and_layers = [(optimizers[0], model.layers[0]), (optimizers[1], model.layers[1:])]

optimizer = tfa.optimizers.MultiOptimizer(optimizers_and_layers)

model.compile(
    optimizer= optimizer,
    loss = 'categorical_crossentropy',
    metrics=[m1, m2, m3],
    )

checkpoint_path = os.getcwd() + os.sep + 'keras_model'
checkpoint_cb = tf.keras.callbacks.ModelCheckpoint(filepath=os.path.join(checkpoint_path), 
                                                    monitor = 'categorical_accuracy',
                                                    save_best_only=True,
                                                    save_weights_only=True)

history = model.fit(train_data, validation_data=test_data, epochs=N_EPOCHS, callbacks=[checkpoint_cb])

在 tf.keras.callbacks.ModelCheckpoint 给我一个错误

TypeError:无法将 1.0000000656873453e-05 序列化为 JSON。无法识别的类型 .

以下是 Google Colab 笔记本的链接,以防您想复制问题

https://colab.research.google.com/drive/1wQbUFfhtDaB5Xta574UkAXJtthui7Bt9?usp=sharing

【问题讨论】:

    标签: keras tensorflow2.0 tf.keras checkpoint


    【解决方案1】:

    这似乎是 Tensorflow 或 Keras 中的一个错误。被序列化为 JSON 的张量来自您的优化器定义。

    model.optimizer.optimizer_specs[0]["optimizer"].get_config()["weight_decay"]
    
    <tf.Tensor: shape=(), dtype=float32, numpy=1.0000001e-05>
    

    tfa.optimizers.AdamWimplementation 开始,weight_decay 使用tf.keras.optimizers.Adam._serialize_hyperparameter 进行序列化。这个函数假设如果你传入一个超参数的可调用对象,它会在调用时返回一个非张量值,但在你的笔记本中,它被实现为

    wd = lambda: 1e-02 * schedule(step)
    

    schedule() 返回一个张量。我尝试了一些不同的方法来尝试将张量转换为标量值,但我无法让它们工作。作为一种解决方法,我将wd 实现为LearningRateSchedule,因此它可以正确序列化,尽管代码比较笨重。用此代码替换 wdlr 的定义可以让我顺利完成模型训练。

    class MyExponentialDecay(tf.keras.optimizers.schedules.ExponentialDecay):
      def __call__(self, step):
        return 1e-2 * super().__call__(step)
    
    wd = MyExponentialDecay(
        initial_learning_rate,
        decay_steps=14,
        decay_rate=0.8,
        staircase=True)
    lr = 1e2 * schedule(step)
    

    训练完成后,model.save() 调用将失败。我相信这与 Tensorflow Addons Github 中的 here 报告的问题相同。这个问题的总结是优化器的get_config() 函数将在配置中包含一个"gv" 键,该键存储Tensor 对象,这些对象不是JSON 可序列化的。

    在撰写本文时,此问题尚未解决。如果您不需要最终保存模型的优化器状态,​​您可以将 include_optimizer=False 参数传递给对我有用的 model.save()。否则,您可能需要修补库或特定的优化器类实现,以摆脱配置中的 "gw" 键,就像 OP 在该线程中所做的那样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-16
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      相关资源
      最近更新 更多