TensorFlow|咖啡豆识别

  • 🍨 本文为🔗365天深度学习训练营中的学习记录博客
  • 🍖 原作者:K同学啊

🍺 要求:

  1. 自己搭建VGG-16网络框架
  2. 调用官方的VGG-16网络框架

🍻 拔高(可选):

  1. 验证集准确率达到100%
  2. 使用PPT画出VGG-16算法框架图(发论文需要这项技能)

🔎 探索(难度有点大)

  1. 在不影响准确率的前提下轻量化模型
    ○ 目前VGG16的Total params是134,276,932

一、前期工作

1. 设置GPU

如果使用的是CPU可以忽略这步

import tensorflow as tfgpus = tf.config.list_physical_devices("GPU")if gpus:tf.config.experimental.set_memory_growth(gpus[0], True)  #设置GPU显存用量按需使用tf.config.set_visible_devices([gpus[0]],"GPU")

2. 导入数据

from tensorflow       import keras
from tensorflow.keras import layers,models
import numpy             as np
import matplotlib.pyplot as plt
import os,PIL,pathlibdata_dir = "C:/Users/76967/.keras/datasets/49-data/"
data_dir = pathlib.Path(data_dir)
image_count = len(list(data_dir.glob('*/*.png')))print("图片总数为:",image_count)

图片总数为: 1200

二、数据预处理

1. 加载数据

使用image_dataset_from_directory方法将磁盘中的数据加载到tf.data.Dataset

batch_size = 32
img_height = 224
img_width = 224

