深度学习 Day11——T11优化器对比实验

  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍖 原作者:K同学啊 | 接辅导、项目定制

文章目录

  • 前言
  • 一、我的环境
  • 二、代码实现与执行结果
    • 1.引入库
    • 2.设置GPU(如果使用的是CPU可以忽略这步)
    • 3.导入数据
    • 4.查看数据
    • 5.加载数据
    • 6.再次检查数据
    • 7.配置数据集
    • 8.可视化数据
    • 9.构建CNN网络模型
    • 10.编译模型
    • 11.训练模型
    • 12.模型评估
  • 三、知识点详解
    • 1.加载预训练的 VGG16 模型
    • 2 优化器
      • 2.1 梯度下降法 (Gradient Descent)
        • 2.1.1 批量梯度下降法 (Batch Gradient Descent, BGD)
        • 2.1.2随机梯度下降(Stochastic Gradient Descent, SGD)
      • 2.2 动量优化法(Momentum)
      • 2.3 自适应学习率优化算法
        • 2.2.1 AdaGrad(Adaptive Gradient)
        • 2.2.2 Adadelta
        • 2.2.3 RMSprop
        • 2.2.4 Adam(Adaptive Moment Estimation)
  • 总结


前言

本文将采用CNN实现好莱坞明星识别,并用两种不同的优化器用于训练,并进行对比。简单讲述实现代码与执行结果,并浅谈涉及知识点。
关键字:加载预训练的 VGG16 模型,优化器。

一、我的环境

  • 电脑系统:Windows 11
  • 语言环境:python 3.8.6
  • 编译器:pycharm2020.2.3
  • 深度学习环境:TensorFlow 2.10.1
  • 显卡:NVIDIA GeForce RTX 4070

二、代码实现与执行结果

1.引入库

from PIL import Image
import numpy as np
from pathlib import Path
import tensorflow as tf
from tensorflow.keras.layers import Dropout, Dense, BatchNormalization
from tensorflow.keras.models import Model
import matplotlib.pyplot as plt
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
import warnings
warnings.filterwarnings('ignore')  # 忽略一些warning内容,无需打印

2.设置GPU(如果使用的是CPU可以忽略这步)

'''前期工作-设置GPU(如果使用的是CPU可以忽略这步)'''
# 检查GPU是否可用
print(tf.test.is_built_with_cuda())
gpus = tf.config.list_physical_devices("GPU")
print(gpus)
if gpus:gpu0 = gpus[0]  # 如果有多个GPU,仅使用第0个GPUtf.config.experimental.set_memory_growth(gpu0, True)  # 设置GPU显存用量按需使用tf.config.set_visible_devices([gpu0], "GPU")

执行结果

True
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]

3.导入数据

