关于人工智能:深度学习的学习率调节实践

9次阅读

共计 6526 个字符,预计需要花费 17 分钟才能阅读完成。

作者 |Luke Newman
编译 |VK
起源 |Towards Data Science

多层感知器

多层感知器(MLP)是由一个输出层、一个或多个暗藏层和一个称为输入层的最终层组成的人工神经网络(ANN)。通常,凑近输出层的层称为较低层,凑近输入层的层称为外层。除输入层外的每一层都蕴含一个偏置神经元,并与下一层齐全相连。

当一个 ANN 蕴含一个很深的暗藏层时,它被称为深度神经网络(DNN)。

在这项考察中,咱们将在 MNIST 时尚数据集上训练一个深度 MLP,并通过指数增长来寻找最佳学习率,绘制损失图,并找到损失增长的点,以达到 85% 以上的准确率。对于最佳实际,咱们将实现晚期进行,保留检查点,并应用 TensorBoard 绘制学习曲线。

你能够在这里查看 jupyter Notebook:https://github.com/lukenew2/l…

指数学习率

学习率能够说是最重要的超参数。个别状况下,最佳学习速率约为最大学习速率(即训练算法偏离的学习速率)的一半。找到一个好的学习率的一个办法是训练模型进行几百次迭代,从非常低的学习率(例如,1e-5)开始,逐步减少到十分大的值(例如,10)。

这是通过在每次迭代时将学习速率乘以一个常数因子来实现的。如果你将损失描述为学习率的函数,你应该首先看到它在降落。但过一段时间后,学习率会太高,因而损失会迅速回升:最佳学习率将略低于转折点。而后,你能够从新初始化你的模型,并应用此良好的学习率对其进行失常训练。

Keras 模型

咱们先导入相干库

import os
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

PROJECT_ROOT_DIR = "."
IMAGES_PATH = os.path.join(PROJECT_ROOT_DIR, "images")
os.makedirs(IMAGES_PATH, exist_ok=True)

def save_fig(fig_id, tight_layout=True, fig_extension="png", resolution=300):
    path = os.path.join(IMAGES_PATH, fig_id + "." + fig_extension)
    print("Saving figure", fig_id)
    if tight_layout:
        plt.tight_layout()
    plt.savefig(path, format=fig_extension, dpi=resolution)
import tensorflow as tf
from tensorflow import keras

接下来加载数据集

(X_train, y_train), (X_test, y_test) = keras.datasets.fashion_mnist.load_data()

X_train.shape

X_train.dtype

标准化像素

X_valid, X_train = X_train[:5000] / 255.0, X_train[5000:] / 255.0
y_valid, y_train = y_train[:5000], y_train[5000:] 
X_test = X_test / 255.0

让咱们疾速看一下数据集中的图像样本,让咱们感受一下分类工作的复杂性:

class_names = ["T-shirt/top", "Trouser", "Pullover", "Dress", "Coat",
               "Sandal", "Shirt", "Sneaker", "Bag", "Ankle boot"]

n_rows = 4
n_cols = 10
plt.figure(figsize=(n_cols * 1.2, n_rows * 1.2))
for row in range(n_rows):
    for col in range(n_cols):
        index = n_cols * row + col
        plt.subplot(n_rows, n_cols, index + 1)
        plt.imshow(X_train[index], cmap="binary", interpolation="nearest")
        plt.axis('off')
        plt.title(class_names[y_train[index]], fontsize=12)
plt.subplots_adjust(wspace=0.2, hspace=0.5)
save_fig('fashion_mnist_plot', tight_layout=False)
plt.show()

咱们曾经筹备好用 Keras 来建设咱们的 MLP。上面是一个具备两个暗藏层的分类 MLP:

model = keras.models.Sequential([keras.layers.Flatten(input_shape=[28,28]),
    keras.layers.Dense(300, activation="relu"),
    keras.layers.Dense(100, activation="relu"),
    keras.layers.Dense(10, activation="softmax")
])

