将Keras-Tuner子类化以进行自定义训练循环

时间:2020-03-08 15:19:52

标签: python tensorflow keras

我正在阅读有关keras-team.github.io(link)上的自定义训练循环的调谐器子类化教程。 在端到端的示例中,我不明白为什么要对优化器进行两次定义。 进入build_model函数后:

optimizer = hp.Choice('optimizer', ['adam', 'sgd'])
model.compile(optimizer, loss='sparse_categorical_crossentropy', metrics=['accuracy'])
return model

这对我来说很有意义,但是随后在trial_run内又定义了一个优化器:

lr = hp.Float('learning_rate', 1e-4, 1e-2, sampling='log', default=1e-3)
optimizer = tf.keras.optimizers.Adam(lr)

然后在run_train_step

中使用第二个优化器
with tf.GradientTape() as tape:
    # calculate loss, gradients
    ...
optimizer.apply_gradients(zip(gradients, model.trainable_variables))

这是否意味着永远不会使用build_model中为优化程序定义的超参数?以我对示例的理解方式,在apply_gradients内部用于run_train_step的优化器始终是Adam,具有不同的学习率,但从来没有SGD

我在这里想错了吗?
我目前正在做的只是在建立模型后在run_trial中获得相应的优化器:

def run_trial(self, trial, *fit_args, **fit_kwargs):
    ...
    model = self.hypermodel.build(trial.hyperparameters)
    optimizer = model.optimizer
    ...

本教程让我感到困惑,无论我在做什么,都对此感到满意,对此我很高兴。

编辑:我刚刚意识到设置学习率超参数也是一个问题。由于模型已经编译,因此在run_trial期间无法轻松设置它。在此hp.Choice之上仅返回一个字符串,因此我必须将优化器字符串映射到实际的优化器函数:

optimizer_str_to_func = {
   "sgd": tf.keras.optimizers.SGD,
   "adam": tf.keras.optimizers.Adam,
   "rmsprop": tf.keras.optimizers.RMSprop
}


def build_model(hp):
    num_res_blocks = hp.Int("res_blocks", 8, 32, step=8, default=16)
    model = MyModel(num_res_blocks=num_res_blocks)
    learning_rate = hp.Float("learning_rate", 1e-4, 1e-2, sampling="log", default=1e-3)
    optimizer_name = hp.Choice("optimizer", ["adam", "sgd", "rmsprop"])
    optimizer = optimizer_str_to_func[optimizer_name](lr=learning_rate)
    model.compile(optimizer, loss="mse")
    return model

我觉得这很不对劲。

0 个答案:

没有答案