Keras训练深度自编码器时,Checkpoint无法加载模型与权重
我帮你梳理一下可能导致这个问题的原因,以及对应的解决办法:
一、先确认权重文件是否真的保存了
你说加载返回None,大概率是weights.best.h5根本没生成,或者生成的路径不对。可以按这几点排查:
检查save_best_only的逻辑是否生效
你设置了save_best_only=True,这个参数会只保存"最优"的模型权重,但前提是Keras能判断什么是"最优":- 默认监控的是
val_loss,所以你必须在model.fit()里传入validation_data或者validation_split,否则Keras拿不到验证集损失,就不会保存任何权重。 - 可以明确指定监控指标和mode,比如如果监控训练集loss,就写
monitor='loss',mode设为'min'(因为loss越小越好);如果监控准确率就用monitor='val_accuracy',mode设为'max'。 - 把
verbose改成1,这样训练时如果保存了权重,控制台会打印类似Epoch 00003: val_loss improved from 0.56 to 0.42, saving model to weights.best.h5的日志,一眼就能知道有没有保存成功。
调整后的checkpointer代码:
checkpointer = ModelCheckpoint(filepath="weights.best.h5", verbose=1, save_best_only=True, monitor='val_loss', mode='min')- 默认监控的是
检查文件路径是否正确
用相对路径的话,文件会保存在当前Python工作目录下。你可以用import os; print(os.getcwd())查看当前工作目录,确认weights.best.h5是否在里面。如果不在,换成绝对路径试试,比如filepath="/Users/xxx/Projects/weights.best.h5"。检查权限问题
如果程序没有目标路径的写入权限,也会导致无法生成权重文件。可以手动在目标路径创建一个文件试试,确认权限没问题。
二、检查加载方式是否正确
很多人会误以为load_weights()会返回模型,但其实它是原地修改现有模型的权重,本身返回None是正常的!正确的加载流程应该是这样:
先定义好和训练时完全一致的模型结构:
input_enc = Input(shape=(input_size,)) hidden = Dense(64, activation='relu')(input_enc) # ... 这里要和你训练时的层结构、参数完全一样 output_dec = Dense(input_size, activation='sigmoid')(hidden) autoencoder = Model(input_enc, output_dec) autoencoder.compile(optimizer='adam', loss='mse')调用
load_weights()加载权重(返回None是正常的,但权重已经加载到autoencoder里了):autoencoder.load_weights("weights.best.h5")之后直接使用这个autoencoder模型就行,比如做预测:
pred = autoencoder.predict(your_test_data)
如果你想直接加载包含结构和权重的完整模型,可以在ModelCheckpoint里设置save_weights_only=False(默认就是False),然后用load_model()加载:
from keras.models import load_model autoencoder = load_model("weights.best.h5") # 这里会返回模型对象,不会是None
三、完整示例代码
给你一个能正常运行的自编码器+ModelCheckpoint示例,你可以对照自己的代码找差异:
from keras.layers import Input, Dense from keras.models import Model from keras.callbacks import ModelCheckpoint, TensorBoard import numpy as np # 模拟输入数据 input_size = 784 x_train = np.random.rand(1000, input_size) x_val = np.random.rand(200, input_size) # 构建自编码器 input_enc = Input(shape=(input_size,)) hidden = Dense(64, activation='relu')(input_enc) output_dec = Dense(input_size, activation='sigmoid')(hidden) autoencoder = Model(input_enc, output_dec) autoencoder.compile(optimizer='adam', loss='mse') # 配置回调 checkpointer = ModelCheckpoint(filepath="weights.best.h5", verbose=1, save_best_only=True, monitor='val_loss', mode='min') tensorboard = TensorBoard(log_dir='/tmp/autoencoder', histogram_freq=0, write_graph=True, write_images=True) # 训练(必须传入验证集) autoencoder.fit(x_train, x_train, epochs=10, batch_size=32, validation_data=(x_val, x_val), callbacks=[checkpointer, tensorboard]) # 加载权重并测试 autoencoder.load_weights("weights.best.h5") test_pred = autoencoder.predict(x_val[:10]) print(test_pred.shape) # 输出(10, 784)说明加载成功
内容的提问来源于stack exchange,提问作者Mari