让咱们一行一行地看这个代码:

  • 首先,咱们创立了一个 Sequential 模型,它是神经网络中最简略的 Keras 模型,它只由一堆按程序连贯的层组成。
  • 接下来,咱们构建第一层并将其增加到模型中。它是一个 Flatten 层,其目标是将每个输出图像转换成一个 1D 数组:如果它接管到输出数据 X,则计算 X.reshape(-1,1)。因为它是模型的第一层,所以应该指定输出形态。或者,你能够增加 keras.layers.InputLayer 作为第一层,设置其 input_shape=[28,28]
  • 下一步,咱们增加一个 300 个神经元的暗藏层,并指定它应用 ReLU 激活函数。每一个全连贯层治理本人的权重矩阵,蕴含神经元与其输出之间的所有连贯权重。它还治理一个偏置向量,每个神经元一个。
  • 而后咱们增加了第二个 100 个神经元的暗藏层,同样应用 ReLU 激活函数。
  • 最初,咱们应用 softmax 激活函数增加了一个蕴含 10 个神经元的输入层(因为咱们执行的分类是每个类都是互斥的)。

应用回调

在 Keras 中,fit() 办法承受一个回调参数,该参数容许你指定 Keras 将在训练开始和完结、每个 epoch 的开始和完结时,甚至在解决每个 batch 解决之前和之后要调用对象的列表。

为了实现指数级增长的学习率,咱们须要创立本人的自定义回调。咱们的回调承受一个参数,用于进步学习率的因子。为了将损失描绘成学习率的函数,咱们跟踪每个 batch 的速率和损失。

请留神,咱们将函数定义为 on_batch_end(),这取决于咱们的指标。当然也能够是 on_train_begin(), on_train_end(), on_batch_begin()。对于咱们的用例,咱们心愿在每个批处理之后进步学习率并记录损失:

K = keras.backend

class ExponentialLearningRate(keras.callbacks.Callback):
    def __init__(self, factor):
        self.factor = factor
        self.rates = []
        self.losses = []
    def on_batch_end(self, batch, logs):
        self.rates.append(K.get_value(self.model.optimizer.lr))
        self.losses.append(logs["loss"])
        K.set_value(self.model.optimizer.lr, self.model.optimizer.lr * self.factor)

当初咱们的模型曾经创立好了,咱们只需调用它的 compile() 办法来指定要应用的 loss 函数和优化器。或者,你能够指定要在训练和评估期间计算的额定指标列表。

首先,咱们应用“稠密的分类穿插熵”损失,因为咱们有稠密的标签(也就是说,对于每个实例,只有一个指标类索引,在咱们的例子中,从 0 到 9),并且这些类是互斥的)。接下来,咱们指定应用随机梯度降落,并将学习速率初始化为 1e-3,并在每次迭代中减少 0.5%:

model.compile(loss="sparse_categorical_crossentropy",
              optimizer=keras.optimizers.SGD(lr=1e-3),
              metrics=["accuracy"])
expon_lr = ExponentialLearningRate(factor=1.005)

当初让咱们只在一个 epoch 训练模型:

history = model.fit(X_train, y_train, epochs=1,
                    validation_data=(X_valid, y_valid),
                    callbacks=[expon_lr])

咱们当初能够将损失绘制为学习率的函数:

plt.plot(expon_lr.rates, expon_lr.losses)
plt.gca().set_xscale('log')
plt.hlines(min(expon_lr.losses), min(expon_lr.rates), max(expon_lr.rates))
plt.axis([min(expon_lr.rates), max(expon_lr.rates), 0, expon_lr.losses[0]])
plt.xlabel("Learning rate")
plt.ylabel("Loss")
save_fig("learning_rate_vs_loss")

正如咱们所冀望的,随着学习率的进步,最后的损失逐步缩小。但过了一段时间,学习率太大,导致损失反弹:最佳学习率将略低于损失开始攀升的点(通常比转折点低 10 倍左右)。咱们当初能够从新初始化咱们的模型,并应用良好的学习率对其进行失常训练。

还有更多的学习率技巧,包含创立学习进度表,我心愿在当前的考察中介绍,但对如何手动抉择好的学习率有一个直观的了解同样重要。

咱们的损失在 3e- 1 左右开始反弹,所以让咱们尝试应用 2e- 1 作为咱们的学习率:

keras.backend.clear_session()
np.random.seed(42)
tf.random.set_seed(42)
model = keras.models.Sequential([keras.layers.Flatten(input_shape=[28, 28]),
    keras.layers.Dense(300, activation="relu"),
    keras.layers.Dense(100, activation="relu"),
    keras.layers.Dense(10, activation="softmax")
])
model.compile(loss="sparse_categorical_crossentropy",
              optimizer=keras.optimizers.SGD(lr=2e-1),
              metrics=["accuracy"])

