【问题标题】:Unable to save weights while using pre-trained VGG16 model使用预训练的 VGG16 模型时无法保存权重
【发布时间】:2018-03-08 08:57:48
【问题描述】:

使用预训练的 VGG16 模型时,我无法保存最佳模型的权重。我使用此代码:

checkpointer = [
                # Stop if the accuracy is not improving after 7 iterations
                EarlyStopping(monitor='val_loss', patience=3, verbose=1),
                # Saving the best model and re-use it while prediction 
                ModelCheckpoint(filepath="C:/Users/skumarravindran/Documents/keras_save_model/vgg16_v1.hdf5", verbose=1, monitor='val_acc', save_best_only=True),
                #            
]

我收到以下错误:

C:\Users\skumarravindran\AppData\Local\Continuum\Anaconda2\envs\py35gpu1\lib\site-packages\keras\callbacks.py:405: RuntimeWarning: Can save best model only with val_acc available, skipping. “跳过。” % (self.monitor), RuntimeWarning)

【问题讨论】:

  • 你的model.compile() 行中有metrics=['acc'] 吗?

标签: deep-learning keras


【解决方案1】:

我遇到了两种出现此错误的情况:

  1. 引入自定义指标
  2. 使用多个输出

在这两种情况下,accval_acc 都不会被计算。奇怪的是,Keras 确实计算了一个整体 lossval_loss

您可以通过在指标中添加accuracy 来补救第一种情况,但这可能会产生副作用,我不确定。但是,在这两种情况下,您都可以在回调中自己添加 accval_acc。我为多输出案例添加了一个示例,其中我创建了一个自定义回调,在该回调中我通过对输出层的所有 val 和 val_acc 进行平均来计算我自己的 accval_acc 结果。

我有一个模型,最后有 5 个密集输出层,标记为 D0..D4。一个epoch的输出如下:

3540/3540 [==============================] - 21s 6ms/step - loss: 14.1437 - 
D0_loss: 3.0446 - D1_loss: 2.6544 - D2_loss: 3.0808 - D3_loss: 2.7751 -
D4_loss: 2.5889 - D0_acc: 0.2362 - D1_acc: 0.3681 - D2_acc: 0.1542 - D3_acc: 0.1161 - 
D4_acc: 0.3994 - val_loss: 8.7598 - val_D0_loss: 2.0797 - val_D1_loss: 1.4088 - 
val_D2_loss: 2.0711 - val_D3_loss: 1.9064 - val_D4_loss: 1.2938 - 
val_D0_acc: 0.2661 - val_D1_acc: 0.3924 - val_D2_acc: 0.1763 - 
val_D3_acc: 0.1695 - val_D4_acc: 0.4627

如您所见,它输出一个整体的lossval_loss,并且对于每个输出层:Di_loss、Di_acc、val_Di_loss 和 val_Di_acc,对于 i in 0..4。所有这些都是logs 字典的内容,它作为回调的on_epoch_beginon_epoch_end 中的参数传输。回调有更多的事件处理程序,但出于我们的目的,这两个是最相关的。当您有 5 个输出(如我的情况)时,字典的大小是 5 乘以 4(acc, loss, val_acc, val_loss) + 2 (loss+val_loss)。

我所做的是计算所有准确度和验证准确度的平均值,以将两项添加到logs

logs['acc'] = som_acc / n_accs
logs['val_acc'] = som_val_acc / n_accs

请务必在检查点回调之前添加此回调,否则您提供的额外信息将不会被“看到”。如果一切都正确实现,则错误消息将不再出现,并且模型正在愉快地检查点。 下面提供了我的多输出案例回调代码。

    class ExtraLogInfo(keras.callbacks.Callback):
        def on_epoch_begin(self, epoch, logs):
            self.timed = time.time()

            return

        def on_epoch_end(self, epoch, logs):
            print(logs.keys())
            som_acc = 0.0
            som_val_acc = 0.0
            n_accs = (len(logs) - 2) // 4
            for i in range(n_accs):
                acc_ptn = 'D{:d}_acc'.format(i)
                val_acc_ptn = 'val_D{:d}_acc'.format(i)
                som_acc += logs[acc_ptn]
                som_val_acc += logs[val_acc_ptn]

            logs['acc'] = som_acc / n_accs
            logs['val_acc'] = som_val_acc / n_accs
            logs['time'] = time.time() - self.timed

            return

【讨论】:

    【解决方案2】:

    通过使用以下代码,您将能够根据准确性保存最佳模型。

    请使用以下代码:

    model.compile(loss='categorical_crossentropy', optimizer= 'adam',
              metrics=['accuracy'])
    
    history = model.fit_generator(
        train_datagen.flow(x_train, y_train, batch_size=batch_size),
        steps_per_epoch=x_train.shape[0] // batch_size,
        epochs=epochs,
        callbacks=[ModelCheckpoint('VGG16-transferlearning.model', monitor='val_acc', save_best_only=True)]
    )
    

    【讨论】:

    • 在使用自定义指标或多输出模型时不适用。
    猜你喜欢
    • 2020-08-25
    • 1970-01-01
    • 2018-03-05
    • 2023-03-19
    • 2020-01-12
    • 1970-01-01
    • 1970-01-01
    • 2021-07-09
    • 1970-01-01
    相关资源
    最近更新 更多