[好莱坞明星数据](https://pan.baidu.com/share/init?surl=C6-9ke_2fPlS2yK_TrNdpQ&pwd=czli)

'''前期工作-导入数据'''
data_dir = r"D:\DeepLearning\data\HollywoodStars"
data_dir = Path(data_dir)

4.查看数据

'''前期工作-查看数据'''
image_count = len(list(data_dir.glob('*/*.jpg')))
print("图片总数为:", image_count)
roses = list(data_dir.glob('Jennifer Lawrence/*.jpg'))
image = Image.open(str(roses[1]))
# 查看图像实例的属性
print(image.format, image.size, image.mode)
plt.imshow(image)
plt.show()

执行结果:

图片总数为: 1800
JPEG (474, 569) RGB

在这里插入图片描述

5.加载数据

'''数据预处理-加载数据'''
batch_size = 16
img_height = 336
img_width = 336
"""
关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
"""
train_ds = tf.keras.preprocessing.image_dataset_from_directory(data_dir,validation_split=0.2,subset="training",seed=12,image_size=(img_height, img_width),batch_size=batch_size)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(data_dir,validation_split=0.2,subset="validation",seed=12,image_size=(img_height, img_width),batch_size=batch_size)
class_names = train_ds.class_names
print(class_names)

运行结果:

Found 1800 files belonging to 17 classes.
Using 1440 files for training.
Found 1800 files belonging to 17 classes.
Using 360 files for validation.
['Angelina Jolie', 'Brad Pitt', 'Denzel Washington', 'Hugh Jackman', 'Jennifer Lawrence', 'Johnny Depp', 'Kate Winslet', 'Leonardo DiCaprio', 'Megan Fox', 'Natalie Portman', 'Nicole Kidman', 'Robert Downey Jr', 'Sandra Bullock', 'Scarlett Johansson', 'Tom Cruise', 'Tom Hanks', 'Will Smith']

6.再次检查数据

'''数据预处理-再次检查数据'''
# Image_batch是形状的张量(16, 336, 336, 3)。这是一批形状336x336x3的16张图片(最后一维指的是彩色通道RGB)。
# Label_batch是形状(16,)的张量,这些标签对应16张图片
for image_batch, labels_batch in train_ds:print(image_batch.shape)print(labels_batch.shape)break

运行结果

(16, 336, 336, 3)
(16,)

7.配置数据集

'''数据预处理-配置数据集'''
AUTOTUNE = tf.data.AUTOTUNE
def train_preprocessing(image, label):return (image / 255.0, label)
train_ds = (train_ds.cache().shuffle(1000).map(train_preprocessing)  # 这里可以设置预处理函数# .batch(batch_size)           # 在image_dataset_from_directory处已经设置了batch_size.prefetch(buffer_size=AUTOTUNE)
)
val_ds = (val_ds.cache().shuffle(1000).map(train_preprocessing)  # 这里可以设置预处理函数# .batch(batch_size)         # 在image_dataset_from_directory处已经设置了batch_size.prefetch(buffer_size=AUTOTUNE)
)

8.可视化数据

'''数据预处理-可视化数据'''
plt.figure(figsize=(10, 8))  # 图形的宽为10高为5
plt.suptitle("数据展示", fontsize=20)
for images, labels in train_ds.take(1):for i in range(15):plt.subplot(3, 5, i + 1)plt.xticks([])plt.yticks([])plt.grid(False)# 显示图片plt.imshow(images[i])# 显示标签plt.xlabel(class_names[np.argmax(labels[i])],fontdict={'family' : 'Times New Roman', 'size':20})
plt.show()

在这里插入图片描述

9.构建CNN网络模型

'''构建CNN网络'''
def create_model(optimizer='adam'):# 加载预训练模型vgg16_base_model = tf.keras.applications.vgg16.VGG16(weights='imagenet',include_top=False,input_shape=(img_width, img_height, 3),pooling='avg')for layer in vgg16_base_model.layers:layer.trainable = FalseX = vgg16_base_model.outputX = Dense(170, activation='relu')(X)X = BatchNormalization()(X)X = Dropout(0.5)(X)output = Dense(len(class_names), activation='softmax')(X)vgg16_model = Model(inputs=vgg16_base_model.input, outputs=output)vgg16_model.compile(optimizer=optimizer,loss='sparse_categorical_crossentropy',metrics=['accuracy'])return vgg16_model
model1 = create_model(optimizer=tf.keras.optimizers.Adam())
model2 = create_model(optimizer=tf.keras.optimizers.SGD())
model2.summary()

网络结构结果如下:

Model: "model_1"
_________________________________________________________________Layer (type)                Output Shape              Param #   
=================================================================input_2 (InputLayer)        [(None, 336, 336, 3)]     0         block1_conv1 (Conv2D)       (None, 336, 336, 64)      1792      block1_conv2 (Conv2D)       (None, 336, 336, 64)      36928     block1_pool (MaxPooling2D)  (None, 168, 168, 64)      0         block2_conv1 (Conv2D)       (None, 168, 168, 128)     73856     block2_conv2 (Conv2D)       (None, 168, 168, 128)     147584    block2_pool (MaxPooling2D)  (None, 84, 84, 128)       0         block3_conv1 (Conv2D)       (None, 84, 84, 256)       295168    block3_conv2 (Conv2D)       (None, 84, 84, 256)       590080    block3_conv3 (Conv2D)       (None, 84, 84, 256)       590080    block3_pool (MaxPooling2D)  (None, 42, 42, 256)       0         block4_conv1 (Conv2D)       (None, 42, 42, 512)       1180160   block4_conv2 (Conv2D)       (None, 42, 42, 512)       2359808   block4_conv3 (Conv2D)       (None, 42, 42, 512)       2359808   block4_pool (MaxPooling2D)  (None, 21, 21, 512)       0         block5_conv1 (Conv2D)       (None, 21, 21, 512)       2359808   block5_conv2 (Conv2D)       (None, 21, 21, 512)       2359808   block5_conv3 (Conv2D)       (None, 21, 21, 512)       2359808   block5_pool (MaxPooling2D)  (None, 10, 10, 512)       0         global_average_pooling2d_1   (None, 512)              0         (GlobalAveragePooling2D)                                        dense_2 (Dense)             (None, 170)               87210     batch_normalization_1 (Batc  (None, 170)              680       hNormalization)                                                 dropout_1 (Dropout)         (None, 170)               0         dense_3 (Dense)             (None, 17)                2907      =================================================================
Total params: 14,805,485
Trainable params: 90,457
Non-trainable params: 14,715,028
_________________________________________________________________

10.编译模型

# 设置初始学习率
initial_learning_rate = 1e-4lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(initial_learning_rate,decay_steps=60,      # 敲黑板!!!这里是指 steps,不是指epochsdecay_rate=0.96,     # lr经过一次衰减就会变成 decay_rate*lrstaircase=True)# 将指数衰减学习率送入优化器
optimizer = tf.keras.optimizers.Adam(learning_rate=lr_schedule)model.compile(optimizer=optimizer,loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),metrics=['accuracy'])

11.训练模型

'''训练模型'''
NO_EPOCHS = 50history_model1 = model1.fit(train_ds, epochs=NO_EPOCHS, verbose=1, validation_data=val_ds)
history_model2 = model2.fit(train_ds, epochs=NO_EPOCHS, verbose=1, validation_data=val_ds)

训练记录如下:

Epoch 1/50
90/90 [==============================] - 13s 99ms/step - loss: 2.7601 - accuracy: 0.1764 - val_loss: 2.7506 - val_accuracy: 0.1250
Epoch 2/50
90/90 [==============================] - 8s 86ms/step - loss: 2.0679 - accuracy: 0.3285 - val_loss: 2.4926 - val_accuracy: 0.2111
Epoch 3/50
90/90 [==============================] - 8s 86ms/step - loss: 1.7437 - accuracy: 0.4410 - val_loss: 2.2004 - val_accuracy: 0.3639
......
Epoch 49/50
90/90 [==============================] - 8s 86ms/step - loss: 0.1929 - accuracy: 0.9354 - val_loss: 2.8650 - val_accuracy: 0.4972
Epoch 50/50
90/90 [==============================] - 8s 86ms/step - loss: 0.1694 - accuracy: 0.9458 - val_loss: 2.7593 - val_accuracy: 0.4694
Epoch 1/50
90/90 [==============================] - 8s 87ms/step - loss: 3.0367 - accuracy: 0.1090 - val_loss: 2.7868 - val_accuracy: 0.1250
Epoch 2/50
90/90 [==============================] - 8s 86ms/step - loss: 2.5409 - accuracy: 0.1979 - val_loss: 2.6385 - val_accuracy: 0.1056
Epoch 3/50
90/90 [==============================] - 8s 86ms/step - loss: 2.2875 - accuracy: 0.2847 - val_loss: 2.4560 - val_accuracy: 0.2167
......

12.模型评估

'''模型评估'''
from matplotlib.ticker import MultipleLocatorplt.rcParams['savefig.dpi'] = 300  # 图片像素
plt.rcParams['figure.dpi'] = 300  # 分辨率acc1 = history_model1.history['accuracy']
acc2 = history_model2.history['accuracy']
val_acc1 = history_model1.history['val_accuracy']
val_acc2 = history_model2.history['val_accuracy']loss1 = history_model1.history['loss']
loss2 = history_model2.history['loss']
val_loss1 = history_model1.history['val_loss']
val_loss2 = history_model2.history['val_loss']epochs_range = range(len(acc1))plt.figure(figsize=(16, 4))
plt.subplot(1, 2, 1)plt.plot(epochs_range, acc1, label='Training Accuracy-Adam')
plt.plot(epochs_range, acc2, label='Training Accuracy-SGD')
plt.plot(epochs_range, val_acc1, label='Validation Accuracy-Adam')
plt.plot(epochs_range, val_acc2, label='Validation Accuracy-SGD')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
# 设置刻度间隔,x轴每1一个刻度
ax = plt.gca()
ax.xaxis.set_major_locator(MultipleLocator(1))plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss1, label='Training Loss-Adam')
plt.plot(epochs_range, loss2, label='Training Loss-SGD')
plt.plot(epochs_range, val_loss1, label='Validation Loss-Adam')
plt.plot(epochs_range, val_loss2, label='Validation Loss-SGD')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')# 设置刻度间隔,x轴每1一个刻度
ax = plt.gca()
ax.xaxis.set_major_locator(MultipleLocator(1))plt.show()def test_accuracy_report(model):score = model.evaluate(val_ds, verbose=0)print('Loss function: %s, accuracy:' % score[0], score[1])test_accuracy_report(model1)
test_accuracy_report(model2)

