第一卷 第十八章 Checkpointing模型下载地址
链接:https://pan.baidu.com/s/1hqtBQf6jRJINx4AgB8S2Tw
提取码:zxkt
在第13章中,我们讨论了如何在训练完成后将模型保存和序列化到磁盘。在上一章中,我们学习了如何在发生时发现欠拟合和过拟合,从而使您能够终止表现不佳的实验,同时保持模型在训练时表现出的希望。
但是,您可能想知道是否可以将这两种策略结合起来。每当我们的损失/准确性提高时,我们可以序列化模型吗?或者是否可以仅序列化训练过程中的最佳模型(即损失最低或准确率最高的模型)?你打赌。幸运的是,我们也不必构建自定义回调——此功能已直接集成到Keras中。
1、 检查点神经网络模型改进检查点的一个很好的应用是在训练期间每次有改进时将您的网络序列化到磁盘。我们将“改进”定义为损失的减少或准确性的提高——我们将在实际的Keras回调中设置此参数。
在这个例子中,我们将在CIFAR-10数据集上训练MiniVGGNet架构,然后每次模型性能提高时将我们的网络权重序列化到磁盘。首先,打开一个新文件,将其命名为cifar10_checkpoint_improvements.py,并插入以下代码:
第2-8行导入我们所需的Python包。请注意第4行导入的ModelCheckpoint类——这个类将使我们能够在发现模型性能的增量改进时检查点并将我们的网络序列化到磁盘。
接下来,让我们解析我们的命令行参数:
我们需要的唯一命令行参数是--weights,输出目录的路径,该目录将在训练过程中存储我们的序列化模型。然后我们执行从磁盘加载CIFAR-10数据集的标准例程,将像素强度缩放到范围[0;1],然后对标签进行单热编码:
鉴于我们的数据,我们现在准备初始化我们的SGD优化器和MiniVGGNet架构:
我们将使用初始学习率为α=0.01的SGD优化器,然后在40个epoch的过程中缓慢衰减它。我们还将应用γ=0.9的动量,并指出也应使用Nesterov加速度。
MiniVGGNet架构被实例化为接受宽度为32像素、高度为32像素、深度为3(通道数)的输入图像。我们设置classes=10,因为CIFAR-10数据集有十个可能的类别标签。
检查点我们网络的关键步骤可以在下面的代码块中找到:
在第37和38行,我们构造了一个特殊的文件名(fname)模板字符串,Keras在将模型写入磁盘时使用该字符串。模板中的第一个变量{epoch:03d}是我们的纪元号,写成三位数。
第二个变量是我们想要监控以改进的指标,{val_loss:.4f},即当前时期验证集的损失本身。当然,如果我们想监控验证准确性,我们可以用val_acc替换val_loss。如果我们想要监控训练损失和准确性,变量将分别变为train_loss和train_acc(尽管我建议监控您的验证指标,因为它们会让您更好地了解模型将如何泛化)。
一旦定义了输出文件名模板,我们就在第39和40行实例化ModelCheckpoint类。ModelCheckpoint的第一个参数是表示我们的文件名模板的字符串。然后我们传入我们想要监控的内容。在这种情况下,我们希望监控验证损失(val_loss)。
mode参数控制ModelCheckpoint应该寻找最小化我们的指标还是最大化它的值。由于我们正在处理损失,因此越低越好,因此我们设置了mode="min"。如果我们改为使用val_acc,我们将设置mode="max"(因为精度越高越好)。
设置save_best_only=True确保最新的最佳模型(根据监控的指标)不会被覆盖。最后,verbose=1设置只是在训练期间将模型序列化到磁盘时将通知记录到我们的终端。
然后第41行构造了一个回调列表——我们唯一需要的回调是我们的检查点。
最后一步是简单地训练网络并让我们的检查点处理其余的事情:
要执行我们的脚本,只需打开一个终端并执行以下命令:
图18.1:每次模型性能提高时检查单个模型,导致训练完成后产生多个权重文件。
从我的终端输出和图18.1中可以看出,每次验证损失减少时,我们都会将一个新的序列化模型保存到磁盘。
在训练过程结束时,我们有18个单独的文件,每个增量改进一个:
如您所见,每个文件名都有三个组成部分。第一个是静态字符串,权重。然后我们就有了轮次。文件名的最后一个组成部分是我们衡量改进的指标,在这种情况下是验证损失。
我们最好的验证损失是在epoch33上获得的,值为0.5546。然后我们可以获取这个模型并从磁盘加载它(第13章)并进一步评估它或将它应用到我们自己的自定义图像(我们将在下一章中介绍)。
请记住,您的结果将与我的不匹配,因为网络是随机的并使用随机变量进行初始化。根据初始值,您可能有截然不同的模型检查点,但在训练过程结束时,我们的网络应该获得相似的准确度(正负几个百分点)。
2、 检查最佳神经网络
也许检查点增量改进的最大缺点是我们最终会得到一堆我们(不太可能)感兴趣的额外文件,如果我们的验证损失在训练时期上下移动,则尤其如此——这些增量改进中的每一个都会被捕获并序列化到磁盘。在这种情况下,最好只保存一个模型,并在我们的指标在训练期间每次改进时简单地覆盖它。
幸运的是,完成这个动作就像更新ModelCheckpoint类以接受一个简单的字符串(即没有任何模板变量的文件路径)一样简单。然后,每当我们的指标改进时,该文件就会被简单地覆盖。为了理解这个过程,让我们创建一个名为cifar10_checkpoint_best.py的第二个Python文件并查看差异。
首先,我们需要导入所需的Python包:
然后解析我们的命令行参数:
命令行参数本身的名称是相同的(--weights),但开关的描述现在不同:“最佳模型权重文件的路径”。因此,这个命令行参数将是一个简单的字符串到输出路径——这个字符串不会有任何诱惑。
从那里我们可以加载我们的CIFAR-10数据集并准备训练:
以及初始化我们的SGD优化器和MiniVGGNet架构:
我们现在准备更新ModelCheckpoint代码:
注意fname模板字符串是如何消失的——我们所做的只是将--weights的值提供给ModelCheckpoint。由于没有要填写的模板值,每当我们的监控指标有所改善(在这种情况下,验证损失)时,Keras将简单地覆盖现有的序列化权重文件。
最后,我们在下面的代码块中进行网络训练:
要执行我们的脚本,请发出以下命令:
在这里你可以看到,只有当我们的验证损失减少时,我们才会用更新的网络覆盖我们的cifar10_best_weights.hdf5文件。这有两个主要好处:
1.训练过程结束时只有一个序列化文件——获得最低损失的模型epoch。
2.我们没有捕捉损失上下波动的“增量改进”。相反,如果我们的指标获得的损失低于所有以前的时期,我们只会保存并覆盖现有的最佳模型。
要确认这一点,请查看我的weights/best目录,在那里您可以看到只有一个输出文件:
然后,您可以使用这个序列化的MiniVGGNet并在测试数据上进一步评估它或将其应用于您自己的图像(在第15章中介绍)。
3、小结在本章中,我们回顾了如何在训练期间监控给定的指标(例如,验证损失、验证准确率等),然后将高性能网络保存到磁盘。在Keras中有两种方法可以实现这一点:
1.检查点增量改进。
2.只检查过程中找到的最佳模型。
就我个人而言,我更喜欢后者而不是前者,因为它会产生更少的文件和一个代表训练过程中找到的最佳时期的单一输出文件。



