第T5周:运动鞋品牌识别

目录

一、前期工作

1. 设置GPU

2. 导入数据

3. 查看数据

二、数据预处理

1. 加载数据

1.1 函数的基本用法:

1.2 测试集与验证集的关系:

2. 可视化数据

3. 再次检查数据

4. 配置数据集

三、构建CNN网络

四、训练模型

ExponentialDecay函数:

主要参数和用法:

1.设置动态学习率

2.早停与保存最佳模型参数

3. 模型训练

五、模型评估

1. Loss与Accuracy图

2. 指定图片进行预测


一、前期工作

1. 设置GPU

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

from tensorflow import keras
from tensorflow.keras import layers, models
import os, PIL, pathlib
import matplotlib.pyplot as plt
import tensorflow as tf

gpus = tf.config.list_physical_devices("GPU")

if gpus:
    gpu0 = gpus[0]
    tf.config.experimental.set_memory_growth(gpu0, True)
    tf.config.set_visible_devices([gpu0], "GPU")

gpus

2. 导入数据

# data_dir = "D:/jupyter notebook/T5/46-data/"
data_dir = "./46-data/"

data_dir = pathlib.Path(data_dir)

3. 查看数据

image_count = len(list(data_dir.glob('*/*/*.jpg')))

print("图片总数为:", image_count)
roses = list(data_dir.glob('train/nike/*.jpg'))
PIL.Image.open(str(roses[0]))

二、数据预处理

1. 加载数据

  • 使用image_dataset_from_directory方法将磁盘中的数据加载到tf.data.Dataset中
    • tf.keras.preprocessing.image_dataset_from_directory 是 TensorFlow 的 Keras 模块中的一个函数,用于从目录中创建一个图像数据集(dataset)。这个函数可以以更方便的方式加载图像数据,用于训练和评估神经网络模型。

1.1 函数的基本用法:

创建出的数据集的标签一般是从目录得到的:

  • directory: 数据所在目录。如果标签是inferred(默认),则它应该包含子目录,每个目录包含一个类的图像。否则,将忽略目录结构。
  • labels: inferred(标签从目录结构生成),或者是整数标签的列表/元组,其大小与目录中找到的图像文件的数量相同。标签应根据图像文件路径的字母顺序排序(通过Python中的os.walk(directory)获得)。
import tensorflow as tf

# 设置图像数据目录
data_dir = "path/to/your/image/directory"

# 创建图像数据集
dataset = tf.keras.preprocessing.image_dataset_from_directory(
    data_dir,
    batch_size=32,  # 每个批次的图像数量
    image_size=(128, 128),  # 图像将被调整为的尺寸
    shuffle=True,  # 是否在每个 epoch 后对数据集进行洗牌
    seed=42,  # 洗牌时使用的随机种子
    validation_split=0.2,  # 验证集的比例
    subset="training"  # 使用训练集还是验证集,"training" 或 "validation"
)

# 查看类别标签
class_names = dataset.class_names
print("类别标签:", class_names)

# 可以通过迭代数据集来获取批次的图像和标签
for images, labels in dataset:
    # 在这里进行模型训练或评估操作
    pass

1.2 测试集与验证集的关系:

  1. 验证集并没有参与训练过程梯度下降过程的,狭义上来讲是没有参与模型的参数训练更新的。
  2. 但是广义上来讲,验证集存在的意义确实参与了一个“人工调参”的过程,我们根据每一个epoch训练之后模型在valid data上的表现来决定是否需要训练进行early stop,或者根据这个过程模型的性能变化来调整模型的超参数,如学习率,batch_size等等。
  3. 因此,我们也可以认为,验证集也参与了训练,但是并没有使得模型去overfit验证集
batch_size = 32
img_height = 224
img_width = 224

train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    # 注意数据目录,它应该有子目录且每个目录包含一个类的图像
    "./46-data/train/",
    seed=123,
    image_size=(img_height, img_width),
    batch_size=batch_size
)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
    "./46-data/test/",
    seed=123,
    image_size=(img_height, img_width),
    batch_size=batch_size
)
class_names = train_ds.class_names
print(class_names)