在这里插入图片描述

Loss function: 2.759303092956543, accuracy: 0.4694444537162781
Loss function: 1.3968818187713623, accuracy: 0.5805555582046509

三、知识点详解

1.加载预训练的 VGG16 模型

def create_model(optimizer='adam'):# 加载预训练模型vgg16_base_model = tf.keras.applications.vgg16.VGG16(weights='imagenet',include_top=False,input_shape=(img_width, img_height, 3),pooling='avg')for layer in vgg16_base_model.layers:layer.trainable = FalseX = vgg16_base_model.outputX = Dense(170, activation='relu')(X)X = BatchNormalization()(X)X = Dropout(0.5)(X)output = Dense(len(class_names), activation='softmax')(X)vgg16_model = Model(inputs=vgg16_base_model.input, outputs=output)vgg16_model.compile(optimizer=optimizer,loss='sparse_categorical_crossentropy',metrics=['accuracy'])return vgg16_modelmodel1 = create_model(optimizer=tf.keras.optimizers.Adam())
model2 = create_model(optimizer=tf.keras.optimizers.SGD())
model2.summary()

定义了一个名为 create_model 的函数,该函数接受一个参数 optimizer(默认为 ‘adam’)。函数内部首先使用 tf.keras.applications.vgg16.VGG16 加载了预训练的 VGG16 模型,其中 weights = ‘imagenet’ 表示使用 ImageNet 数据集的预训练权重,include_top = False 表示不包含顶层的全连接层,input_shape 设置输入图像的形状,pooling = ‘avg’ 表示使用平均池化。

