深度学习t11-优化器对比实验

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


我的环境:

1.语言:python3.7

2.编译器:pycharm

3.深度学习环境:TensorFlow2.5


一、前期工作

1、设置GPU

import tensorflow as tf
gpus = tf.config.list_physical_devices("GPU")

if gpus:
    gpu0 = gpus[0] #如果有多个GPU,仅使用第0个GPU
    tf.config.experimental.set_memory_growth(gpu0, True) #设置GPU显存用量按需使用
    tf.config.set_visible_devices([gpu0],"GPU")

from tensorflow import keras
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import warnings,os,PIL,pathlib

warnings.filterwarnings("ignore")             #忽略警告信息
plt.rcParams['font.sans-serif']    = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False    # 用来正常显示负号

二、导入数据

data_dir = "E:/TF环境/48-data/"
data_dir = pathlib.Path(data_dir)
image_count = len(list(data_dir.glob('*/*.jpg')))
print("图片总数为:",image_count)
图片总数为: 1800
batch_size = 16
img_height = 336
img_width  = 336
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)
  1. 首先,tf.keras.preprocessing.image_dataset_from_directory()函数被调用,用于从指定的目录加载图像数据集。

  2. data_dir是包含图像数据的目录路径。该目录应按类别组织,每个类别一个子目录,其中包含对应类别的图像。

  3. validation_split=0.2指定了将数据集划分为训练集和验证集时,验证集应占总数据集的比例为20%。换句话说,80%的数据将用于训练,20%的数据将用于验证。

  4. subset="training"参数用于指定当前正在创建的数据集是训练集。

  5. seed=12参数用于设置随机种子,以确保在不同运行之间生成的随机数相同。这样可以获得可重复的数据集划分结果。

  6. image_size=(img_height, img_width)指定了图像的目标尺寸,即将所有图像调整为相同的高度和宽度。

  7. batch_size=batch_size参数确定每个批次包含的图像数量。

Found 1800 files belonging to 17 classes.
Using 1440 files for training.

 Found 1800 files belonging to 17 classes.
Using 360 files for validation.

class_names = train_ds.class_names
print(class_names)

 ['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']

2、检查数据

from imagr_batch,labels_batch in train_ds:
     print(image_batch.shape)
     print(labels_batch.shape)
     break

3、配置数据集

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)
)

4、数据可视化 

plt.figure(figsize=(10, 8))  # 图形的宽为10高为5
plt.suptitle("数据展示")

for images, labels in train_ds.take(1):
    for i in range(15):
        plt.subplot(4, 5, i + 1)
        plt.xticks([])
        plt.yticks([])
        plt.grid(False)

        # 显示图片
        plt.imshow(images[i])
        # 显示标签
        plt.xlabel(class_names[labels[i]-1])

plt.show()

三、构建模型

from tensorflow.keras.layers import Dropout,Dense,BatchNormalization
from tensorflow.keras.models import Model

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 = False

    X = vgg16_base_model.output
    
    X = 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()
  1. from tensorflow.keras.layers import Dropout, Dense, BatchNormalization导入所需的层类别Dropout、Dense和BatchNormalization。

  2. from tensorflow.keras.models import Model导入模型类别Model。

  3. create_model(optimizer='adam')定义了一个名为create_model的函数,它接受一个参数optimizer,默认值为'adam'。此参数用于指定优化器的类型。

  4. 在函数内部,使用tf.keras.applications.vgg16.VGG16()加载预训练的VGG16模型作为基础模型。通过设置weights='imagenet',使用在ImageNet数据集上预训练的权重。include_top=False表示不包含顶层的全连接层,即只加载卷积部分。input_shape=(img_width, img_height, 3)指定输入图像的尺寸和通道数。pooling='avg'表示在全局平均池化后输出特征向量。

  5. 接下来,将VGG16模型的所有层设置为不可训练,即冻结它们的权重。

  6. 使用vgg16_base_model.output获取VGG16模型的输出张量,然后进行后续的网络构建。

  7. X = Dense(170, activation='relu')(X)添加一个具有170个神经元和ReLU激活函数的全连接层。

  8. X = BatchNormalization()(X)添加批归一化层,用于加速训练过程和提高模型性能。

  9. X = Dropout(0.5)(X)添加一个50%的Dropout层,用于防止过拟合。

  10. output = Dense(len(class_names), activation='softmax')(X)添加一个具有类别数目个神经元和softmax激活函数的全连接层作为最终输出层。

  11. 使用Model(inputs=vgg16_base_model.input, outputs=output)创建一个新的模型对象vgg16_model,指定输入层和输出层。

  12. 使用vgg16_model.compile()配置模型的优化器、损失函数和评价指标。这里使用了sparse_categorical_crossentropy作为损失函数,适用于多分类问题。

  13. return vgg16_model返回创建的vgg16_model模型对象。

  14. model1 = create_model(optimizer=tf.keras.optimizers.Adam())创建一个使用Adam优化器的模型model1。

  15. model2 = create_model(optimizer=tf.keras.optimizers.SGD())创建一个使用SGD优化器的模型model2。

  16. model2.summary()打印出model2模型的摘要信息,显示模型的结构、参数数量等。

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         
_________________________________________________________________
dense_2 (Dense)              (None, 170)               87210     
_________________________________________________________________
batch_normalization_1 (Batch (None, 170)               680       
_________________________________________________________________
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
 

四、训练模型

NO_EPOCHS = 50

history_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)

五、模型评估

1、Accuracy与Loss图


from matplotlib.ticker import MultipleLocator
plt.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()

  1. Adam优化器(Adaptive Moment Estimation): Adam优化器是一种自适应学习率优化算法,结合了AdaGrad和RMSProp的优点。它通过计算梯度的一阶矩估计(均值)和二阶矩估计(方差)来自适应地调整每个参数的学习率。 Adam优化器的主要优点包括:

    • 自动调节学习率:可以根据参数的梯度动态地调节各个参数的学习率。
    • 考虑梯度历史信息:利用一阶和二阶矩估计,更好地估计参数的梯度方向和步长。
    • 适用于大多数问题:在各种类型的深度学习问题中,Adam通常能够提供较好的性能。
  2. SGD优化器(Stochastic Gradient Descent): SGD优化器是最经典的优化算法之一,它在每一次迭代中仅使用部分样本(小批量样本)来计算梯度和更新参数。SGD优化器的更新规则如下:

    • 随机选择一个小批量样本进行前向传播和反向传播,计算模型的损失和梯度。
    • 根据学习率和梯度更新模型参数,使得损失函数最小化。
    • 重复上述步骤,直到达到指定的迭代次数或停止条件。 SGD优化器的主要优点包括:
    • 较低的存储需求:由于每次更新仅使用少量样本,所以占用的内存较少。
    • 可收敛到较好的局部最优解:在某些情况下,SGD可以通过随机性更好地逃离局部最优值并达到较好的全局最优值。

2、评估模型

def test_accuracy_report(model):
    score = model.evaluate(val_ds, verbose=0)
    print('Loss function: %s, accuracy:' % score[0], score[1])
    
test_accuracy_report(model2)

Loss function: 1.4828451871871948, accuracy: 0.5833333134651184

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值