2. 可视化数据

plt.figure(figsize=(20, 10))

# take(1)表示获取第一个批次的数据
for images, labels in train_ds.take(1):
    for i in range(20):
        ax = plt.subplot(5, 10, i+1)

        # 这段代码的目的是将一个张量表示的图像转换为 NumPy 数组,并使用 Matplotlib 的 `imshow()` 函数显示出来。
        plt.imshow(images[i].numpy().astype("uint8"))
        plt.title(class_names[labels[i]])
        
        plt.axis("off")

3. 再次检查数据

for image_batch, labels_batch in train_ds:
    print(image_batch.shape)
    print(labels_batch.shape)
    break
  • Image_batch是形状的张量(32,224,224,3)。这是一批形状224x224x3的32张图片(最后一维指的是彩色通道RGB)。
  • Label_batch是形状(32,)的张量,这些标签对应32张图片

4. 配置数据集

AUTOTUNE = tf.data.AUTOTUNE

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

三、构建CNN网络

卷积神经网络(CNN)的输入是张量 (Tensor) 形式的 (image_height, image_width, color_channels),包含了图像高度、宽度及颜色信息。不需要输入batch size。color_channels 为 (R,G,B) 分别对应 RGB 的三个颜色通道(color channel)。在此示例中,我们的 CNN 输入的形状是 (224, 224, 3)即彩色图像。我们需要在声明第一层时将形状赋值给参数input_shape

"""
layers.Dropout(0.4) 作用是防止过拟合,提高模型的泛化能力。

layers.experimental.preprocessing.Rescaling 是 TensorFlow 2.x 中的一个图像预处理层(preprocessing layer),
用于将图像的像素值重新缩放到指定的范围内。
通常,在训练深度学习模型时,对输入数据进行标准化和缩放是一个常见的步骤,以便更好地训练模型并提高收敛速度。

Rescaling 层通常用于模型的输入层,以确保输入数据的范围在合理的范围内。这对于训练深度学习模型非常重要,
因为标准化和缩放可以改善梯度下降的性能,提高模型的稳定性和收敛速度。
"""

model = 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.3),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.Dropout(0.3),
    
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
    layers.Dense(len(class_names))
])

model.summary()

四、训练模型

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

  • 损失函数(loss):用于衡量模型在训练期间的准确率。
  • 优化器(optimizer):决定模型如何根据其看到的数据和自身的损失函数进行更新。
  • 指标(metrics):用于监控训练和测试步骤。以下示例使用了准确率,即被正确分类的图像的比率。

ExponentialDecay函数:

tf.keras.optimizers.schedules.ExponentialDecay 是 TensorFlow 中的一个学习率衰减策略,用于在训练神经网络时动态地降低学习率。学习率衰减是一种常用的技巧,可以帮助优化算法更有效地收敛到全局最小值,从而提高模型的性能。

ExponentialDecay 通过指数函数来减小学习率,其基本思想是随着训练的进行,学习率会按照指数函数的规律逐渐减小。

主要参数和用法:

以下是 tf.keras.optimizers.schedules.ExponentialDecay 的主要参数和用法:

  • initial_learning_rate(初始学习率):在训练开始时的学习率大小。通常,您需要根据问题和模型的特点来选择一个合适的初始学习率。
  • decay_steps(衰减步数):学习率衰减的步数。在经过 decay_steps 步后,学习率将按照指数函数衰减。例如,如果 decay_steps 设置为 1000,那么在训练的第 1000 步后,学习率将开始衰减。
  • decay_rate(衰减率):学习率的衰减率。它决定了学习率如何减小。通常,取值在 0 到 1 之间。较小的 decay_rate 会导致学习率更缓慢地下降。
  • staircase(阶梯式衰减):一个布尔值,控制学习率的衰减方式。如果设置为 True,则学习率在每个 decay_steps 步之后直接减小,形成阶梯状下降。如果设置为 False,则学习率将连续衰减。

1.设置动态学习率

# 设置初始学习率
initial_learning = 1e-3

lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(
    initial_learning,
    decay_steps=10,
    decay_rate=0.92,  # lr经过一次衰减就会变成 decay_rate*lr
    staircase=True
)