然后,对 VGG16 模型的所有层进行循环遍历,将每一层的 trainable 属性设置为 False,即冻结预训练参数,使它们在训练过程中保持不变。

接下来,将 VGG16 模型的输出作为输入,并经过一系列的神经网络层进行特征提取和分类。首先是全连接层 Dense(170, activation = ‘relu’),然后是批归一化层 BatchNormalization(),最后是丢弃层 Dropout(0.5),用于防止过拟合。

最后一层是输出层 Dense(len(class_names), activation = ‘softmax’),其中 len(class_names) 是类别的数量,根据具体情况进行设置,激活函数使用 softmax。

接下来,使用 Model 函数创建了一个新的模型 vgg16_model,指定了输入和输出。这里的 vgg16_base_model.input 表示 VGG16 模型的输入,output 表示上述神经网络层的输出。

然后,使用 compile 方法编译了模型,指定了优化器、损失函数和评估指标。优化器根据传入的参数进行选择,如果没有指定,默认为 Adam 优化器。损失函数使用稀疏分类交叉熵,评估指标为准确率。

最后,函数返回创建的模型。

接下来,通过调用 create_model 函数分别创建了两个模型 model1 和 model2,分别使用了 Adam 优化器和 SGD 优化器。最后调用 model2.summary() 打印了 model2 的模型摘要信息。

参考链接:深度学习-第T11周——优化器对比实验

2 优化器

优化器是一种算法,它在模型优化过程中,动态地调整梯度的大小和方向,使模型能够收敛到更好的位置,或者用更快的速度进行收敛。

2.1 梯度下降法 (Gradient Descent)

我们可以把模型的参数空间想象成是一个曲面,曲面的高度是整体上模型预测值与真实值的误差。我们的目的就是找到整个曲面的最低点,这样我们其实就找到了模型参数的最优点。梯度下降法是最基本的优化算法之一,它让参数朝着梯度下降最大的方向去变化。

假设模型参数为 θ \theta θ,损失函数为 J ( θ ) J(\theta) J(θ) ,损失函数 J ( θ ) J(\theta) J(θ) 关于参数 θ \theta θ 的偏导数,也就是梯度为 ∇ t J ( θ ) \nabla_tJ(\theta) tJ(θ) ,学习率为 α \alpha α ,则使用梯度下降法更新参数的公式为:
θ t + 1 = θ t − α ⋅ ∇ t J ( θ ) \theta_{t+1}=\theta_t-\alpha\cdot\nabla_tJ(\theta) θt+1=θtαtJ(θ)

梯度下降算法中,沿着梯度的方向不断减小模型参数,从而最小化损失函数。基本策略可以理解为”在你目光所及的范围内,不断寻找最陡最快的路径下山“