"""
关于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=123,image_size=(img_height, img_width),batch_size=batch_size)

Found 1200 files belonging to 4 classes.
Using 960 files for training.

这段代码使用了 TensorFlow 的 image_dataset_from_directory() 函数来从指定的目录中加载图像数据,并将其转换为一个适合模型训练的数据集。这一步的目的和作用主要包括以下几点:

1. 从文件夹中加载图像数据

image_dataset_from_directory() 会从指定的 data_dir 目录中自动读取图像文件。它会根据文件夹结构将每个子文件夹视为一个类(例如,每个文件夹对应一个标签),并且从每个文件夹中加载图像数据。每张图像会被自动标记为该子文件夹的标签。

2. 数据集划分(训练集和验证集)

validation_split=0.2 参数指定将数据集的 20% 用于验证(用于模型训练过程中进行验证),剩余的 80% 用于训练。通过这种方式,image_dataset_from_directory() 可以自动将数据集分成训练集和验证集。

subset="training" 参数指示当前数据集是训练集。另一个常用的 subset="validation" 用于指定验证集。

3. 随机种子控制数据分割

seed=123 设置了一个随机种子,以确保数据划分的可重复性。如果没有指定种子,每次执行时数据集的划分可能会不同,设置种子保证每次运行时数据集划分的一致性。

4. 调整图像尺寸

image_size=(img_height, img_width) 参数指定了加载的图像的尺寸(即缩放后的目标尺寸)。通常,神经网络输入需要统一的尺寸image_size 参数用来将所有图像调整为指定的大小。

5. 设置批次大小

batch_size=batch_size 用于指定每个批次的样本数量。神经网络训练时,数据通常会被分成多个小批次进行训练。较大的批次有时可以加速训练,但会增加内存使用。批次大小的选择取决于硬件资源和训练数据的特性。

总结

此步骤的目的是:

  • 加载图像数据并将其转换为 TensorFlow 可处理的格式。
  • 自动从文件夹结构中提取标签(类别)。
  • 将数据划分为训练集和验证集。
  • 调整图像尺寸,使其符合网络输入要求。
  • 设置批次大小以便进行高效训练。

通过这一操作,你可以方便地将数据集加载并进行必要的预处理,直接用于模型训练和验证。

"""
关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
"""
val_ds = tf.keras.preprocessing.image_dataset_from_directory(data_dir,validation_split=0.2,subset="validation",seed=123,image_size=(img_height, img_width),batch_size=batch_size)

Found 1200 files belonging to 4 classes.
Using 240 files for validation.

我们可以通过class_names输出数据集的标签。标签将按字母顺序对应于目录名称

class_names = train_ds.class_names
print(class_names)

['Dark', 'Green', 'Light', 'Medium']

2. 可视化数据

plt.figure(figsize=(10, 4))  # 图形的宽为10高为5for images, labels in train_ds.take(1):for i in range(10):ax = plt.subplot(2, 5, i + 1)  plt.imshow(images[i].numpy().astype("uint8"))plt.title(class_names[labels[i]])plt.axis("off")

这段代码的目的是在 Python 中使用 matplotlib 库展示图像,并给每张图像加上对应的标题。

代码解析:

  1. plt.imshow(images[i].numpy().astype("uint8"))

    • images[i]:这是从数据集中获取的第 i 张图像。假设 images 是一个张量(Tensor),这一步的作用是提取第 i 张图像数据。
    • .numpy():将 TensorFlow 张量转换为 NumPy 数组。TensorFlow 张量是高效的计算对象,但为了使用 matplotlib 来展示图像,通常需要将其转换为 NumPy 数组。
    • .astype("uint8"):将图像数据类型转换为 uint8(8位无符号整数),因为图像的像素值通常是 0 到 255 之间的整数,适合用 uint8 类型表示。
  2. plt.title(class_names[labels[i]])

    • labels[i]:这是图像的标签,通常是一个整数,表示图像所属的类别。假设 labels 是一个包含类别标签的列表或张量,这一步就是获取第 i 张图像的标签。
    • class_names[labels[i]]class_names 是一个类别名称的列表或数组,其中的元素是类别的名称或描述。labels[i] 提供了该图像对应类别的索引,class_names[labels[i]] 会返回这个类别对应的名称。
    • plt.title():设置图像的标题为该图像的类别名称。

目的:

这段代码的目的是:

  • 显示图像:通过 plt.imshow() 来显示 images[i] 这张图像。
  • 设置标题:通过 plt.title() 为每张图像设置一个标题,标题显示的是该图像所属的类别名称(通过 class_names[labels[i]] 获取)。

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

(32, 224, 224, 3)
(32,)

3. 配置数据集

  • shuffle() :打乱数据,关于此函数的详细介绍可以参考:https://zhuanlan.zhihu.com/p/42417456
  • prefetch() :预取数据,加速运行,其详细介绍可以参考我前两篇文章,里面都有讲解。
  • cache() :将数据集缓存到内存当中,加速运行

AUTOTUNE = tf.data.AUTOTUNEtrain_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds   = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
normalization_layer = layers.experimental.preprocessing.Rescaling(1./255)train_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
val_ds   = val_ds.map(lambda x, y: (normalization_layer(x), y))
image_batch, labels_batch = next(iter(val_ds))
first_image = image_batch[0]# 查看归一化后的数据
print(np.min(first_image), np.max(first_image))

0.0 1.0

 优化数据加载

AUTOTUNE = tf.data.AUTOTUNEtrain_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds   = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

这段代码的目的是通过 TensorFlowtf.data API 来优化数据加载过程,使训练和验证数据集的加载更高效。让我们逐行分析这些操作:

1. AUTOTUNE = tf.data.AUTOTUNE

  • AUTOTUNE 是一个 TensorFlow 的常量,表示自动调优。AUTOTUNE 会让 TensorFlow 自动选择最合适的预取(prefetch)缓冲区大小。这可以根据系统的资源和硬件动态调整,以优化性能,通常是在数据加载时利用 CPU 和 GPU 的并行处理能力。
  • 在后续代码中,我们使用 AUTOTUNE 来优化数据预处理。

2. train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)

  • train_ds.cache()

    • cache() 方法会将数据集加载到内存中。如果数据集能适应内存,缓存可以加速数据加载过程,因为这样 TensorFlow 就不需要每次从磁盘重新读取数据。

    • 这对于训练集来说尤为重要,因为数据集通常会被多次重复读取,缓存能显著提高速度。

  • train_ds.shuffle(1000)

    • shuffle(buffer_size=1000) 会对训练数据进行随机打乱,buffer_size 参数控制打乱时使用的缓冲区大小。1000 表示将从数据集中随机选取 1000 个样本进行打乱。

    • 这样可以防止模型看到数据的顺序,从而提高模型的泛化能力。

  • train_ds.prefetch(buffer_size=AUTOTUNE)

    • prefetch() 方法会提前加载数据到内存中,以减少训练过程中的等待时间。指定 buffer_size=AUTOTUNE 让 TensorFlow 自动选择最适合的预取缓冲区大小。

    • 通过预取数据,模型在进行一次训练时能够同时准备下一批次的数据,从而提高训练效率。

目的和总结:

  • cache():将数据集缓存到内存中,避免每次读取时都从磁盘加载。
  • shuffle():对训练数据进行随机打乱,避免模型过拟合于数据的顺序。
  • prefetch():提前加载数据,确保训练过程中的数据加载与模型训练并行进行,减少等待时间。

这些优化操作的目的是提升数据加载和处理的效率,尤其是在处理大规模数据集时,能够显著缩短训练时间并提高模型的训练速度。

 归一化

normalization_layer = layers.experimental.preprocessing.Rescaling(1./255)train_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
val_ds   = val_ds.map(lambda x, y: (normalization_layer(x), y))

这段代码的目的是对训练集和验证集的数据进行 归一化 处理,使得图像的像素值位于 [0, 1] 的范围内,以便在训练过程中提高模型的稳定性和收敛速度。归一化是神经网络训练中的一个常见步骤,尤其是对于图像数据。让我们逐步分析这段代码:

1. normalization_layer = layers.experimental.preprocessing.Rescaling(1./255)

  • layers.experimental.preprocessing.Rescaling(1./255) 创建了一个归一化层,它将输入的像素值除以 255,缩放到 [0, 1] 的范围。图像的原始像素值通常是整数,范围在 [0, 255] 之间。通过将每个像素除以 255,得到的是一个浮动范围为 [0.0, 1.0] 的值。这样的归一化可以帮助神经网络更快收敛,尤其是当使用基于梯度的优化算法时,归一化能提高训练的效率和稳定性。

2. train_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))

  • train_ds.map()tf.data API 中的一个方法,它将指定的操作应用到数据集的每个元素。

  • lambda x, y: (normalization_layer(x), y):这里的 xy 分别代表图像和对应的标签。在这个 lambda 函数中:

    • normalization_layer(x):对每张图像 x 应用归一化操作,将其像素值缩放到 [0, 1] 范围。

    • y:图像的标签不需要改变,因此它直接传递给输出。

    这个操作会对整个训练集中的每张图像应用归一化处理,但保持标签不变。

3. val_ds = val_ds.map(lambda x, y: (normalization_layer(x), y))

  • 对验证集 val_ds 执行类似的操作。验证集中的图像同样需要归一化,以确保模型在训练和验证时处理一致的数据。

  • lambda x, y: (normalization_layer(x), y) 对每张图像进行归一化,并保持标签不变。

为什么需要归一化?

  • 提升训练稳定性:图像的原始像素值范围通常是 [0, 255],这样的数值可能导致模型在训练过程中梯度变化剧烈,难以收敛。通过将像素值缩放到 [0, 1],可以使得数据在一个更适合神经网络的范围内。

  • 加速收敛:当输入特征的尺度一致时,神经网络的训练过程通常会更加平稳,梯度下降方法的收敛速度也会更快。大多数优化算法(例如 Adam、SGD)都假设输入特征的值处于较小范围内。

总结:

  • Rescaling(1./255) 将图像像素值从 [0, 255] 范围缩放到 [0, 1]

  • 通过 map() 方法,对训练集和验证集的每张图像应用归一化操作,而标签 y 不变。

这个步骤是数据预处理的一部分,目的是为神经网络提供一个标准化的输入,帮助模型更快、更稳定地训练。

三、构建VGG-16网络

在官方模型与自建模型之间进行二选一就可以了,选着一个注释掉另外一个。

VGG优缺点分析:

  • VGG优点

VGG的结构非常简洁,整个网络都使用了同样大小的卷积核尺寸(3x3)和最大池化尺寸(2x2)

  • VGG缺点

1)训练时间过长,调参难度大。2)需要的存储容量大,不利于部署。例如存储VGG-16权重值文件的大小为500多MB,不利于安装到嵌入式系统中。

1. 官方模型

官网模型调用这块我放到后面几篇文章中,下面主要讲一下VGG-16

# model = tf.keras.applications.VGG16(weights='imagenet')
# model.summary()

2. 自建模型

from tensorflow.keras import layers, models, Input
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropoutdef VGG16(nb_classes, input_shape):input_tensor = Input(shape=input_shape)# 1st blockx = Conv2D(64, (3,3), activation='relu', padding='same',name='block1_conv1')(input_tensor)x = Conv2D(64, (3,3), activation='relu', padding='same',name='block1_conv2')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block1_pool')(x)# 2nd blockx = Conv2D(128, (3,3), activation='relu', padding='same',name='block2_conv1')(x)x = Conv2D(128, (3,3), activation='relu', padding='same',name='block2_conv2')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block2_pool')(x)# 3rd blockx = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv1')(x)x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv2')(x)x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv3')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block3_pool')(x)# 4th blockx = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv1')(x)x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv2')(x)x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv3')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block4_pool')(x)# 5th blockx = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv1')(x)x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv2')(x)x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv3')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block5_pool')(x)# full connectionx = Flatten()(x)x = Dense(4096, activation='relu',  name='fc1')(x)x = Dense(4096, activation='relu', name='fc2')(x)output_tensor = Dense(nb_classes, activation='softmax', name='predictions')(x)model = Model(input_tensor, output_tensor)return modelmodel=VGG16(len(class_names), (img_width, img_height, 3))
model.summary()

3. 网络结构图

关于卷积的相关知识可以参考文章:卷积的计算_卷积核2x2-CSDN博客文章浏览阅读3.7k次,点赞5次,收藏21次。1. 卷积4×44×44×4 的输入矩阵 III 和 3 × 3 的卷积核 KKK:在步长(stride)为 1 时,输出的大小为 ( 4 − 3 + 1 ) × ( 4 − 3 + 1 )计算公式:输入图片矩阵 III 大小: w×ww × ww×w卷积核 KKK:k×kk × kk×k步长SSS:sss填充大小(padding):pppo=(w−k+2p)s+1o = \frac{(w − k + 2p )}{s}+1o=s(w−k+2p)​+1输出图片大小为:o×oo × ._卷积核2x2https://mtyjkh.blog.csdn.net/article/details/114278995

结构说明:

  • 13个卷积层(Convolutional Layer),分别用blockX_convX表示
  • 3个全连接层(Fully connected Layer),分别用fcXpredictions表示
  • 5个池化层(Pool layer),分别用blockX_pool表示

VGG-16包含了16个隐藏层(13个卷积层和3个全连接层),故称为VGG-16

四、编译

在准备对模型进行训练之前,还需要再对其进行一些设置。以下内容是在模型的编译步骤中添加的:

  • 损失函数(loss):用于衡量模型在训练期间的准确率。
  • 优化器(optimizer):决定模型如何根据其看到的数据和自身的损失函数进行更新。
  • 指标(metrics):用于监控训练和测试步骤。以下示例使用了准确率,即被正确分类的图像的比率。
# 设置初始学习率
initial_learning_rate = 1e-4lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(initial_learning_rate, decay_steps=30,      # 敲黑板!!!这里是指 steps,不是指epochsdecay_rate=0.92,     # lr经过一次衰减就会变成 decay_rate*lrstaircase=True)# 设置优化器
opt = tf.keras.optimizers.Adam(learning_rate=initial_learning_rate)model.compile(optimizer=opt,loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),metrics=['accuracy'])

SparseCategoricalCrossentropy函数注意事项:

from_logits参数:

  • 布尔值,默认值为 False
  • 当为 True 时,函数假设传入的预测值是未经过激活函数处理的原始 logits 值。如果模型的最后一层没有使用 softmax 激活函数(即返回 logits),需要将 from_logits 设置为 True
  • 当为 False 时,函数假设传入的预测值已经是经过 softmax 处理的概率分布。

这段代码主要涉及了设置 学习率调度器优化器,然后将它们应用到模型编译过程中。以下是详细的解析:

1. 设置初始学习率

 

initial_learning_rate = 1e-4

  • initial_learning_rate = 1e-4 设置了优化器的初始学习率为 0.0001。学习率是控制每一步优化过程中参数更新幅度的超参数,较小的学习率有助于细致调整参数,但可能会导致收敛速度较慢。

2. 学习率调度器(ExponentialDecay)

 

lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay( initial_learning_rate, decay_steps=30, # 这里是指 steps,不是指 epochs decay_rate=0.92, # lr经过一次衰减就会变成 decay_rate*lr staircase=True)

  • ExponentialDecay:这是 TensorFlow 中的一种学习率衰减方式。学习率会随着训练步数的增加而按指数衰减。每经过一定的步数,学习率都会乘以一个衰减因子(decay_rate)。这个调度器的作用是随着训练进程逐渐减小学习率,避免训练后期学习率过大导致跳跃性更新,帮助网络收敛。

  • initial_learning_rate:初始学习率,设定为 1e-4

  • decay_steps=30:这表示学习率每隔 30 个训练步骤(steps)就会进行一次衰减。注意,decay_steps 这里是按照步骤(steps)来计算的,而不是按照训练轮次(epochs)。如果你使用的是批量训练,则 decay_steps 与每个批次的训练步骤数量有关。

  • decay_rate=0.92:这表示每经过 decay_steps 步,学习率会乘以 0.92,即衰减到原来的 92%。所以,如果初始学习率是 1e-4,经过 30 个步骤后,新的学习率将变为 1e-4 * 0.92

  • staircase=True:这表示学习率的衰减是阶梯型的,即每 decay_steps 步,学习率突然减小为原来的 decay_rate 倍,而不是平滑的指数衰减。如果设置为 False,则学习率会平滑地下降。

3. 设置优化器

 

opt = tf.keras.optimizers.Adam(learning_rate=initial_learning_rate)

  • Adam:这里选择了 Adam 优化器,Adam 是一种自适应学习率的优化算法,它结合了 MomentumRMSProp 的优点,能够根据不同参数的梯度调整学习率。Adam 是最常用的深度学习优化器之一,适用于大部分问题。

  • learning_rate=initial_learning_rate:这里初始化时传入的学习率是 1e-4,但接下来通过学习率调度器 lr_schedule 来调整学习率。

4. 编译模型

 

model.compile(optimizer=opt, loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False), metrics=['accuracy'])

  • optimizer=opt:在这里,将 Adam 优化器(带有学习率调度器)传递给 compile 方法。

  • loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False)

    • SparseCategoricalCrossentropy 是一种常用于分类任务的损失函数。它适用于处理整数标签(不是 one-hot 编码标签)。如果 from_logits=True,则表示模型输出的是未经 softmax 激活的 logits;如果 from_logits=False,表示模型输出的是经过 softmax 激活的概率分布。
    • 这里选择 from_logits=False,假设你的模型输出已经是经过 softmax 归一化的概率。
  • metrics=['accuracy']:指定训练和评估时使用准确度作为衡量指标。

总结

这段代码完成了以下几个任务:

  1. 设置学习率调度:通过 ExponentialDecay 调度器,使得学习率随训练步数逐渐衰减,以便在训练过程中提高模型的稳定性和收敛效果。
  2. 选择优化器:使用 Adam 优化器,并结合学习率调度器。
  3. 编译模型:使用 SparseCategoricalCrossentropy 作为损失函数,并监控训练过程中的准确度。

这样,模型在训练过程中会根据每 30 步调整一次学习率,帮助模型更好地收敛。

学习率有啥用

学习率(Learning Rate)是训练深度学习模型时的一个超参数,它控制着每次参数更新的步长,即每次迭代中模型的权重调整幅度。学习率的大小直接影响到模型的训练效果和速度,因此选择合适的学习率对于成功训练模型至关重要。

学习率的作用
  1. 控制模型权重更新的幅度

    • 学习率决定了每次梯度更新时,模型参数(如权重和偏置)改变的幅度。如果学习率太大,可能会导致每次更新的步伐过大,错过最优解,甚至可能导致训练过程中出现震荡或发散(损失函数不收敛)。
    • 如果学习率太小,模型每次更新的步伐过小,可能导致训练过程非常缓慢,甚至无法在合理的时间内收敛到较好的解。
  2. 影响模型的收敛速度

    • 学习率对模型的收敛速度有很大影响。如果学习率合适,模型能较快地找到损失函数的最小值;如果学习率太小,收敛速度会非常慢,训练时间会变得非常长。
    • 但如果学习率过大,模型可能会错过最优解,甚至无法收敛。
  3. 优化的稳定性

    • 在训练过程中,学习率过大可能导致优化过程不稳定,模型的损失值可能在优化过程中震荡,甚至增加,无法收敛到最优解。
    • 适当的学习率能够使得优化过程稳定,最终收敛到一个较好的最优解。
  4. 影响局部最小值的跳跃能力

    • 选择较大的学习率可能会使模型跳过局部最小值,找到全局最优解。然而,过大的学习率可能使得模型在全局最优解附近震荡,无法收敛。
    • 较小的学习率有助于细致的调整,但容易在局部最小值处停滞,导致模型无法进一步优化。
学习率的调度

在训练深度学习模型时,通常会采用 学习率调度(Learning Rate Scheduling)技术,随着训练的进行动态调整学习率。这种方法能够提高训练效率、加速收敛并避免过拟合。常见的学习率调度方法有:

  1. 指数衰减(Exponential Decay): 学习率随训练步骤或轮次按指数衰减,通常表现为:

    lrnew=lrinitial×decay_rate(step/decay_steps)\text{lr}_{new} = \text{lr}_{initial} \times \text{decay\_rate}^{(\text{step} / \text{decay\_steps})}lrnew​=lrinitial​×decay_rate(step/decay_steps)

    随着训练进程,学习率逐渐减小,使得训练过程越来越稳定。

  2. 阶梯衰减(Step Decay): 每经过一定数量的训练步骤,学习率会突然下降为原来的某个比例。可以有效地避免过拟合,并让模型更好地收敛。

  3. 循环学习率(Cyclical Learning Rate): 学习率在训练过程中不断循环增大和减小,这种方法能够使模型跳出局部最小值并找到全局最优解。

  4. 自适应学习率(如 Adam、RMSprop 等): 这些优化器会根据梯度的大小和历史信息动态调整每个参数的学习率,使得每个参数的更新步长更加智能和自适应。

学习率的选择
  • 学习率过大
    • 可能导致模型的损失函数值不稳定,甚至无法收敛。
    • 训练过程可能出现震荡(loss波动)或发散(loss增大)。
  • 学习率过小
    • 模型的收敛速度会非常慢,可能需要很长时间才能达到较好的解。
    • 可能会在某些局部最小值处停滞,导致模型无法进一步优化。
实际应用中如何选择学习率
  1. 调参

    • 可以尝试使用 网格搜索(Grid Search)或 随机搜索(Random Search)等方法来测试不同的学习率,并选择最适合的值。
    • 通常从较小的学习率开始,例如 1e-31e-4,然后通过实验逐渐调整。
  2. 学习率热身(Warmup)

    • 在训练的初期,使用较小的学习率,随着训练的进行逐渐增大学习率,然后再开始衰减。这有助于模型稳定地进入训练过程。
  3. 使用学习率调度

    • 如果使用了如 ExponentialDecayReduceLROnPlateau 等调度器,可以让学习率在训练过程中自动调整,以便在训练后期微调模型。
总结
  • 学习率是影响模型训练效果的关键超参数之一,它直接决定了优化过程中参数更新的步长。
  • 选择合适的学习率能够加速模型收敛、提高训练稳定性,并帮助模型达到更好的效果。
  • 通过使用学习率调度器,我们可以在训练过程中动态调整学习率,进一步提升模型的表现和训练效率。

五、训练模型

🔊注:从本周开始,网络越来越复杂,对算力要求也更高,CPU训练模型时间会很长,建议尽可能的使用GPU来跑。

epochs = 20history = model.fit(train_ds,validation_data=val_ds,epochs=epochs
)

六、可视化结果

acc = history.history['accuracy']
val_acc = history.history['val_accuracy']loss = history.history['loss']
val_loss = history.history['val_loss']epochs_range = range(epochs)plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

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

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

相关文章

Jmeter5.X性能测试

Jmeter5.X性能测试 文章目录 Jmeter5.X性能测试一、掌握Http基础协议1.1 浏览器的B/S架构和C/S架构1.2 HyperText Transfer Protocol 超文本传输协议1.3 超文本传输协议Http消息体拆分讲解1.4 HTTP的九种请求方法和响应码介绍1.5 Http请求头/响应头1.6 Http常见请求/响应头cont…

信息安全工程师(81)网络安全测评质量管理与标准

一、网络安全测评质量管理 遵循标准和流程 网络安全测评应严格遵循国家相关标准和流程,确保测评工作的规范性和一致性。这些标准和流程通常包括测评方法、测评步骤、测评指标等,为测评工作提供明确的指导和依据。 选择合格的测评团队 测评团队应具备相关…

AI - 人工智能;Ollama大模型工具;Java之SpringAI(三)

AI - 人工智能;Java之SpringAI(一) AI - 人工智能;Java之SpringAI(二) 一、Ollama 官网:https://ollama.com/ Ollama是一个大模型部署运行工具,在该工具里面可以部署运行各种大模型…

力扣—不同路径(路径问题的动态规划)

文章目录 题目解析算法原理代码实现题目练习 题目解析 算法原理 状态表示 对于这种「路径类」的问题,我们的状态表示⼀般有两种形式: i. 从[i, j] 位置出发。 ii. 从起始位置出发,到[i, j] 位置。 这⾥选择第⼆种定义状态表⽰的⽅式&#xf…

用了Stream后,代码反而越写越丑?

使用 Stream API 可以使代码更加简洁和易读,但如果不恰当地使用或过度使用,确实可能导致代码变得复杂和难以理解。以下是一些常见的问题和改进建议: 常见问题 过度链式调用:过度链式调用 Stream 方法会导致代码行过长&#xff0c…

论文速读:简化目标检测的无源域适应-有效的自我训练策略和性能洞察(ECCV2024)

中文标题:简化目标检测的无源域适应:有效的自我训练策略和性能洞察 原文标题:Simplifying Source-Free Domain Adaptation for Object Detection: Effective Self-Training Strategies and Performance Insights 此篇文章为论文速读&#xff…

FFmpeg 4.3 音视频-多路H265监控录放C++开发十. 多线程控制帧率。循环播放,QT connect 细节,

在前面,我们总结一下前面的代码。 在 FactoryModeForAVFrameShowSDL 构造函数中 init SDL。 通过 QT timerevent机制,通过startTimer(10);每隔10ms,就会调用timerEvent事件。 在timerEvent事件中,真正的去 读取数据&#xff0c…

企业文件加密要怎么做?好用的10款企业文件加密软件排行榜!

在现代信息化的工作环境中,企业数据安全面临着越来越多的威胁。尤其是当涉及到敏感文件和商业机密时,如何保护这些数据不被泄露或遭受恶意攻击显得尤为重要。企业文件加密成为了保护企业信息安全的关键手段。本文将探讨如何进行企业文件加密,…

20241107给野火LubanCat1-BTB刷Ubuntu的预编译固件并点亮USB接口的热像仪AT600

20241107给野火LubanCat1-BTB刷Ubuntu的预编译固件并点亮USB接口的热像仪AT600 2024/11/7 20:08 缘起:需要使用RK3566的linux/Buildroot系统。 将 鲁班猫的 云盘资料下载之后,发现里面没有Buildroot的预编译固件。 火速联系 淘宝客服!转技术支…

VMware没有卸载干净,安装后ping不通

目录 1.问题 2.问题分析 3. 解决办法 🍓 STEP1:卸载VMware 🍈 STEP2:services.msc设置 🍒STEP3:安装everything删除所有与vmware相关的文件 🍑STEP4:使用CCleaner清理修复注册…

【科普】简述机器学习和深度学习及其相关的算法

文章目录 机器学习1. 基本概念2. 机器学习的分类3. 机器学习的常用方法4. 应用领域5. 挑战与未来6. 未来趋势 机器学习算法 深度学习1.深度学习的基本概念2.深度学习的主要架构3.深度学习的应用4.深度学习的挑战 深度学习算法 机器学习 机器学习是人工智能的一个重要分支&…

HCIP--3实验- 链路聚合,VLAN间通讯,Super VLAN,MSTP,VRRPip配置,静态路由,环回,缺省,空接口,NAT

学习目标: 链路聚合VLAN间通讯Super VLANMSTPVRRPip配置,静态路由,环回,缺省,空接口NAT 学习内容: 实验拓扑实验需求实验需求分析实验配置内容 (每一个设备的每一步操作)实验结果验证 1.实验拓扑 搭建 …

Zabbix监控架构

目录 1. Zabbix监控架构-CS架构 2. Zabbix极速上手指南 主机规划 2.1 部署ngxphp环境并测试 检查安装结果 2.2 部署数据库 2.3 编译安装zabbix-server服务端及后续配置 2.4 部署前端代码代码进行访问 前端的配置文件(连接数据库与主机名等信息) 2.5 欢迎来到zabbix 2…

【CentOS】中的Firewalld:全面介绍与实战应用(上)

🐇明明跟你说过:个人主页 🏅个人专栏:《Linux :从菜鸟到飞鸟的逆袭》🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、iptables 时代 2、firewalld 时代 3、 从 ipt…

人工智能未来前景好不好?

人工智能(AI)正以前所未有的速度改变着我们的世界。随着技术的不断进步,AI不仅在各行各业中扮演着越来越重要的角色,也为求职者和职业发展带来了广阔的机会。那么,人工智能未来的前景如何? 1 高增长行业 人…

湘潭大学软件工程专业选修 SOA 期末考试复习(二)

文章目录 回顾序言第一章课后题填空选择简答 第二章课后题填空选择编程 计划第三章课后题填空选择简答编程 第四章课后题填空选择简答编程 第五章课后题填空选择简答编程 第六章课后题说明 第七章课后题填空选择简答编程 第八章课后题填空选择简答编程 第九章课后题填空选择简答…

JVM垃圾回收详解

前言 当需要排查各种内存溢出问题、当垃圾收集成为系统达到更高并发的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节。 堆空间的基本结构 Java 的自动内存管理主要是针对对象内存的回收和对象内存的分配。同时,Java 自动内存管理最核…

Hive 操作基础(进阶篇✌️)

Hive 进阶操作 分区表 创建分区表 create table score_part(字段名 字段类型,字段名 字段类型 )partitioned by (分区字段 分区类型) row format delimited fields terminated by \t; 创建单极分区表 注意: 分区的列名不能和数据列名相同.分区列会当做虚拟列出现在数据列…

【Kafka】Windows+KRaft部署指南

【Kafka】WindowsKRaft部署指南 摘要本地环境说明官网快速开始修改config/kraft/server.properties初始化数据存储目录启动 测试创建topic创建生产者创建消费者 FAQ输入行太长。命令语法不正确。问题描述解决方案 参考资料 摘要 Kafka是一种高吞吐量的分布式发布订阅消息系统&…

Docker-软件容器平台

一、容器 1、什么是容器 容器就是将软件打包成标准化单元,以用于开发、交付和部署 容器镜像是轻量的、可执行的独立软件包 ,包含软件运行所需的所有内容:代码、运行时环境、系统工具、系统库和设置。容器化软件适用于基于 Linux 和 Windows…