我有两个“子问题”
1) 鉴于目前在Tensorboard callback
中write_grads=True
已被弃用,如何使用Tensorboard检测梯度消失或梯度爆炸?详见“un-deprecate write_grads
for fit
#31173″ ?
2) 我认为我可以通过Tensorboard中的分布和直方图标签页中的权重分布和直方图来判断我的模型是否存在梯度消失问题。我的问题是我没有参考框架进行比较。目前,我的偏置似乎在“移动”,但我无法判断我的内核权重(Conv2D层)是否在“移动”/“变化”得“足够”。有人能通过提供一个经验法则来帮助我在Tensorboard中视觉评估吗?例如,如果只有底部25%的内核权重在移动,这是否足够/不够?或者有人能从TensorBoard中发布两张参考图片,分别展示梯度消失和非梯度消失的情况吗?
这是我的直方图和分布,能否判断我的模型是否存在梯度消失问题?(为简洁起见,省略了一些层)提前感谢。
回答:
我目前面临同样的问题,并且使用Tensorboard以类似的方式解决了这个问题。
尽管write_grads
已被弃用,您仍然可以通过子类化tf.keras.Model
类,并在train_step
方法中使用gradient.Tape
手动计算梯度,来记录网络各层的梯度。
类似于下面的方法对我有效
from tensorflow.keras import Modelclass TrainWithCustomLogsModel(Model): def __init__(self, **kwargs): super(TrainWithCustomLogsModel, self).__init__(**kwargs) self.step = tf.Variable(0, dtype=tf.int64,trainable=False) def train_step(self, data): # 获取批次图像和标签 x, y = data # 计算批次损失 with tf.GradientTape() as tape: p = self(x , training = True) loss = self.compiled_loss(y, p, regularization_losses=self.losses) # 计算网络各权重的梯度。注意trainable_vars和gradients是张量列表 trainable_vars = self.trainable_variables gradients = tape.gradient(loss, trainable_vars) # 在Tensorboard中记录梯度 self.step.assign_add(tf.constant(1, dtype=tf.int64)) #tf.print(self.step) with train_summary_writer.as_default(): for var, grad in zip(trainable_vars, gradients): name = var.name var, grad = tf.squeeze(var), tf.squeeze(grad) tf.summary.histogram(name, var, step = self.step) tf.summary.histogram('Gradients_'+name, grad, step = self.step) # 更新模型权重 self.optimizer.apply_gradients(zip(gradients, trainable_vars)) del tape # 更新指标(包括跟踪损失的指标) self.compiled_metrics.update_state(y, p) # 返回一个将指标名称映射到当前值的字典 return {m.name: m.result() for m in self.metrics}
然后,您应该能够可视化训练的任何步骤的梯度分布,以及内核值的分布。
此外,尝试绘制随时间变化的范数分布图而不是单个值,可能会有帮助。