我应该选择哪种学习率?

数据挖掘 深度学习 训练 损失函数 优化 学习率
2021-09-23 02:50:28

我正在2d 图像上训练分割模型Unet++我现在正试图找到最佳学习率。模型的主干是Resnet34,我使用Adam优化器,损失函数是dice 损失函数

另外,我使用了一些回调函数:

callbacks = [
            keras.callbacks.EarlyStopping(monitor='val_loss', patience=15, verbose=1, min_delta=epsilon, mode='min'),
            keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3, verbose=1, mode='min', cooldown=0, min_lr=1e-8),
            keras.callbacks.ModelCheckpoint(model_save_path, save_weights_only=True, save_best_only=True, mode='min'),
            keras.callbacks.ReduceLROnPlateau(),
            keras.callbacks.CSVLogger(logger_save_path)
        ]

我绘制了几个学习率的训练损失曲线:

超过 24 个 epoch 的损失函数,学习率等于 2.10^-6

验证损失和训练损失似乎在缓慢减少。然而,验证损失并没有波动(它几乎总是在减少)。

损失函数演化超过 8 个 epoch,学习率等于 2.10^-5

验证和训练损失在前 2/3 时期迅速下降。在 6 或 7 个 epoch 之后,验证损失再次增加。

损失函数演化超过 4 个 epoch,学习率等于 1.10^-4 损失函数演化超过 16 个 epoch,学习率等于 5.10^-4

我有几个问题(希望不要太多):

  • *通常找到学习率的最佳方法是什么,即
    • 在考虑学习率不好之前我应该​​等待多少个时期?
    • 确定学习率是否“好”的损失函数的标准是什么?
  • 如果我使用小学习(仍然收敛)而不是“最佳”学习率,会有很大的不同吗?
  • 验证损失函数在训练过程中振荡是否正常
  • 根据我的结果,我应该使用哪个学习率?

即使是部分回应也会对我有很大帮助。

1个回答

恐怕除了学习率之外,还有很多值可供您选择很多超参数,特别是如果您使用 ADAM 优化等。

调优的原则性重要性顺序如下

  1. 学习率𝛼
  2. 动量项𝛽,每层隐藏单元的数量,批量大小。
  3. 隐藏层数,学习率衰减。

要调整一组超参数,您需要定义一个对每个参数有意义的范围。给定您想要根据预算尝试的多个不同值,您可以从随机抽样中选择一个超参数值。

但是,专门针对学习率调查,您可能希望尝试广泛的值,例如从 0.0001 到 1,因此您可以避免直接从 0.0001 到 1 采样随机值。您可以改为 x=[4,0] 为了 a=10x 基本上遵循对数刻度。

就时期数而言,您应该使用 设置提前停止回调patience~=50,具体取决于您的“探索”预算。这意味着,如果在定义的 epoch 数量上没有改进,您将放弃具有特定学习率值的训练。

可以说,神经网络的参数调整是一种艺术形式。出于这个原因,我建议您查看非手动调整的基本方法,例如在 sklearn 包中实现的方法GridSearchRandomSearch此外,可能值得研究更高级的技术,例如使用高斯过程的贝叶斯优化和 Tree Parzen 估计器。祝你好运!


Keras 中参数调优的随机搜索

  1. 定义创建模型实例的函数
# Model instance
input_shape = X_train.shape[1]

def create_model(n_hidden=1, n_neurons=30, learning_rate = 0.01, drop_rate = 0.5, act_func = 'ReLU',
                act_func_out = 'sigmoid',kernel_init = 'uniform', opt= 'Adadelta'):
    model = Sequential()
    model.add(Dense(n_neurons, input_shape=(input_shape,), activation=act_func,
                   kernel_initializer = kernel_init))
    model.add(BatchNormalization())
    model.add(Dropout(drop_rate))
    # Add as many hidden layers as specified in nl
    for layer in range(n_hidden):
    # Layers have nn neurons model.add(Dense(nn, activation='relu'
        model.add(Dense(n_neurons, activation=act_func, kernel_initializer = kernel_init))
        model.add(BatchNormalization())
        model.add(Dropout(drop_rate))
    model.add(Dense(1, activation=act_func_out, kernel_initializer = kernel_init))
    opt= Adadelta(lr=learning_rate)
    model.compile(loss='binary_crossentropy',optimizer=opt, metrics=[f1_m])
    return model
  1. 定义参数搜索空间
params = dict(n_hidden= randint(4, 32),
              epochs=[50], #, 20, 30],
              n_neurons= randint(512, 600),
              act_func=['relu'],
              act_func_out=['sigmoid'],
              learning_rate= [0.01, 0.1, 0.3, 0.5],
              opt = ['adam','Adadelta', 'Adagrad','Rmsprop'],
              kernel_init = ['uniform','normal', 'glorot_uniform'],
              batch_size=[256, 512, 1024, 2048],
              drop_rate= [np.random.uniform(0.1, 0.4)])
  1. 用 sklearn API 包装 Keras 模型并实例化随机搜索
model = KerasClassifier(build_fn=create_model)
random_search = RandomizedSearchCV(model,  params, n_iter=5, scoring='average_precision', 
                                   cv=5)
  1. 搜索最优超参数
random_search_results = random_search.fit(X_train, y_train, 
                                          validation_data =(X_test, y_test),
                                          callbacks=[EarlyStopping(patience=50)])