Keras 在保存模型时给出 'Not JSON Serializable' 错误

Keras gives 'Not JSON Serializable' error when saving the model

我正在使用此处定义的 unet 实现用于图像分割的完全卷积神经网络

https://github.com/zhixuhao

为了给不同 类 的像素赋予不同的权重,我定义了一个额外的 Lambda 层,如这里所建议的那样

Keras, binary segmentation, add weight to loss function

问题是 Keras 在保存模型时引发了这个错误

.....
self.model.save(filepath, overwrite=True)
.....
TypeError: ('Not JSON Serializable:', b'\n\x15clip_by_value/Minimum\x12\x07Minimum\x1a\x12conv2d_23/Identity\x1a\x17clip_by_value/Minimum/y*\x07\n\x01T\x12\x020\x01')

我的网络是在外部函数中定义的

def weighted_binary_loss(X):
    y_pred, y_true, weights = X
    loss = binary_crossentropy(y_true, y_pred)
    weights_mask = y_true*weights[0] + (1.-y_true)*weights[1]
    loss = multiply([loss, weights_mask])
    return loss    

def identity_loss(y_true, y_pred):
    return y_pred


def net()
.....
....
conv10 = Conv2D(1, 1, activation = 'sigmoid')(conv9)
w_loss = Lambda(weighted_binary_loss, output_shape=input_size, name='loss_output')([conv10, inputs, weights])
model = Model(inputs = inputs, outputs = w_loss)
model.compile(optimizer = Adam(lr = 1e-5), loss = identity_loss, metrics = ['accuracy'])

我在主函数中调用的

...
model_checkpoint = ModelCheckpoint('temp_model.hdf5', monitor='loss',verbose=1, save_best_only=True)
model.fit_generator(imgs,steps_per_epoch=20,epochs=1,callbacks=[model_checkpoint])

当我擦除 Lambda 层时,错误消失了

...
conv10 = Conv2D(1, 1, activation = 'sigmoid')(conv9)
model = Model(inputs = inputs, outputs = conv10)
model.compile(optimizer = Adam(lr = 1e-5), loss = 'binary_crossentropy', metrics = ['accuracy'])

我正在使用 Keras==2.2.4, tensorflow-gpu==2.0.0b1

您似乎是在计算模型层中的损失。将损失函数作为一个层来容纳并不是一个好习惯。您可以使用自定义损失函数计算加权损失。

所以你的代码可以重写如下:

def weighted_binary_loss(y_true, y_pred):
    weights = [0.5, 0.6]  # Define your weights here
    loss = binary_crossentropy(y_true, y_pred)
    weights_mask = y_true*weights[0] + (1.-y_true)*weights[1]
    loss = multiply([loss, weights_mask])
    return loss  

conv10 = Conv2D(1, 1, activation = 'sigmoid')(conv9)
model = Model(inputs = inputs, outputs = conv10)
model.compile(optimizer = Adam(lr = 1e-5), loss = weighted_binary_loss, metrics = ['accuracy'])

如果需要weights是一个动态的属性并且你必须在损失函数中将它作为一个单独的参数发送,你可以按照这个.