如何在Keras的train_on_batch中查看与调整Adam学习率
解决Python2 Keras中自定义Adam优化器+train_on_batch时的学习率查看与调整问题
嘿,我来帮你搞定这个问题!在Python2的Keras里用自定义Adam优化器,还靠train_on_batch做训练,确实容易遇到没法直接查看或调整学习率的情况,下面给你几个实用的方案:
一、给自定义Adam优化器添加学习率跟踪属性
如果你是自己继承keras.optimizers.Optimizer写的Adam,可以在自定义类里加个属性实时跟踪当前学习率,这样随时能拿到准确值:
from keras.optimizers import Optimizer import keras.backend as K class CustomAdam(Optimizer): def __init__(self, lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-8, decay=0., **kwargs): super(CustomAdam, self).__init__(**kwargs) self.__dict__.update(locals()) self.iterations = K.variable(0, dtype='int64') self.lr = K.variable(lr) self.beta_1 = K.variable(beta_1) self.beta_2 = K.variable(beta_2) self.decay = K.variable(decay) # 新增跟踪当前学习率的属性 self.current_lr = None self._update_lr() def _update_lr(self): # 按照Adam的逻辑计算实际生效的学习率 lr = self.lr * (1. / (1. + self.decay * K.cast(self.iterations, K.dtype(self.lr)))) t = K.cast(self.iterations, K.floatx()) + 1 self.current_lr = lr * (K.sqrt(1. - K.pow(self.beta_2, t)) / (1. - K.pow(self.beta_1, t))) def get_updates(self, params, loss): grads = self.get_gradients(loss, params) self.updates = [K.update_add(self.iterations, 1)] self._update_lr() # 每次更新迭代时重新计算学习率 # 以下是Adam核心更新逻辑(保留你原有的实现即可) m = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params] v = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params] self.weights = [self.iterations] + m + v for p, g, m_t, v_t in zip(params, grads, m, v): m_t = self.beta_1 * m_t + (1. - self.beta_1) * g v_t = self.beta_2 * v_t + (1. - self.beta_2) * K.square(g) p_t = p - self.current_lr * m_t / (K.sqrt(v_t) + self.epsilon) self.updates.append(K.update(m_t, m_t)) self.updates.append(K.update(v_t, v_t)) new_p = p_t if getattr(p, 'constraint', None) is not None: new_p = p.constraint(new_p) self.updates.append(K.update(p, new_p)) return self.updates def get_config(self): config = {'lr': float(K.get_value(self.lr)), 'beta_1': float(K.get_value(self.beta_1)), 'beta_2': float(K.get_value(self.beta_2)), 'epsilon': self.epsilon, 'decay': float(K.get_value(self.decay))} base_config = super(CustomAdam, self).get_config() return dict(list(base_config.items()) + list(config.items()))
之后你只需要用K.get_value(model.optimizer.current_lr)就能随时获取当前生效的学习率。
二、直接查看/修改优化器内部变量
如果你的自定义Adam没做额外处理,也能直接访问优化器的内部变量来查看或调整:
查看当前实际学习率
import keras.backend as K optimizer = model.optimizer # 获取已完成的迭代次数 iterations = K.get_value(optimizer.iterations) # 提取Adam的核心参数 base_lr = K.get_value(optimizer.lr) decay = K.get_value(optimizer.decay) beta_1 = K.get_value(optimizer.beta_1) beta_2 = K.get_value(optimizer.beta_2) # 按照Adam公式计算当前实际学习率 lr_decayed = base_lr / (1 + decay * iterations) t = iterations + 1 current_lr = lr_decayed * (K.sqrt(1 - K.pow(beta_2, t)) / (1 - K.pow(beta_1, t))) print("当前生效学习率:", current_lr)
手动调整基础学习率
如果想直接修改基础学习率,更新Keras变量即可:
# 把基础学习率改成0.0001 K.set_value(model.optimizer.lr, 0.0001)
后续的train_on_batch会自动用新的基础值结合衰减逻辑计算实际学习率。
三、结合自定义调度逻辑适配train_on_batch
因为train_on_batch不会自动触发Keras内置回调,你可以自己写简单的调度逻辑,按epoch或batch数调整学习率:
def lr_scheduler(epoch, current_base_lr): # 自定义调整规则:每10个epoch学习率减半 if epoch % 10 == 0 and epoch > 0: return current_base_lr * 0.5 return current_base_lr # 训练时维护epoch和batch计数器 epoch = 0 batch_count = 0 batches_per_epoch = 100 # 根据你的数据集设置每个epoch的batch数 while epoch < 20: # 训练20个epoch x_batch, y_batch = your_batch_generator() # 替换成你的取batch函数 loss = model.train_on_batch(x_batch, y_batch) batch_count += 1 # 完成一个epoch后调整学习率 if batch_count >= batches_per_epoch: epoch += 1 batch_count = 0 current_base_lr = K.get_value(model.optimizer.lr) new_lr = lr_scheduler(epoch, current_base_lr) K.set_value(model.optimizer.lr, new_lr) print(f"Epoch {epoch} 完成,学习率调整为: {new_lr}")
内容的提问来源于stack exchange,提问作者Florian Lalande




