多层感知器
多层感知器(MLP)是由一个输入层、一个或多个隐藏层和一个称为输出层的最终层组成的人工神经网络(ANN)。一般,靠近输入层的层称为较低层,靠近输出层的层称为外层,除输出层外的每一层都包含一个偏置神经元,并与下一层彻底相连。
当一个ANN包含一个很深的隐藏层时,它被称为深度神经网络(DNN)。
在本文中,咱们将在MNIST数据集上训练一个深度MLP,并经过指数增加来寻找最佳学习率,绘制损失图,并找到损失增加的点,以达到85%以上的准确率。对于最佳的实践过程,咱们将实现早期中止,保存检查点,并使用TensorBoard绘制学习曲线。
你能够在这里查看jupyter Notebook:https://github.com/lukenew2/learning_rates_and_best_practices/blob/master/optimal_learning_rates_with_keras_api.ipynb
指数学习率
学习率能够说是最重要的超参数。通常状况下,最佳学习速率约为最大学习速率(即训练算法偏离的学习速率)的一半。找到一个好的学习率的一个方法是训练模型进行几百次迭代,从很是低的学习率(例如,1e-5)开始,逐渐增长到很是大的值(例如,10)。
这是经过在每次迭代时将学习速率乘以一个常数因子来实现的。若是你将损失描绘为学习率的函数,你应该首先看到它在降低,但过一段时间后,学习率会变得很高,这时损失会迅速回升:最佳学习率将略低于转折点,而后你能够从新初始化你的模型,并使用此良好的学习率对其进行正常训练。
Keras模型
咱们先导入相关库git
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
接下来加载数据集github
(X_train, y_train), (X_test, y_test) = keras.datasets.fashion_mnist.load_data() X_train.shape X_train.dtype
标准化像素web
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:api
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") ])
让咱们一行一行地看这个代码:数组
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])
咱们如今能够将损失绘制为学习率的函数:session
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做为咱们的学习率:app
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),它对图像数据很是有效。
就咱们的目的而言,这就足够了。咱们学会了如何: