keras版本以及tensorflow-gpu 版本:
Name: Keras
Version: 2.1.3
Name: tensorflow-gpu
Version: 1.10.0
问题重现
假设model是一个已经训练好的模型,现在要用keras中自带的save_weights保存模型的权重。一般我们都直接保存为‘xxx.h5’(save_weights只会保存权重)。我尝试用下面一行代码将其保存下来
model.save_weights('cifar10.hdf5')
然后就报错如下
ValueError: Parent directory of cifar10.hdf5 doesn't exist, can't save
但是如果更改命名的后缀为‘h5’,就可以顺利保存
model.save_weights('cifar10.h5')
出现在文件夹保存成功,开始想这是为什么,寻找相关的资料大多数都说hdf5文件和h5文件是同一个东西。
解决方案
因为这里我用到了keras的回调函数(callbacks)来保存最佳的模型,检查报错原因,可能是因为没有有效的父目录。于是使用如下代码:(使用绝对路径,使用'/python/kerastest/cifar10/'效果一样)
modelname = 'cifar10'
folderpath = 'd:/python/kerastest/cifar10/' # 使用绝对路径,使用'/python/kerastest/cifar10/'效果一样
filepath = folderpath+modelname + ".h5"
model.save_weights(filepath)
这次可以保存成功了,文件夹同时出现以下两个文件了:
这也解释了为什么需要一个父目录了,因为同时有两个文件啊!
到这里可能有人要问了,"啊,博主,为什么自己见过.hdf5 后缀的文件啊??“要hdf5后缀的文件也可以。之前提到这是一个训练过程中有使用回调函数训练出来的模型。只要使用回调函数,将你的filepath传入然后在训练中使用回调函数就可以得到后缀为’hdf5‘的文件了
folderpath = 'd:/python/kerastest/cifar10/'
filepath = folderpath+modelname + ".hdf5"
checkpoint = ModelCheckpoint(filepath,
monitor='val_acc', #确保你的版本中是val_acc,有些版本是val_accuracy
verbose=1,
save_best_only=True,
mode='max')
csv_logger = CSVLogger(folderpath+modelname +'.csv')
callbacks_list = [checkpoint,csv_logger,LRScheduler]
datagen = ImageDataGenerator(width_shift_range=0.1,
height_shift_range=0.1,
rotation_range=20,
horizontal_flip=True,
vertical_flip= False)
model.fit_generator(datagen.flow(trDat,trLbl,batch_size=128),
validation_data = (tsDat,tsLbl),
epochs = 100,
verbose = 1,
steps_per_epoch = len(trDat)/128,# 因为在fitgenerator中他不知道什么时候完成一个epoch,所以用所有数据量除以batchsize来告诉函数目前进行了多少个epoch
callbacks=callbacks_list)
在这个版本的keras 和 tensorflow 中,我尝试将上面代码块的第二行后缀改为’.h5‘ 然后将第一行删去,不会对程序结果造成除了名字以外的其他影响。此时模型默认保存在.py文件的目录下。所以我以后应该只会用’.h5‘后缀了,很方便。
虽然二者后缀不一样,有的还会存为两个文件,但是读取他们的方法却是统一的。只要名字对了就行。
#filepath = 'd:/python/kerastest/cifar10/cifar10.hdf5'
modelGo.load_weights(filepath) #不管你生成了是一个完整的hdf5,还是两个分开的文件都可以读
###or
modelGo.load_weights('cifar10.h5')
这里的modelGo是一个已经创建好结构的模型,只要填入参数即可
总结:
保存为HDF5和H5不同点:直接调用save_weights保存参数为hdf5后缀需要指定绝对路径,保存为h5则可以只需要写名字。而且直接保存,保存为HDF5时会有两个文件。存为单独一个HDF5文件的话(在我这个版本)则可以用回调函数,让程序自己存下模型。
相同点:读取的方式相同,只要路径名字正确即可。
结论:用H5后缀