如何在Keras中显示模型最后一轮训练实际使用的学习率
我完全理解你的困扰——明明想拿到训练时真正用的学习率,不管怎么试都是初始值,手动计算又怕和实际逻辑不符。其实问题出在Keras优化器的学习率存储逻辑上:optimizer.lr只是基础学习率张量,实际训练中用到的衰减/调整后的学习率是动态计算的,不是直接存在这个属性里的。
下面给你几个直接获取实际学习率的靠谱方案:
方案1:修改回调函数,直接获取衰减后的学习率(最推荐)
不管你用的是内置的学习率衰减(比如decay参数)还是学习率调度器(比如ReduceLROnPlateau、CosineAnnealingLR),TensorFlow 2.x的Keras优化器都提供了_decayed_lr()方法,能直接返回当前实际使用的学习率。修改你的回调函数如下:
from tensorflow.keras.callbacks import Callback import tensorflow as tf class Callback_show_learn_param(Callback): def on_epoch_end(self, epoch, logs=None): # 获取当前实际生效的学习率 current_lr = self.model.optimizer._decayed_lr(tf.float32).numpy() # 其他参数直接取numpy值即可 decay = self.model.optimizer.decay.numpy() beta_1 = self.model.optimizer.beta_1.numpy() beta_2 = self.model.optimizer.beta_2.numpy() print(f"第{epoch+1}轮实际学习率: {current_lr:.6f}") print(f"decay值: {decay}, beta_1: {beta_1}, beta_2: {beta_2}")
这个方法的好处是自动适配所有Keras内置的学习率调整逻辑,不管你用哪种策略,拿到的都是反向传播时真正用到的数值,不用自己写公式计算。
方案2:修复自定义指标,显示实际学习率
你之前的自定义指标返回的是初始学习率,改成返回衰减后的版本就能在训练日志里看到了:
def get_lr_metric(optimizer): def lr(y_true, y_pred): # 返回当前衰减后的学习率张量 return optimizer._decayed_lr(tf.float32) return lr # 然后添加到指标列表 lr_metric = get_lr_metric(optimizer) metric_list.append(lr_metric)
这样训练时每一轮的日志里都会输出实际的学习率,不用单独看回调的打印信息。
旧版Keras(TensorFlow 1.x)的兼容方案
如果你还在使用TF1.x的Keras,可以用手动计算的方式,但要确保和优化器的衰减逻辑一致:
import keras.backend as K class Callback_show_learn_param(Callback): def on_epoch_end(self, epoch, logs=None): lr = K.eval(self.model.optimizer.lr) decay = K.eval(self.model.optimizer.decay) iterations = K.eval(self.model.optimizer.iterations) # 按照Keras默认的衰减公式计算实际学习率 current_lr = lr / (1. + decay * iterations) beta_1 = K.eval(self.model.optimizer.beta_1) beta_2 = K.eval(self.model.optimizer.beta_2) print(f"第{epoch+1}轮实际学习率: {current_lr:.6f}") print(f"初始lr: {lr}, decay: {decay}, beta_1: {beta_1}, beta_2: {beta_2}")
不过这个方法只适用于默认的阶梯衰减,如果用了其他学习率调度器,还是得用对应调度器的方法获取调整后的值。
为什么之前的方法不行?
你之前手动计算的lr_with_decay只符合Keras默认的decay参数逻辑,但如果用了ReduceLROnPlateau这类动态调整学习率的回调,这个公式就不适用了——这类调度器会直接修改优化器的学习率张量,而不是通过decay和iterations计算。而_decayed_lr()方法会自动处理所有这些情况,直接拿到最终生效的学习率。
内容的提问来源于stack exchange,提问作者user3723247