应用 TensorBoard 进行可视化

TensorBoard 是一个很好的交互式可视化工具,你能够应用它查看训练期间的学习曲线、比拟学习曲线、可视化计算图、剖析训练统计数据、查看模型生成的图像,可视化简单的多维数据投影到三维和主动聚类,等等!这个工具是在装置 TensorFlow 时主动装置的,所以你应该曾经装置了。

让咱们首先定义将用于 TensorBoard 日志的根日志目录,再加上一个小函数,该函数将依据以后工夫生成一个子目录门路,以便每次运行时它都是不同的。你可能须要在日志目录名称中蕴含额定的信息,例如正在测试的超参数值,以便更容易地理解你在 TensorBoard 中查看的内容:

root_logdir = os.path.join(os.curdir, "my_logs")

def get_run_logdir():
    import time
    run_id = time.strftime("run_%Y_%m_%d-%H_%M_%S")
    return os.path.join(root_logdir, run_id)

run_logdir = get_run_logdir() # 例如, './my_logs/run_2020_07_31-15_15_22'

Keras api 提供了一个 TensorBoard() 回调函数。TensorBoard() 回调函数负责创立日志目录, 并在训练时创立事件文件和编写摘要 (摘要是一种二进制数据记录用于创立可视化 TensorBoard)。

每次运行有一个目录,每个目录蕴含一个子目录,别离用于训练日志和验证日志。两者都蕴含事件文件,但训练日志也蕴含剖析跟踪:这使 TensorBoard 可能精确地显示模型在模型的每个局部(逾越所有设施)上破费了多少工夫,这对于查找性能瓶颈十分有用。

early_stopping_cb = keras.callbacks.EarlyStopping(patience=20)
checkpoint_cb = keras.callbacks.ModelCheckpoint("my_fashion_mnist_model.h5", save_best_only=True)
tensorboard_cb = keras.callbacks.TensorBoard(run_logdir)

history = model.fit(X_train, y_train, epochs=100,
                    validation_data=(X_valid, y_valid),
                    callbacks=[early_stopping_cb, checkpoint_cb, tensorboard_cb])

接下来,咱们须要启动 TensorBoard 服务器。咱们能够通过运行以下命令在 Jupyter 中间接执行此操作。第一行加载 TensorBoard 扩大,第二行启动端口 6004 上的 TensorBoard 服务器,并连贯到它:

%load_ext tensorboard 
%tensorboard — logdir=./my_logs — port=6004

当初你应该能够看到 TensorBoard 的 web 界面。单击“scaler”选项卡以查看学习曲线。在左下角,抉择要可视化的日志(例如,第一次运行的训练日志),而后单击 epoch_loss scaler。请留神,在咱们的训练过程中,训练损失降落得很顺利。

你还能够可视化整个图形、学习的权重(投影到 3D)或剖析轨迹。TensorBoard() 回调函数也有记录额定数据的选项,例如 NLP 数据集的嵌入。

这实际上是一个十分有用的可视化工具。

论断

在这里咱们失去了 88% 的准确率,这是咱们能够达到的最好的深度 MLP。如果咱们想进一步提高性能,咱们能够尝试卷积神经网络(CNN),它对图像数据十分无效。

就咱们的目标而言,这就足够了。咱们学会了如何:

  • 应用 Keras 的 Sequential API 构建深度 mlp。
  • 通过按指数增长学习率,绘制损失图,并找到损失从新呈现的点,来找到最佳学习率。
  • 构建深度学习模型时的最佳实际,包含应用回调和应用 TensorBoard 可视化学习曲线。

如果你想在这里看到演示幻灯片或 jupyterNotebook 中残缺的代码和阐明,请随时查看 Github 存储库:https://github.com/lukenew2/l…

额定的资源

https://www.tensorflow.org/te…

https://towardsdatascience.co…

原文链接:https://towardsdatascience.co…

欢送关注磐创 AI 博客站:
http://panchuang.net/

sklearn 机器学习中文官网文档:
http://sklearn123.com/

欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/

正文完
 0