使用Keras加载重训练VGG16模型时出现ValueError问题求助
问题分析与解决方案
错误根源
你遇到的ValueError本质是模型保存/加载时的权重形状不匹配:你的自定义模型最后一层是Dense(3)(输入维度4096,对应VGG16倒数第二层的输出),但加载时Keras尝试匹配原VGG16最后一层Dense(1000)的权重形状(输入维度1000),导致冲突。
这是因为你直接复制VGG16的所有层到Sequential模型后再pop()最后一层的操作,并没有完全清除原模型的权重元数据绑定——原VGG16的最后一层权重信息仍残存在模型的内部映射中,保存时被写入HDF5文件,加载时就会和新添加的Dense(3)层的期望形状冲突。
正确的模型构建方式
推荐两种避免该问题的构建方法,优先选择Functional API(更灵活清晰):
方法1:使用Functional API(推荐)
这种方式直接基于VGG16的特征输出构建新模型,完全规避原分类层的干扰:
from keras.applications.vgg16 import VGG16 from keras.models import Model from keras.layers import Dense from keras.optimizers import Adam # 加载预训练VGG16,不包含顶部的1000类全连接层,用全局平均池化压缩特征 vgg16_base = VGG16(weights='imagenet', include_top=False, pooling='avg') # 冻结所有预训练层 for layer in vgg16_base.layers: layer.trainable = False # 添加自定义3分类层 x = vgg16_base.output predictions = Dense(3, activation='softmax')(x) # 构建完整模型 model = Model(inputs=vgg16_base.input, outputs=predictions) # 编译模型 model.compile(Adam(lr=.0001), loss='categorical_crossentropy', metrics=['accuracy'])
方法2:改进版Sequential构建
如果坚持用Sequential,直接跳过VGG16的最后一层,而不是添加后再删除:
from keras.applications.vgg16 import VGG16 from keras.models import Sequential from keras.layers import Dense from keras.optimizers import Adam vgg16_model = VGG16() model = Sequential() # 只添加VGG16的前len(vgg16_model.layers)-1层(自动跳过最后一层Dense(1000)) for layer in vgg16_model.layers[:-1]: model.add(layer) # 冻结所有预训练层 for layer in model.layers: layer.trainable = False # 添加自定义3分类层 model.add(Dense(3, activation='softmax')) # 编译模型 model.compile(Adam(lr=.0001), loss='categorical_crossentropy', metrics=['accuracy'])
验证保存与加载
用上述任意一种方法构建并训练模型后,再执行保存和加载操作:
# 保存模型 model.save('my_model_vgg16.h5') # 重启内核后加载模型 from keras.models import load_model loaded_model = load_model('my_model_vgg16.h5')
此时加载模型不会再出现形状不匹配的错误,因为模型的权重元数据完全对应你自定义的结构。
内容的提问来源于stack exchange,提问作者AaronDT
相关产品推荐
相关产品推荐

