Colab加载Keras LSTM模型修改units参数出现AttributeError如何解决
问题原因
Keras中LSTM层的units是只读属性,模型加载完成后,层的核心结构参数(比如循环层的单元数、卷积层的卷积核数量这类直接影响权重形状的参数)被封装成了只读@property,不能直接修改。你之前可以正常修改的是不影响权重维度的超参数(比如Dropout层的rate、激活函数类型这类),所以不会触发报错。
你原本的直接修改.units属性再转JSON生成新模型的思路行不通,因为只读属性的修改不会生效,就算你强制赋值,JSON序列化时读取的还是层内部存储的原始结构参数,不会识别你额外赋值的属性。
解决方案
根据你是否需要保留原有LSTM层的预训练权重,分为两种处理方式:
场景1:不需要保留原有LSTM层的预训练权重,直接重构模型
直接复用原有模型除LSTM层外的结构和权重,手动替换LSTM层即可,代码示例:
import keras from keras.models import Sequential from keras.layers import LSTM # 加载原有模型 model = keras.models.load_model('model.h5') new_units = 100 # 构建新模型 new_model = Sequential() # 复用前两层(Embedding、Dropout)的结构和权重 for layer in model.layers[:2]: new_model.add(layer) # 加入新的LSTM层,units设置为目标数值 new_model.add(LSTM(units=new_units)) # 复用后面两层(Dropout、Dense)的结构和权重 for layer in model.layers[3:]: new_model.add(layer) # 编译后即可使用 new_model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) new_model.summary()
场景2:调整LSTM单元数的同时尽可能复用原有权重
改units会导致LSTM层权重的形状发生变化,你可以手动适配权重形状,保留原有单元的权重,新增单元的权重可以用初始值或者补零,代码示例:
# 加载原有模型 model = keras.models.load_model('model.h5') old_lstm = model.layers[2] new_units = 100 # 新建和原LSTM层参数一致、仅units不同的新层 new_lstm = LSTM(units=new_units, return_sequences=old_lstm.return_sequences, return_state=old_lstm.return_state) # 先build新层拿到权重占位 new_lstm.build(input_shape=old_lstm.input_shape) # 适配权重:保留原有单元的权重,新增单元保留初始值 old_weights = old_lstm.get_weights() new_weights = new_lstm.get_weights() for i in range(len(old_weights)): slice_len = min(old_weights[i].shape[-1], new_weights[i].shape[-1]) new_weights[i][..., :slice_len] = old_weights[i][..., :slice_len] new_lstm.set_weights(new_weights) # 替换原有模型的LSTM层 new_model = Sequential() for layer in model.layers[:2]: new_model.add(layer) new_model.add(new_lstm) for layer in model.layers[3:]: new_model.add(layer) new_model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
内容的提问来源于stack exchange,提问作者Rafael Greca
相关产品推荐
相关产品推荐

