Keras模型权重用scipy savemat保存后加载报错,求正确加载方式
解决从.mat文件加载Keras模型权重的问题
我来帮你排查这个ValueError: Shapes must be equal rank错误的原因,以及给出可行的解决方案:
错误原因分析
当你用scipy.io.savemat保存model.get_weights()的结果时,需要注意:Keras的get_weights()返回的是Python列表,每个元素是对应层的权重numpy数组;而Scipy会把这个列表转换成Matlab风格的object类型数组(因为Matlab没有原生的列表结构)。
加载后你得到的W['lstm_32']并不是直接的权重列表,而是一个二维numpy数组(通常形状是(1, num_weights)),每个数组元素才是原始的权重矩阵。你之前用list(W['lstm_32'][0])提取的内容,其实是错误地取了数组的某个维度,导致权重形状和模型期望的不匹配,最终触发形状不兼容的错误。
解决方案
方案1:正确提取.mat文件中的权重列表
加载后,需要把W['lstm_32']中的元素展平并转换成Python列表,再传入set_weights:
import scipy.io as sio # 加载.mat文件 W = sio.loadmat('lstm_weights.mat') # 展平object数组并转成权重列表 loaded_weights = [weight for weight in W['lstm_32'].flatten()] # 为模型设置权重 model.set_weights(loaded_weights)
方案2:用更适配的方式保存/加载权重(推荐)
如果你不需要和Matlab交互,更推荐使用Keras原生的权重保存方法,完全避免格式转换的问题:
# 保存权重(Keras原生格式) model.save_weights('lstm_weights.h5') # 加载权重 model.load_weights('lstm_weights.h5')
如果必须使用.mat文件,下次保存时可以把每个权重单独存为字典的键,这样加载时更直观:
import scipy.io as sio # 保存时拆分权重列表为单独键 weights = model.get_weights() save_dict = {f'layer_weight_{i}': weight for i, weight in enumerate(weights)} sio.savemat('lstm_weights.mat', save_dict) # 加载时重组权重列表 W = sio.loadmat('lstm_weights.mat') num_weights = len([key for key in W if key.startswith('layer_weight_')]) loaded_weights = [W[f'layer_weight_{i}'] for i in range(num_weights)] model.set_weights(loaded_weights)
验证步骤(可选)
设置权重前,你可以先对比原模型权重和加载后权重的形状是否一致,确保没有问题:
# 原模型权重的形状列表 original_shapes = [w.shape for w in model.get_weights()] # 加载后权重的形状列表 loaded_shapes = [w.shape for w in loaded_weights] print("形状是否匹配:", original_shapes == loaded_shapes) # 应输出True
内容的提问来源于stack exchange,提问作者shaifali Gupta
相关产品推荐
相关产品推荐

