基于批次而非周期的指数衰减学习率

我想基于时间步长而非周期来调整学习率,这与大多数调度器不同。我有一个模型如下:

import tensorflow as tffrom tensorflow.keras.models import Modelfrom tensorflow.keras import layersfrom tensorflow.keras.optimizers import Adamclass DQNagent:    def __init__(self, state_size, action_size):        self.state_size = state_size        self.action_size = action_size        self.model = self.build_model()    # 原模型        self.target_model = self.build_model()  # 目标模型        self.lr = 1e-2    def build_model(self):                x_in = layers.Input(shape=(self.step_size, self.state_size))        x_out = layers.Dense(20, activation='relu')(x_in)        output = layers.Dense(self.action_size, activation='linear')(x_out)                self.learning_rate = CustomSchedule()         opt = tf.keras.optimizers.Adam(self.learning_rate)        model = Model(inputs=x_in, outputs=output_y, name="DQN")        model.compile(loss=['mse'], optimizer=opt)            return model

我想创建一个类似这样的调度器:

class CustomSchedule:  def __init__(self, lr=1e-2):    super(CustomSchedule, self).__init__()    self.lr = lr    self.t = 0  def __call__(self):    self.t +=1    if self.t % 100 ==0:        self.lr /= 10    return self.lr

我的主要代码没有声明所有内容,大致如下:

dqn = DQNagent(state_size, action_size)for step in range(1000):    states_all = np.array([[[0, 0, 1],[1,0,1], [0, -1, 1], [1,-1,1]]])    Q_values =  dqn.model.predict(state_all)[0]        # 训练    batch = memory.sample(batch_size)    batch_states = utils.get_states_user(batch) # 假设我使用此方法生成了状态        Q_states = dqn.model.predict(batch_states) # 假设我已经抽样了批次状态        dqn.model.fit(batch_states, Q_states, verbose =0)

我想调整我的学习率,使得当step%100==0时,学习率减少为learning_rate/10。看起来对于我创建的CustomSchedule类,我需要重新编译model,这似乎不太有效,因为需要保存和加载权重。有什么其他方法可以实现吗?

编辑:

我根据@FedericoMalerba的回答编辑了我的代码

创建了一个decay_func如下:

def decay_func(step, lr):    return lr/10**(step/100)

然后我对我的DQNAgent类做了以下更改:

class DQNAgent():     def __init__(self, state_size, action_size):     self.lr = 1e-2     self.t_step = tf.Variable(0, trainable=False, name='Step', dtype=tf.int64)     self.decaying_lr = partial(decay_func, step=self.step, lr=self.lr)         def __call__(self):        self.step.assign_add(1)        return self.step

并在我的主要代码中每一步调用dqn()。可调用的decaying_lrbuild_model()中传递给优化器,如opt = tf.keras.optimizers.Adam(self.decaying_lr)


回答:

一般来说,可以通过创建一个不带参数的可调用对象(函数)并将其传递给在DQNagent.build_model()中定义的Adam优化器来处理这个问题。具体步骤如下:

  1. 创建你的epsilon衰减函数:
def decay_func(step_tensor, **other_arguments_your_func_needs):    # 函数体。必须使用输入参数step tensor来确定要返回的学习率    return learning_rate
  1. 创建你的步长张量(必须是张量!!!):
step = tf.Variable(0, trainable=False, name='Step', dtype=tf.int64)
  1. 创建要传递给优化器的可调用对象:
from functools import partialdecaying_learning_rate = partial(decay_func, step_tensor=step, **other_arguments_your_func_needs)
  1. 在创建优化器时传递可调用对象:
opt = tf.keras.optimizers.Adam(decaying_learning_rate)
  1. 在训练循环中通过增加你的步长张量来迭代:
step.assing_add(1)

你实际上是在创建一个不带参数的可调用对象decaying_learning_rate,因为所有参数都通过functools.partial调用传递给了它。tensorflow优化器会发现学习率不是一个数字,而是一个可调用对象,并像这样调用它:

this_step_learning_rate = decaying_learning_rate()

由于张量是运行时共享的对象,当你使用step.assing_add(1)增加你的步长计数器时,这个新的步长将在优化器的下一次调用中用于计算你的decay_func中的新学习率。尽管你没有明确传递新的和更新的张量,但这仍然会发生。真是神奇!

顺便说一下,这正是指数衰减所做的。我在这里展示的只是一种通用的方法来定义你自己的decay_func,并让它像TF预实现的指数衰减一样工作。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注