算法缺点:

  • 训练速度慢:每走一步都要计算调整下一步的方向,下山的速度变慢。在应用于大型数据集中,每输入一个样本都要更新一次参数,且每次迭代都要遍历所有的样本。会使得训练过程及其缓慢,需要花费很长时间才能得到收敛解。
  • 容易陷入局部最优解:由于是在有限视距内寻找下山的方向。当陷入平坦的洼地,会误以为到达了山地的最低点,从而不会继续往下走。

真正在使用时,主要是经过改进的以下三类方法,区别在于每次参数更新时计算的样本数据量不同

  • 批量梯度下降法(BGD, Batch Gradient Descent)
  • 随机梯度下降法(SGD, Stochastic Gradient Descent)
  • 小批量梯度下降法(Mini-batch Gradient Descent)
2.1.1 批量梯度下降法 (Batch Gradient Descent, BGD)

  第一种很天然的想法是批量梯度下降法BGD(Batch Gradient Descent),其实就是每次用全量的数据对参数进行梯度下降。
假设训练样本总数为n,样本为 {(x1,y1), … (xn, yn)} ,模型参数为 θ \theta θ,损失函数为 J ( θ ) J(\theta) J(θ) ,损失函数 J ( θ ) J(\theta) J(θ) 关于参数 θ \theta θ 的偏导数,也就是梯度为 ∇ t J ( θ ) \nabla_tJ(\theta) tJ(θ) ,学习率为 α \alpha α ,则使用BGD更新参数为:
θ t + 1 = θ t − α t ⋅ ∑ i = 1 n ∇ t J i ( θ , x i , y i ) \theta_{t+1}=\theta_t-\alpha_t\cdot\sum_{i=1}^n\nabla_tJ_i(\theta,x^i,y^i) θt+1=θtαti=1ntJi(θ,xi,yi)
由上式可以看出,每进行一次参数更新,需要计算整个数据样本集,因此导致批量梯度下降法的速度会比较慢,尤其是数据集非常大的情况下,收敛速度就会非常慢,但是由于每次的下降方向为总体平均梯度,它可能得到的会是一个全局最优解。

2.1.2随机梯度下降(Stochastic Gradient Descent, SGD)

随机梯度下降法,不像BGD每一次参数更新,需要计算整个数据样本集的梯度,而是每次参数更新时,仅仅选取一个样本(xi, yi)计算其梯度,参数更新公式为
θ t + 1 = θ t − α ⋅ ∇ t J i ( θ , x i , y i ) \theta_{t+1}=\theta_t-\alpha\cdot\nabla_tJ_i(\theta,x^i,y^i) θt+1=θtαtJi(θ,xi,yi)
SGD训练速度很快,即使在样本量很大的情况下,可能只需要其中一部分样本就能迭代到最优解,由于每次迭代并不是都向着整体最优化方向,导致梯度下降的波动非常大(如下图),更容易从一个局部最优跳到另一个局部最优,准确度下降。

优点

  • 由于每次迭代只使用了一个样本计算梯度,训练速度快,包含一定随机性,但是从期望来看,每次计算的梯度基本是正确的导数的。虽然看起来SGD波动非常大,会走很多弯路,但是对梯度的要求很低(计算梯度快),而且对于引入噪声,大量的理论和实践工作证明,只要噪声不是特别大,SGD都能很好地收敛。
  • 应用大型数据集时,训练速度很快。比如每次从百万数据样本中,取几百个数据点,算一个SGD梯度,更新一下模型参数。相比于标准梯度下降法的遍历全部样本,每输入一个样本更新一次参数,要快得多
    缺点:
  • 更新频繁,带有随机性,会造成损失函数在收敛过程中严重震荡。SGD没能单独克服局部最优解的问题(主要)
  • SGD在随机选择梯度的同时会引入噪声,使得权值更新的方向不一定正确(次要)

2.2 动量优化法(Momentum)

关于动量
动量优化法引入了物理之中的概念。动量 p=mvp=mvp=mv,当一个小球从山顶滚下,速度越来越快,动量越来越大,开始加速梯度下降,当跨越了山谷,滚到对面的坡上时,速度减小,动量减小。

带动量的小球不仅可以加速梯度;还可以借着积累的动量,冲过小的山坡,以避免落入局部最优点。

动量优化法(Momentum)提出的原因
梯度下降法容易被困在局部最小的沟壑处来回震荡,可能存在曲面的另一个方向有更小的值;有时候梯度下降法收敛速度还是很慢。动量法就是为了解决这两个问题提出的

动量优化法思想
参数更新时在一定程度上保留之前更新的方向,同时又利用当前batch的梯度微调最终的更新方向,简言之就是通过积累之前的动量来 (previous_sum_of_gradient) 加速当前的梯度。

