Keras基于外部损失更新模型权重时梯度全为None的解决方法
基于外部代价函数训练模型时梯度返回全None问题
我尝试基于外部代价函数完成模型训练,整体计算流程如下:
- 首先model_1接收声谱图(spectrograms)输入,基于输入生成包含4个值的输出向量
- Model_2为已完成训练的预训练模型,训练过程中冻结其权重不做更新,该模型接收model_1输出的4维向量完成预测,结合时间信号生成与model_1初始输入(原始声谱图)形状完全一致的输出
- 对比上述第二步生成的最终输出与model_1的原始输入(两组声谱图)计算损失值
得到损失值与model_1的预测结果后,我需要获取损失对model_1权重的梯度,以正确完成权重更新。为此我使用tf.GradientTape()实现:先获取model_1的预测结果,再计算原始声谱图与最终生成声谱图的损失。我推测当前问题的成因是最终声谱图的计算路径并非完全由model_1构成,导致无法按现有写法完成梯度回传,因此想要确认:是否可以仅通过预测结果、代表损失函数输出的标量值完成梯度计算?
我编写了如下用于获取梯度的训练函数,但返回的梯度列表元素全为None:
def train_modelo_inverso(self, epochs=40): for s in range(epochs): espectrogramas_predicts = self.get_espectrograms_from_amplitudes() # 第一次执行预测,获取生成的预测声谱图 loss_modelo_inverso = self.loss_fn(self.amplitudes, espectrogramas_predicts) # 构建tf计算图,用于计算参数对当前预测对应损失的偏导 with tf.GradientTape() as tape: modelo_inverso_preds = self.modelo_inverso(self.amplitudes) # 基于预测结果更新参数 # espectrogramas_predicts = self.get_espectrograms_from_amplitudes() loss_modelo_inverso = self.loss_fn(self.amplitudes, espectrogramas_predicts) gradients = tape.gradient(loss_modelo_inverso, self.modelo_inverso.trainable_variables) print(f"gradients {gradients} | len(self.modelo_inverso.trainable_variables) {len(self.modelo_inverso.trainable_variables)} | loss_modelo_inverso {loss_modelo_inverso}")# 基于预测结果计算梯度
运行上述函数的打印输出如下:
gradients [None, None, None, None, None, None] | len(self.modelo_inverso.trainable_variables) 6 | loss_modelo_inverso (9.79201461332436e-12-1.57796630234136e-10j)
我初步判断该现象的成因为:计算损失函数时并未使用model_1输出的预测张量,换言之损失计算路径未接入model_1的计算图,因此无法对model_1的参数求导。
内容的提问来源于stack exchange,提问作者CYD
相关产品推荐
相关产品推荐

