使用Keras训练LSTM后,如何提取并重组权重矩阵?
嘿,我来帮你把Keras里LSTM的权重问题掰明白!你说调用model.get_weights()只拿到偏置?其实是没认出那些大矩阵对应的部分啦,咱们一步步拆解:
一、先搞懂你的模型权重构成
当你调用model.get_weights()时,返回的是一个有序列表,里面的元素依次是:
- LSTM层的输入到隐藏+隐藏到隐藏权重矩阵
- LSTM层的偏置向量
- Dense层的权重矩阵
- Dense层的偏置向量
你觉得只有偏置,大概率是没意识到前面那两个大矩阵就是LSTM核心的权重部分~
二、LSTM层权重的详细拆分
你的LSTM定义了100个隐藏单元,输入维度是data_dim。Keras里的LSTM每个门(输入门i、遗忘门f、细胞更新g、输出门o)都包含两类权重:输入x到门的权重,以及上一时刻隐藏状态h_t-1到门的权重,这些被打包在了两个大矩阵里:
第一组:输入到所有门的权重
形状是(data_dim, 4*100),这是把四个门的输入权重拼在一起了,拆分方式:- 输入门权重:取前100列 →
weights[0][:, :100] - 遗忘门权重:取中间100列 →
weights[0][:, 100:200] - 细胞更新权重:取接下来100列 →
weights[0][:, 200:300] - 输出门权重:取最后100列 →
weights[0][:, 300:400]
- 输入门权重:取前100列 →
第二组:隐藏到所有门的循环权重
形状是(100, 4*100),这是把四个门的循环权重拼在一起,拆分逻辑和上面一致:- 输入门循环权重:
weights[1][:, :100] - 遗忘门循环权重:
weights[1][:, 100:200] - 细胞更新循环权重:
weights[1][:, 200:300] - 输出门循环权重:
weights[1][:, 300:400]
- 输入门循环权重:
第三组:LSTM的偏置向量
形状是(4*100,),同样对应四个门的偏置,每个门占100个值:- 输入门偏置:
weights[2][:100] - 遗忘门偏置:
weights[2][100:200] - 细胞更新偏置:
weights[2][200:300] - 输出门偏置:
weights[2][300:400]
- 输入门偏置:
三、动手重组权重的代码示例
给你写个实用的小代码,直接把这些权重拆成每个门独立的矩阵,方便你查看或修改:
# 获取模型所有权重 all_weights = model.get_weights() # 提取LSTM层的三组权重 lstm_input_weights = all_weights[0] lstm_recurrent_weights = all_weights[1] lstm_biases = all_weights[2] # 拆分输入到各大门的权重 input_i = lstm_input_weights[:, :100] # 输入门:输入→隐藏 input_f = lstm_input_weights[:, 100:200] # 遗忘门:输入→隐藏 input_g = lstm_input_weights[:, 200:300] # 细胞更新:输入→隐藏 input_o = lstm_input_weights[:, 300:400] # 输出门:输入→隐藏 # 拆分隐藏到各大门的循环权重 recurrent_i = lstm_recurrent_weights[:, :100] # 输入门:隐藏→隐藏 recurrent_f = lstm_recurrent_weights[:, 100:200] # 遗忘门:隐藏→隐藏 recurrent_g = lstm_recurrent_weights[:, 200:300] # 细胞更新:隐藏→隐藏 recurrent_o = lstm_recurrent_weights[:, 300:400] # 输出门:隐藏→隐藏 # 拆分偏置 bias_i = lstm_biases[:100] bias_f = lstm_biases[100:200] bias_g = lstm_biases[200:300] bias_o = lstm_biases[300:400]
你可以打印拆分后的矩阵形状验证,比如print(input_i.shape),应该是(data_dim, 100),完全符合输入维度到输入门隐藏单元的映射逻辑~
另外补充一下,Dense层的权重是all_weights[3](形状(100,5),对应LSTM的100个隐藏单元到5个输出类),偏置是all_weights[4](形状(5,)),这个就比较直观啦。
内容的提问来源于stack exchange,提问作者Michele