优缺点分析

  • 优点:前后梯度一致的时候能够加速学习;前后梯度不一致的时候能够抑制震荡,越过局部极小值(加速收敛,减小震荡)
  • 缺点:多了一个超参数,增加了计算量

2.3 自适应学习率优化算法

传统的优化算法要么将学习率设置为常数要么根据训练次数调节学习率。往往忽视了学习率其他变化的可能性。学习率对模型的性能有着显著的影响,需要采取一些策略来更新学习率,进而提高训练速度与准确率。

使用统一的全局学习率的缺点可能出现的问题

  • 对于某些参数,通过算法已经优化到了极小值附近,但是有的参数仍然有着很大的梯度。
  • 如果学习率太小,则梯度很大的参数会有一个很慢的收敛速度; 如果学习率太大,则已经优化得差不多的参数可能会出现不稳定的情况。

解决方案:对每个参与训练的参数设置不同的学习率,在整个学习过程中通过一些算法自动适应这些参数的学习率。
如果损失与某一指定参数的偏导的符号相同,那么学习率应该增加; 如果损失与该参数的偏导的符号不同,那么学习率应该减小。

2.2.1 AdaGrad(Adaptive Gradient)

Adagrad其实是对学习率进行了一个约束,对于经常更新的参数,我们已经积累了大量关于它的知识,不希望被单个样本影响太大,希望学习速率慢一些;对于偶尔更新的参数,我们了解的信息太少,希望能从每个偶然出现的样本(稀疏特征的样本)身上多学一些,即学习速率大一些。该方法中开始使用的二阶动量,意味着“自适应学习率”优化算法时代的到来。

AdaGrad 算法,独立地适应所有模型参数的学习率,缩放每个参数反比于其所有梯度历史平均值总和的平方根。(知道这么回事就好,基本不用它~)
● 具有损失函数最大梯度的参数相应地有个快速下降的学习率 ● 而具有小梯度的参数在学习率上有相对较小的下降。

优点:自适应的学习率,无需人工调节
缺点

  • 仍需要手工设置一个全局学习率 η, 如果 η 设置过大的话,会使 regularizer 过于敏感,对梯度的调节太大
  • 中后期,分母上梯度累加的平方和会越来越大,使得参数更新量趋近于0,使得训练提前结束,无法学习
2.2.2 Adadelta

由于AdaGrad调整学习率变化过于激进,我们考虑一个改变二阶动量计算方法的策略:不累积全部历史梯度,而只关注过去一段时间窗口的下降梯度,即Adadelta只累加固定大小的项,并且也不直接存储这些项,仅仅是近似计算对应的平均值(指数移动平均值),这就避免了二阶动量持续累积、导致训练过程提前结束的问题了。

优点

  • 不依赖全局learning rate
  • 训练初中期,加速效果不错,很快

缺点: 训练后期,反复在局部最小值附近抖动

2.2.3 RMSprop

RMSprop 和 Adadelta 都是为了解决 AdaGrad 学习率急剧下降问题的,但是RMSProp算法修改了AdaGrad的梯度平方和累加为指数加权的移动平均

指数加权平均,旨在消除梯度下降中的摆动,与Momentum的效果一样,某一维度的导数比较大,则指数加权平均就大,某一维度的导数比较小,则其指数加权平均就小,这样就保证了各维度导数都在一个量级,进而减少了摆动。

另外,指数衰减平均的方式可以淡化遥远过去的历史对当前步骤参数更新量的影响,衰减率表明的是只是最近的梯度平方有意义,而很久以前的梯度基本上会被遗忘

优点

  • RMSprop算是Adagrad的一种发展,和Adadelta的变体,效果趋于二者之间
  • 适合处理非平稳目标(包括季节性和周期性)——对于RNN效果很好

缺点:其实RMSprop依然依赖于全局学习率 η

2.2.4 Adam(Adaptive Moment Estimation)

Adam 结合了前面方法的一阶动量和二阶动量,是前述方法的集大成者。

优点

  • Adam梯度经过偏置校正后,每一次迭代学习率都有一个固定范围,使得参数比较平稳。
  • 结合了Adagrad善于处理稀疏梯度和RMSprop善于处理非平稳目标的优点
  • 为不同的参数计算不同的自适应学习率
  • 节省了训练集时间、训练成本

缺点: Adam 使用动量的滑动平均,可能会随着训练数据变化而抖动比较剧烈,在online场景可能波动较大,在广告场景往往效果不如 AdaGrad

