You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在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

火山引擎 最新活动