扬州建设安装网站,泰州seo外包,如何改变wordpress字体颜色,阿里巴巴上怎样做自己的网站深度学习-第T5周——运动鞋品牌识别 深度学习-第T5周——运动鞋品牌识别一、前言二、我的环境三、前期工作1、导入数据集2、查看图片数目3、查看数据 四、数据预处理1、 加载数据1、设置图片格式2、划分训练集3、划分验证集4、查看标签 2、数据可视化3、检查数据4、配置数据集 … 深度学习-第T5周——运动鞋品牌识别 深度学习-第T5周——运动鞋品牌识别一、前言二、我的环境三、前期工作1、导入数据集2、查看图片数目3、查看数据 四、数据预处理1、 加载数据1、设置图片格式2、划分训练集3、划分验证集4、查看标签 2、数据可视化3、检查数据4、配置数据集 五、搭建CNN网络六、编译七、训练模型八、模型评估1、Loss和Acc图2、指定图片进行预测 九、总结 深度学习-第T5周——运动鞋品牌识别
一、前言 本文为365天深度学习训练营 中的学习记录博客 原作者K同学啊 二、我的环境
电脑系统Windows 10语言环境Python 3.8.5编译器colab在线编译深度学习环境Tensorflow
三、前期工作
1、导入数据集
导入数据集数据集K同学啊 from tensorflow import keras
from tensorflow.keras import layers, models
import os, PIL, pathlib
import matplotlib.pyplot as plt
import tensorflow as tfdata_dir /content/drive/MyDrive/Training_Camp_DL/TensorFlow/CNN/46-data
data_dir pathlib.Path(data_dir)这段代码将字符串类型的 data_dir 转换为了 pathlib.Path 类型的对象。pathlib 是 Python3.4 中新增的模块用于处理文件路径。 通过 Path 对象可以方便地操作文件和目录如创建、删除、移动、复制等。 在这里我们使用 pathlib.Path() 函数将 data_dir 转换为路径对象这样可以更加方便地进行文件路径的操作和读写等操作。
2、查看图片数目
image_count len(list(data_dir.glob(*/*/*.jpg)))print(图片总数为 ,image_count)
获取指定目录下所有子文件夹中 jpg 格式的文件数量并将其存储在变量 image_count 中。
具体来说data_dir 是一个路径变量表示需要计算的目标文件夹的路径。glob() 方法可以返回匹配指定模式通配符的文件列表该方法的参数 “/.jpg” 表示匹配所有子文件夹下以 .jpg 结尾的文件。
list() 方法将 glob() 方法返回的生成器转换为列表方便进行数量统计。最后len() 方法计算列表中元素的数量就得到了指定目录下 jpg 格式文件的总数。
所以这行代码的作用就是计算指定目录下 jpg 格式文件的数量。
3、查看数据
roses list(data_dir.glob(train/nike/*.jpg))
PIL.Image.open(str(roses[0]))在第一行代码中glob() 方法匹配了 data_dir 目录下位于 train/nike/ 子目录中所有后缀名为 .jpg 的文件并将其转换为一个 pathlib.Path 对象列表。 因此 roses 列表中包含了符合条件的所有文件路径。需要注意的是这里只是选取了 nike 子目录下的所有 .jpg 文件。
接下来我们使用 PIL.Image.open() 函数打开了列表中的第一张图片即 roses[0]。str() 函数将 pathlib.Path 对象转换为字符串类型的路径使其能够被 PIL.Image.open() 正确解析。
最终PIL.Image.open(str(roses[0])) 返回的是一个 PIL.Image.Image 类型的对象代表了打开的图片。可以使用该对象进行后续处理如调整大小、裁剪、旋转等操作。
四、数据预处理
1、 加载数据
1、设置图片格式
batch_size 32
img_height 224
img_width 2242、划分训练集
train_ds tf.keras.preprocessing.image_dataset_from_directory(D:/DL_Camp/CNN/T5/46-data,seed 123,image_size (img_height, img_width),batch_size batch_size)这行代码使用 TensorFlow 读取指定路径下的图片文件并生成一个 tf.data.Dataset 对象用于模型的训练和评估。
具体来说tf.keras.preprocessing.image_dataset_from_directory() 函数从指定目录中读取图像数据并自动对其进行标准化和预处理。该函数有以下参数
directory指定图像文件所在目录的路径 seed用于随机划分数据集的种子 image_size指定图像缩放后的尺寸 batch_size指定批次中图像的数量。 通过这些参数函数将指定目录中的图像按照指定大小预处理后随机划分为训练集和验证集。最终生成的 tf.data.Dataset 对象包含了划分好的数据集可以用于后续的模型训练和验证。
需要注意的是这里的 img_height 和 img_width 变量应该提前定义并且应该与实际图像的尺寸相对应。同时batch_size 也应该根据硬件设备的性能合理调整以充分利用 GPU/CPU 的计算资源。
3、划分验证集
val_ds tf.keras.preprocessing.image_dataset_from_directory(D:/DL_Camp/CNN/T5/46-data,seed 123,image_size (img_height, img_width),batch_size batch_size
)
这段代码和上一段代码类似使用 TensorFlow 的 keras.preprocessing.image_dataset_from_directory() 函数从指定的目录中读取图像数据集并将其划分为训练集和验证集。
其中data_dir 指定数据集目录的路径validation_split 表示从数据集中划分出多少比例的数据作为验证集subset 参数指定为 “validation” 则表示从数据集的 20% 中选择作为验证集其余 80% 作为训练集。seed 是一个随机种子用于生成可重复的随机数。image_size 参数指定输出图像的大小batch_size 表示每批次加载的图像数量。
该函数返回一个 tf.data.Dataset 对象代表了整个数据集包含训练集和验证集。可以使用 train_ds 和 val_ds 两个对象分别表示训练集和验证集。
不过两段代码的 subset 参数值不同一个是 “training”一个是 “validation”。
因此在含有交叉验证或者验证集的深度学习训练过程中需要定义两个数据集对象 train_ds 和 val_ds。我们已经定义了包含训练集和验证集的数据集对象 train_ds可以省略这段代码无需重复定义 val_ds 对象。只要确保最终的训练过程中两个数据集对象都能够被正确地使用即可。
如果你没有定义 val_ds 对象可以使用这段代码来创建一个验证数据集对象用于模型训练和评估从而提高模型性能。
4、查看标签
class_names train_ds.class_names
class_namestrain_ds.class_names 是一个属性它是通过数据集对象 train_ds 中的类别信息自动生成的一个包含类别名称的列表。
在创建数据集对象 train_ds 时你可以通过 class_names 参数手动指定类别名称也可以根据图像文件夹的目录结构自动推断出来。 例如假设你有一个包含猫和狗两种类别的图像数据集其中猫类别的图像存储在 “cat” 文件夹中狗类别的图像存储在 “dog” 文件夹中 那么当你使用 keras.preprocessing.image_dataset_from_directory() 函数加载数据集时会自动将 “cat” 和 “dog” 文件夹作为两个不同的类别 并将它们的名称存储在 train_ds.class_names 属性中。
执行该代码后你就可以在控制台或者输出窗口中看到包含数据集中所有类别名称的列表。这些名称通常是按照字母顺序排列的
因此train_ds.class_names 属性可以让你方便地查看数据集中所有的类别名称以便后续的模型训练、预测和评估等任务。 如果你要对数据集进行多类别分类则需要根据 train_ds.class_names 的元素个数设置输出层的神经元数量并将每个类别与一个唯一的整数标签相关联。
2、数据可视化
plt.figure(figsize (20, 10))for images, labels in train_ds.take(1):for i in range(20):plt.subplot(5, 10, i 1)plt.imshow(images[i].numpy().astype(uint8))plt.title(class_names[labels[i]])plt.axis(off)train_ds.take(1) 是一个方法调用它返回一个数据集对象 train_ds 中的子集其中包含了 take() 方法参数指定的数量的样本。 在这个例子中take(1) 意味着我们从 train_ds 数据集中获取一批包含一个样本的数据块。
因此for images, labels in train_ds.take(1): 的作用是遍历这个包含一个样本的数据块并将其中的图像张量和标签张量依次赋值给变量 images 和 labels。具体来说 它的执行过程如下
从 train_ds 数据集中获取一批大小为 1 的数据块。 遍历这个数据块每次获取一个图像张量和一个标签张量。 将当前图像张量赋值给变量 images将当前标签张量赋值给变量 labels。 执行 for 循环中的代码块即对当前图像张量和标签张量进行处理。
plt.imshow() 函数是 Matplotlib 库中用于显示图像的函数它接受一个数组或张量作为输入并在窗口中显示对应的图像。 在这个代码中images[i] 表示从训练集中获取的第 i 个图像张量。由于 images 是一个包含多个图像的张量列表因此使用 images[i] 可以获取其中的一个图像。
由于 imshow() 函数需要输入的数组或张量的类型是整型或浮点型而从数据集中获取的图像张量通常是浮点型张量因此需要将其转换为整型张量以便进行显示。 这里使用了 .numpy().astype(“uint8”) 操作来将图像张量转换为整型张量uint8 表示无符号8位整数然后将结果传递给 plt.imshow() 函数进行显示。
因此plt.imshow(images[i].numpy().astype(“uint8”)) 的作用是在 Matplotlib 窗口中显示训练集中的第 i 个图像。 你可以通过改变 i 的值来显示不同的图像例如 i 0 表示显示训练集中的第一张图像。
plt.axis(“off”) 是 Matplotlib 库中的一个函数调用它用于控制图像显示时的坐标轴是否可见。 具体来说当参数为 “off” 时图像的坐标轴会被关闭不会显示在图像周围。这个函数通常在 plt.imshow() 函数之后调用以便在显示图像时去掉多余的细节信息仅仅显示图像本身。 3、检查数据
for image_batch, labels_batch in train_ds:print(image_batch.shape)print(labels_batch.shape)break4、配置数据集
AUTOTUNE tf.data.AUTOTUNEtrain_ds train_ds.cache().shuffle(1000).prefetch(buffer_size AUTOTUNE)
val_ds val_ds.cache().prefetch(buffer_size AUTOTUNE)AUTOTUNE 是 TensorFlow 的一个常量它的值取决于当前硬件配置和运行环境。 它表示 TensorFlow 数据处理流程中可以自动选择最优化参数例如 GPU 处理数量等的范围在不同的硬件配置下可能会有不同的取值。 在这个代码片段中AUTOTUNE 的作用是为数据集的预处理过程提供了一个启发式的缓冲大小以便更好地平衡内存使用和计算速度。
train_ds.cache() 和 val_ds.cache() 函数是 Tensorflow 的数据转换函数它们的作用是将数据集中的元素缓存到内存或者磁盘中以便后续访问时能够更快地读取数据。 使用缓存可以避免由于磁盘 I/O 等因素导致数据读取速度变慢的问题从而加速训练或评估过程。
train_ds.shuffle(1000) 函数是 Tensorflow 的数据转换函数它的作用是将输入数据集中的元素随机打乱顺序。 这样做的目的是防止模型过拟合并促进模型对不同数据的学习能力。其中1000 表示用于对数据集进行重排的元素数量其具体取值可以根据数据集大小进行调整。
train_ds.prefetch(buffer_size AUTOTUNE) 和 val_ds.prefetch(buffer_size AUTOTUNE) 函数是 Tensorflow 的数据转换函数 它们的作用是将输入数据集中的元素通过 AUTOTUNE 参数定义的缓冲大小进行预加载。 具体来说这个函数可以在当前训练或评估任务执行期间异步读取和处理数据集中的下一批样本从而减少模型训练或评估过程中的等待时间和延迟。
因此这段代码的作用是对训练集和验证集进行预处理并将它们缓存到内存或磁盘中以便更快地访问数据。 然后它对训练集进行了一次随机打乱操作并将缓存结果设为可以提前预加载的形式以便在训练时能够快速地读取和处理数据。 最后它将缓存结果也设置为可以提前预加载的形式以加速评估过程。
五、搭建CNN网络
num_classes 2model models.Sequential([layers.experimental.preprocessing.Rescaling(1. / 255, input_shape (img_height, img_width, 3)),layers.Conv2D(16, (3, 3), activation relu, input_shape (img_height, img_width, 3)),layers.AveragePooling2D((2, 2)),layers.Conv2D(32, (3, 3), activation relu),layers.AveragePooling2D((2, 2)),layers.Dropout(0.1),layers.Conv2D(64, (3, 3), activation relu),layers.Dropout(0.1),layers.Flatten(),layers.Dense(128, activation relu),layers.Dense(num_classes)
])model.summary()layers.experimental.preprocessing.Rescaling(1./255, input_shape(img_height, img_width, 3)) 是 TensorFlow 中的一个预处理层 用于将图像数据缩放至 [0, 1] 范围内在神经网络的训练过程中稳定模型训练过程。
在这个代码片段中1./255 表示将输入数据除以 255这样就把原来范围在 [0, 255] 的像素值缩放到 [0, 1] 的范围内。 这个操作可以使得神经网络的输入数据归一化从而更好地适应不同的计算机视觉任务例如图像分类、目标检测、语义分割等。
input_shape(img_height, img_width, 3) 参数表示输入图像的形状其中 img_height 和 img_width 分别表示图像的高度和宽度而 3 表示通道数。 由于这个预处理层是作为神经网络模型的第一层使用的因此需要指定输入数据的形状。
因此这行代码的作用是将输入图像的像素值除以 255从而将像素范围缩放到 [0, 1]并将其作为神经网络模型的第一层 以便在训练过程中更好地归一化输入数据并提高模型的鲁棒性和泛化性能。 六、编译
model.summary()initial_learning_rate 1e-4lr_schedule tf.keras.optimizers.schedules.ExponentialDecay(initial_learning_rate,decay_steps 30,decay_rate 0.92,staircase True
)optimizer tf.keras.optimizers.Adam(learning_rate lr_schedule)model.compile(optimizer optimizer,loss tf.keras.losses.SparseCategoricalCrossentropy(from_logits True),metrics [accuracy] )lr_schedule 是一个学习率的调度器它是基于指数衰减方法来自动调整学习率的。在深度学习中学习率是一个非常重要的超参数它会影响模型的性能和训练速度。
这个调度器包含四个参数。initial_learning_rate 为初始学习率一开始通常需要较大的学习率以便更快地进行收敛然后逐步减小以提高训练效果。 decay_steps 是衰减步数指定了多少次更新后进行学习率衰减。 这里设置成30防止学习率衰减过快。decay_rate 是衰减速率决定每一次衰减后学习率的大小。 通过以上两个参数可以控制学习率的下降速度和幅度。staircase 参数则表示是否对步数取整如果设置为 True则表示将步数向下取整。
这个调度器的计算公式为 decayed_learning_rate initial_learning_rate * decay_rate ^ (step / decay_steps)
其中 step 表示当前训练步数。通过指数函数的方式学习率会随着训练步数的增加而不断降低。 这种调度器的优点在于它可以在训练初期使用较大的学习率以便快速接近最优解而在后期则可以逐渐降低学习率以更精细的调整模型参数。
在上述代码段中我们使用了初始学习率为 initial_learning_rate衰减步数为 30衰减速率为 0.92 的指数衰减策略来更新模型的学习率。 这种学习率调度器是一种常见的方法在实践中通常可以通过尝试不同的参数设置来确定最佳的学习率调度策略。
SparseCategoricalCrossentropy 是一种常用的损失函数通常用于多分类问题。 它的输入是模型输出结果经过 softmax 处理后得到的概率分布和真实的分类标签输出是一个标量值表示模型在当前数据上的损失值。
其中 from_logitsTrue 表示输入的模型输出结果是没有进行 softmax 处理的 logits这种设置可以提高计算效率并且对于梯度计算也更加稳定。
具体地SparseCategoricalCrossentropy 的计算公式为
loss -Σ[y * log(y_hat)] 其中 y 是真实的分类标签y_hat 是模型在该分类下的预测概率分布log 是自然对数。通过最小化损失函数模型可以调整参数以提高预测准确率并不断逼近真实结果
七、训练模型
from tensorflow.keras.callbacks import ModelCheckpointepochs 50checkpointer ModelCheckpoint(best_model.h5,monitor val_accuracy,verbose 1,save_best_only True,save_weights_only True
)
ModelCheckpoint 是 Keras 中的一个回调函数Callback用于在训练过程中保存模型的权重。 具体来说对于每一轮训练后该回调函数都可以按照一定的条件将这一轮训练得到的最佳模型权重保存下来。
使用 ModelCheckpoint 可以避免在训练过程中出现意外情况导致模型信息的丢失同时也可以方便地对比不同阶段训练得到的模型效果进行模型的选择和调整。
具体来说这段代码中的参数设置如下
best_model.h5保存模型权重的文件路径和名称。 monitor‘val_accuracy’表示在验证集上监测模型的准确率并作为指标以便在每个 epoch 结束时评估模型效果。当发现模型在验证集上的准确率有提高时就会保存当前的模型权重。 verbose1表示每个 epoch 结束时在控制台输出一条信息说明模型权重是否被更新了。 save_best_onlyTrue表示只有在模型效果提高时才保存模型权重。如果设为 False则每个 epoch 结束后都会保存模型权重不管模型效果是否提高。 save_weights_onlyTrue表示只保存模型的权重而不保存模型的结构和配置信息。这样可以方便地加载已经训练好的模型权重并重新构建模型。 综合起来这段代码的作用是在训练过程中不断保存最佳的模型权重以便后续的模型加载和使用。
earlystopper EarlyStopping(monitor val_accuracy,min_delta 0.001,patience 20,verbose 1
)earlystopper 是一个早期停止器用于在训练过程中监控模型的表现并在满足终止条件时提前结束训练。它是 tensorflow.keras.callbacks.EarlyStopping 类的一个实例对象。
在深度学习中由于模型参数非常多训练时间可能会很长。而对于一些问题模型可能已经学习到了足够好的特征此时继续训练只会导致过拟合或者浪费计算资源。 为了避免这种情况的发生我们可以通过早期停止器来控制模型的训练过程。
通过 EarlyStopping我们可以设置一些参数来指定如何判断模型是否应该停止训练并在满足条件时终止训练。其中monitor ‘val_accuracy’ 表示监控模型在验证集上的准确率 min_delta 0.001 表示设置检测指标的最小变化量如果变化量小于该值则认为模型已经不再进步可以终止训练。patience 20 表示设置容忍指标在多少个 epoch 中没有进步 如果超过该次数则终止训练。verbose 1 表示在控制台打印提示信息。
当早期停止器被激活时它会自动停止训练同时保留模型在最后一个 epoch 的参数。这个参数可以用于进一步的预测和测试任务。在具体实践中我们可以根据问题和数据集的特点 合理地设置早期停止器的参数从而获得更好的训练效果。
history model.fit(train_ds,validation_data val_ds,epochs epochs,callbacks [checkpointer, earlystopper]
)这段代码是基于给定数据集 train_ds 进行模型训练并在验证集 val_ds 上评估模型表现。同时使用了之前定义的 checkpointer 和 earlystopper 两个回调函数来保存模型和控制早期停止。
其中epochs epochs 表示训练的轮数callbacks [checkpointer, earlystopper] 表示在训练过程中使用了之前定义的回调函数来保存模型和控制早期停止。
该方法会返回一个 history 对象包含了模型在训练过程中的各种指标例如训练损失、验证损失、训练准确率、验证准确率等等。 通过对这些指标的分析我们可以更加深入地了解模型的表现和训练效果从而进一步调整模型的参数和结构提高模型的性能并得到更好的预测结果。
八、模型评估
1、Loss和Acc图
loss history.history[loss]
val_loss history.history[val_loss]acc history.history[accuracy]
val_acc history.history[val_accuracy]epochs_range range(len(loss))plt.figure(figsize (12, 4))plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label Training Acc)
plt.plot(epochs_range, val_acc, label Validation Acc)
plt.legend(loc lower right)
plt.title(Training And Validation Acc)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()decay_steps 设置成 10
decay_steps 修改成30后 2、指定图片进行预测
model.load_weights(best_model.h5)
#这段代码用于加载之前训练中保存的最佳模型权重。best_model.h5 指的是之前保存的模型权重文件路径和名称。
#这样可以避免从头开始训练模型直接使用已经训练好的最佳模型进行预测的工作。from PIL import Image
import numpy as npimg Image.open(D:/DL_Camp/CNN/T5/46-data/train/nike/1 (12).jpg) #使用 PIL 库中的 Image.open() 方法打开一张待预测的图片。
image tf.image.resize(img, [img_height, img_width])
#这个函数调整输入图像的大小以符合模型的要求。
#在这个例子中使用 TensorFlow 的 tf.image.resize() 函数将图像缩放为指定大小其中 img_height 和 img_width 是指定的图像高度和宽度。img_array tf.expand_dims(image, 0)这个函数将输入图像转换为形状为 (1, height, width, channels) 的四维数组
其中 height 和 width 是图像的高度和宽度channels 是图像的通道数例如 RGB 图像有 3 个通道。
这里使用 TensorFlow 的 tf.expand_dims() 函数来扩展图像数组的维度以匹配模型的输入格式。具体来说
image 是一个二维图片张量它的形状是 (height, width, channels)。其中 height 和 width 分别为图片的高度和宽度channels 为图片的颜色通道数。0 是一个整数值它指定在哪个维度上扩展此张量这里表示在最前面第一个的维度上扩展。
因此函数的作用是将输入张量 image 在最前面添加一个额外的维度batch_size生成一个四维张量。tf.expand_dims(input, axis)
其中 input 表示要扩展的输入张量axis 表示要在哪个维度上进行扩展。在这个例子中input 是变量 imageaxis 是 0。
predictions model.predict(img_array)
#这个函数用于对输入图像进行分类预测。它使用已经训练好的模型来对输入数据进行推断并输出每个类别的概率分布。
print(预测结果为, class_names[np.argmax(predictions)])将模型输出的概率分布转换为最终预测结果。
具体来说使用 np.argmax() 函数找到概率最大的类别索引然后使用该索引在 class_names 列表中查找相应的类别名称并输出预测结果。九、总结
通过多次实验我已经更加熟悉了识别任务的流程。然而在本次实验中要求测试集准确率达到84%。尽管我对模型参数进行了调整例如将Dropout层的参数都改成0.1但是准确率仍然远远没有达到目标。
后来我查阅了资料和博客发现动态学习率里的参数也会影响模型的效果。起初我只把注意力放在模型参数上这才导致模型效果并没有太大的提升。原因是先前的 decay_steps 设置成了 10导致学习率衰减过快模型很快就停止训练了。这样模型的准确率提升并不明显。为了解决这个问题我将 decay_steps 设置成了 30学习率变化缓慢可以充分训练模型因此准确率也随之提高。最后我成功将测试集准确率提高到了 0.9394。
综上所述调整动态学习率的参数对模型的训练结果也十分重要这个经验也对我的后续研究和实验有了很大的指导意义。