Adam那么棒,为什么还对SGD念念不忘
举个栗子。很多年以前,摄影离普罗大众非常遥远。十年前,傻瓜相机开始风靡,游客几乎人手一个。智能手机出现以后,摄影更是走进千家万户,手机随手一拍,前后两千万,照亮你的美(咦,这是什么乱七八糟的)。但是专业摄影师还是喜欢用单反,孜孜不倦地调光圈、快门、ISO、白平衡……一堆自拍党从不care的名词。技术的进步,使得傻瓜式操作就可以得到不错的效果,但是在特定的场景下,要拍出最好的效果,依然需要深入地理解光线、理解结构、理解器材。
更深入的内容,可以通过文末的参考文献进入了解。
1)TensorFlow2调用
函数原型:

keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)

📍官网地址:https://www.tensorflow.org/api_docs/python/tf/keras/optimizers/Adam

参数详解:

  • lr: float >= 0. 学习率。
  • beta_1: float, 0 < beta < 1. 通常接近于 1。
  • beta_2: float, 0 < beta < 1. 通常接近于 1。
  • epsilon: float >= 0. 模糊因子. 若为 None, 默认为 K.epsilon()。
  • decay: float >= 0. 每次参数更新后学习率衰减值。
  • amsgrad: boolean. 是否应用此算法的 AMSGrad 变种,来自论文 “On the Convergence of Adam and Beyond”。

调用示例:

# 设置优化器
opt = tf.keras.optimizers.Adam(learning_rate=0.001, decay=0.0)model.compile(optimizer=opt,loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),metrics=['accuracy'])

参考文献
An overview of gradient descent optimization algorithms

Adam那么棒,为什么还对SGD念念不忘 (2)—— Adam的两宗罪

总结

通过本次的学习,了解了预加载模型的用法,了解了多种优化器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/216259.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker部署Mysql5.7x和Myslq8.x

Docker部署Mysql5.7x和Myslq8.x 文章目录 1.部署mysql5.7.x2.部署mysql8.x3.创建用户授权及远程登录3.1 mysql5.7创建用户授权及远程登录3.2 mysql8创建用户授权及远程登录 4.总结 1.部署mysql5.7.x 在D盘下的mysql目录下新建如下目录&#xff1a; D:\mysql\conf\my.cnf内容如下…

centos7 docker Mysql8 搭建主从

Mysql8 搭建主从 docker的安装docker-compose的安装安装mysql配置主从在master配置在slave中配置在master中创建同步用户在slave中连接 测试连接测试配置测试数据同步遇到的问题id重复错误执行事务出错&#xff0c;跳过错误my.cnf 不删除多余配置的错误可能用到的命令 docker的…

【ARM Trace32(劳特巴赫) 使用介绍 13 -- Trace32 断点 Break 命令篇】

文章目录 1. Break.Set1.1 TRACE32 Break1.1.1 Break命令控制CPU的暂停1.2 Break.Set 设置断点1.2.1 Trace32 程序断点1.2.2 读写断点1.2.2.1 变量被改写为特定值触发halt1.2.2.2 设定非值触发halt1.2.2.4 变量被特定函数改写触发halt1.2.3 使用C/C++语法设置断点条件1.2.4 使用…

苍穹外卖项目笔记(11)— 数据统计-图形报表

前言 代码链接&#xff1a; Echo0701/take-out⁤ (github.com) 1 Apache ECharts 基于 Javascript 的数据可视化图标库&#xff0c;提供直观生动可交互可个性定制的数据可视化图表 柱形图饼形图折线图 【核心】通过直观的图表来展示数据。使用 Echarts &#xff0c;重点在…

算法——位运算

常见位运算总结 基础位运算 << >> ~与&&#xff1a;有0就是0或|&#xff1a;有1就是1异或^&#xff1a;相同为0&#xff0c;相异为1 / 无进位相加 给一个数n&#xff0c;确定他的二进制表示中的第x位是0还是1 让第x位与上1即可先让n右移x位&上一个1&#…

java反序列化数据过滤

前言&#xff1a; 反序列化漏洞的危害稍微了解一点的都知道&#xff0c;如果能找到前端某处存在反序列化漏洞&#xff0c;那基本上距离拿下服务器仅一步之遥&#xff0c;这个时候我们可以通过继承ObjectInputFilter添加tFilter实现对所有反序列化类的校验&#xff0c;当然这个需…

嵌入式行业是否会面临中年危机?