# 将指数衰减学习率送入优化器
optimizer = tf.keras.optimizers.Adam(learning_rate=lr_schedule)

model.compile(optimizer=optimizer,
             # 设置损失函数为交叉熵损失函数(tf.keras.losses.SparseCategoricalCrossentropy())
             # from_logits为True时,会将y_pred转化为概率(softmax),否则不进行转换,通常情况下用True结果更稳定
             loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
             metrics=['accuracy'])

学习率大与学习率小的优缺点分析:

学习率大

  • 优点:
    • 1、加快学习速率。
    • 2、有助于跳出局部最优值。
  • 缺点:
    • 1、导致模型训练不收敛。
    • 2、单单使用大学习率容易导致模型不精确。

学习率小

  • 优点:
    • 1、有助于模型收敛、模型细化。
    • 2、提高模型精度。
  • 缺点:
    • 1、很难跳出局部最优值。
    • 2、收敛缓慢。

注意:这里设置的动态学习率为:指数衰减型(ExponentialDecay)。在每一个epoch开始前,学习率(learning_rate)都将会重置为初始学习率(initial_learning_rate),然后再重新开始衰减。计算公式如下:

learning_rate = initial_learning_rate * decay_rate ^ (step / decay_steps)

2.早停与保存最佳模型参数

EarlyStopping()参数说明

  • monitor: 被监测的数据。
  • min_delta: 在被监测的数据中被认为是提升的最小变化, 例如,小于 min_delta 的绝对变化会被认为没有提升。
  • patience: 没有进步的训练轮数,在这之后训练就会被停止。
  • verbose: 详细信息模式。
  • mode: {auto, min, max} 其中之一。 在 min 模式中, 当被监测的数据停止下降,训练就会停止;在 max 模式中,当被监测的数据停止上升,训练就会停止;在 auto 模式中,方向会自动从被监测的数据的名字中判断出来。
  • baseline: 要监控的数量的基准值。 如果模型没有显示基准的改善,训练将停止。
  • estore_best_weights: 是否从具有监测数量的最佳值的时期恢复模型权重。 如果为 False,则使用在训练的最后一步获得的模型权重。
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping

epochs = 50

# 保存最佳模型参数
checkpointer = ModelCheckpoint('best_model.h5',
                                monitor='val_accuracy',
                                verbose=1,
                                save_best_only=True,# 仅保存在监控指标上性能最佳的模型权重
                                save_weights_only=True# 仅保存权重而不保存整个模型
                              )

# 设置早停
earlystopper = EarlyStopping(monitor='val_accuracy', 
                             min_delta=0.001,
                             patience=20, 
                             verbose=1)

3. 模型训练

history = model.fit(train_ds,
                    validation_data=val_ds,
                    epochs=epochs,
                    callbacks=[checkpointer, earlystopper])

五、模型评估

1. Loss与Accuracy图

acc = history.history['accuracy']
val_acc = history.history['val_accuracy']

loss = history.history['loss']
val_loss = history.history['val_loss']

epochs_range = range(len(loss))

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

2. 指定图片进行预测

# 加载效果最好的模型权重
model.load_weights('best_model.h5')

from PIL import Image
import numpy as np 

img_path = "./46-data/test/nike/1.jpg" # 这里选择你需要预测的图片
img = tf.io.read_file(img_path)
img = tf.image.decode_jpeg(img, channels=3)  # 将图像解码为3通道的Tensor
image = tf.image.resize(img, [img_height, img_width])

# 使用 tf.expand_dims 将其准备成可以输入到神经网络的格式,将其变成形状为 [1, H, W, C] 的批次数据
img_array1 = tf.expand_dims(image, 0) # /255.0  # 记得做归一化处理(与训练集处理方式保持一致)
img_array2 = tf.expand_dims(image, 0)  /255.0

predictions1 = model.predict(img_array1) # 这里选用你已经训练好的模型
predictions2 = model.predict(img_array2)
print("1 预测结果为:",class_names[np.argmax(predictions1)])
print("2 预测结果为:",class_names[np.argmax(predictions2)])
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值