今日话题&#xff1a;嵌入式行业是否会面临中年危机&#xff1f;事实上&#xff0c;无论你在哪个行业工作&#xff0c;都可能面临下岗风险。因此&#xff0c;我的建议是选择一个有前景、发展空间大的行业和方向&#xff0c;并不断提升自己的技能价值。为了帮助你在嵌入式领域取…

perl处理json的序列化和反序列化

perl可以使用JSON模块很方便的处理json的序列化和反序列化。先来一段简单的例子&#xff1a; #! /usr/bin/perl use v5.14; use JSON; use IO::File;my $info {id > 1024,desc > hello world,arry > [1, 2, 3, 4, 5],obj > {char > [ A, B, C ]} };say to_jso…

个人介绍以及毕业去向

CSDN陪伴我从大一到大四&#xff0c;后面也会接着用 写一点大学四年的总结 #总结#理工科#留学 211大学 弃保出国 智能科学与技术 均分88.9 EI论文一篇 数学竞赛和数学建模均为省二 大创评为国家级 全国大学生计算机设计大赛国家三等奖 百度Paddle、大疆RoboMaster、Phytium Te…

2 mysql主从复制配置

1、节点以及网络配置 前置条件&#xff1a; 已经在linux上安装好了一主一从或者一主多从的mysql 2、具体配置 主服务器 172.20.0.2 从服务器 172.20.0.3 首先主机mysql配置&#xff1a; 打开mysqld.cnf&#xff1a; 添加如下配置&#xff1a; # 主服务器ID 必须唯一 serve…

硕士论文写的重复率 PaperBERT

大家好&#xff0c;今天来聊聊硕士论文写的重复率&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff1a; 硕士论文写的重复率 1. 硕士论文的重要性 硕士论文是硕士阶段最重要的学术成果之一&#xff0c;它不仅…

基于ssm四六级报名与成绩查询系统论文

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对四六级报名信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性…

UE4 图片环形轮播 蓝图

【需求】 图片环形轮播 任意图片之间相互切换 切换图片所需时间均为1s 两个图片之间切换使用就近原则 播放丝滑无闪跳 【Actor的组成】 每个图片的轴心都在原点 【蓝图节点】

记录 | linux安装Manim

linux 安装 Manim sudo apt update sudo apt install build-essential python3-dev libcairo2-dev libpango1.0-dev ffmpeg sudo apt install xdg-utilsconda create manim_py39 python3.9 conda activate manim_py39pip install manim安装好环境后来测试一个例程&#xff0c;…

ECS省钱指南来啦!万字长文教你如何选择与业务形态最匹配的付费方式

为了更好的帮助用户在使用DevOps缩短开发周期、提升业务效率的同时&#xff0c;也能让业务保持稳定、安全、可靠&#xff0c;且低成本的持续运营&#xff0c;阿里云弹性计算团队独家出品的【弹性计算技术公开课_CloudOps云上运维季】正式启动。阿里云弹性计算内部13位产品&…

接口测试 — 1.接口和接口文档概念

1、接口的概念 接口又叫API&#xff0c;全称application programming interface&#xff1a;应用程序接口&#xff08;规范&#xff09;&#xff0c;也就是我们经常会听说Web接口&#xff0c;APP接口。 详细说明&#xff1a; APP是一种基于C/S架构的应用程序&#xff0c;如抖音…

MYSQL练题笔记-子查询-电影评分

一、题目相关内容 1&#xff09;相关的表 2&#xff09;题目 3&#xff09;帮助理解题目的示例&#xff0c;提供返回结果的格式 二、自己初步的理解 1.字典序是指从前到后比较两个字符串大小的方法。 首先比较第1个字符&#xff0c;如果不同则第1个字符较小的字符串更小&…

Retrofit嵌套请求与适配器

一、前言&#xff1a; 1. retrofit嵌套请求 在实际开发中&#xff0c;可能会存在&#xff1a;需要先请求A接口&#xff0c;在请求B接口的情况&#xff0c;比如进入“玩android”网页请求获取收藏文章列表&#xff0c;但是需要先登录拿到Cookie才能请求搜藏文章几口&am…

day01、什么是数据库系统?

数据库系统介绍 1.实例化与抽象化数据库系统2.从用户角度看数据库管理系统的功能2.1 数据库定义功能2.2 数据库操纵2.3 数据库控制2.4 数据库维护功能2.5 数据库语言与高级语言 3.从系统&#xff1a;数据库管理系统应具有什么功能 来源于战德臣的B站网课 1.实例化与抽象化数据库…