网站页面统计代码是什么今日新闻最新头条10条摘抄
- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
- 🍖 原作者:K同学啊
目标
具体实现
(一)环境
语言环境:Python 3.10
编 译 器: PyCharm
框 架: TensorFlow
(二)具体步骤
import numpy as np
import tensorflow as tf
from tensorflow.python.data import AUTOTUNE # 设置GPU
# 获取当前系统中所有可用的物理GPU设备
gpus = tf.config.list_physical_devices("GPU") # 如果系统中存在GPU设备
if gpus: # 设置第一个GPU设备的内存增长模式为动态增长,以避免一次性占用所有显存 tf.config.experimental.set_memory_growth(gpus[0], True) # 设置当前可见的GPU设备为第一个GPU,确保程序仅使用该GPU进行计算 tf.config.set_visible_devices([gpus[0]], "GPU") # 导入数据
import matplotlib.pyplot as plt
import os, PIL, pathlib
from tensorflow import keras
from tensorflow.keras import layers, models # 设置matplotlib的字体为SimHei,以支持中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
# 设置matplotlib的负号显示为正常符号,避免显示为方块
plt.rcParams['axes.unicode_minus'] = False # 定义数据目录路径
data_dir = "./data/bird_photos"
# 将路径转换为pathlib.Path对象,方便后续操作
data_dir = pathlib.Path(data_dir) # 使用glob方法获取所有子目录下的jpg文件,并计算其数量
image_count = len(list(data_dir.glob('*/*.jpg')))
# 打印图片数量
print("图片数量:",image_count) # 数据预处理
# 定义批量大小和图像尺寸
batch_size = 8
img_height = 224
img_width = 224 # 使用 `tf.keras.preprocessing.image_dataset_from_directory` 从指定目录加载训练数据集
# 参数说明:
# - data_dir: 包含图像数据的目录路径
# - validation_split: 用于验证集的数据比例,此处为20%
# - subset: 指定加载的数据子集,此处为训练集
# - seed: 随机种子,确保数据分割的可重复性
# - image_size: 图像将被调整到的尺寸,此处为224x224
# - batch_size: 每个批次的图像数量,此处为8
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) # 使用 `tf.keras.preprocessing.image_dataset_from_directory` 从指定目录加载验证数据集
# 参数说明与训练集相同,但 `subset` 参数指定为验证集
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) # 从训练数据集中获取类别名称
class_names = train_ds.class_names # 打印类别名称
print("类别:", class_names) # 可视化数据
# 可视化训练数据集中的部分图像及其对应的标签
# 该代码块创建一个大小为10x5的图形窗口,并在窗口中展示训练数据集中的前8张图像及其标签。 plt.figure(figsize=(10, 5)) # 创建一个大小为10x5的图形窗口
plt.suptitle("训练数据集可视化") # 设置图形的标题为"训练数据集可视化" # 从训练数据集中取出一批数据(images和labels),并展示其中的前8张图像
for images, labels in train_ds.take(1): for i in range(8): ax = plt.subplot(2, 4, i+1) # 在2行4列的网格中创建第i+1个子图 plt.imshow(images[i].numpy().astype("uint8")) # 显示第i张图像,并将其转换为uint8类型 plt.title(class_names[labels[i]]) # 设置子图的标题为对应的类别名称 plt.axis("off") # 关闭子图的坐标轴显示 # 检查数据
"""
遍历训练数据集中的批次,并打印图像批次和标签批次的形状。 该代码片段从训练数据集 `train_ds` 中获取一个批次的数据,并打印该批次中图像和标签的形状。
`train_ds` 是一个可迭代对象,通常包含图像和标签的批次数据。 代码执行流程:
1. 从 `train_ds` 中获取一个批次的图像和标签。
2. 打印图像批次的形状。
3. 打印标签批次的形状。
4. 使用 `break` 语句提前退出循环,仅处理第一个批次。
"""
for image_batch, labels_batch in train_ds: # 打印图像批次的形状,通常为 (batch_size, height, width, channels) print(image_batch.shape) # 打印标签批次的形状,通常为 (batch_size,) print(labels_batch.shape) # 仅处理第一个批次后退出循环 break # 配置数据集
# 设置自动调优参数,用于优化数据加载和预处理性能
AUTOTUNE = tf.data.AUTOTUNE # 对训练数据集进行优化处理:
# 1. `cache()`: 将数据集缓存到内存或磁盘,避免在每个epoch重复加载数据,提高训练效率。
# 2. `shuffle(1000)`: 对数据集进行随机打乱,缓冲区大小为1000,确保训练数据的随机性。
# 3. `prefetch(buffer_size=AUTOTUNE)`: 使用自动调优的缓冲区大小,预取数据以重叠数据加载和模型训练,提高整体性能。
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE) # 对验证数据集进行优化处理:
# 1. `cache()`: 将数据集缓存到内存或磁盘,避免在每个epoch重复加载数据,提高验证效率。
# 2. `prefetch(buffer_size=AUTOTUNE)`: 使用自动调优的缓冲区大小,预取数据以重叠数据加载和模型验证,提高整体性能。
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE) # 构建ResNet50网络
from keras import layers
from keras.layers import Input, Activation, BatchNormalization, Flatten
from keras.layers import Dense, Conv2D,MaxPooling2D,ZeroPadding2D,AveragePooling2D
from keras.models import Model def identity_block(input_tensor, kernel_size, filters, stage, block): """ 实现ResNet中的恒等块(Identity Block)。 参数: - input_tensor: 输入张量,形状为 (batch_size, height, width, channels)。 - kernel_size: 卷积核的大小,通常为 (3, 3)。 - filters: 三个整数的列表,表示三个卷积层的滤波器数量。 - stage: 当前块的阶段标识,用于命名。 - block: 当前块的标识,用于命名。 返回: - 输出张量,形状与输入张量相同。 """ filters1, filters2, filters3 = filters name_base= str(stage) + block + '_identify_block_' # 第一个卷积层,1x1卷积,用于降维 x = Conv2D(filters1, (1,1), name = name_base + 'conv1')(input_tensor) x = BatchNormalization(name = name_base + 'bn1')(x) x = Activation('relu', name = name_base + 'relu1')(x) # 第二个卷积层,使用指定的kernel_size进行卷积 x = Conv2D(filters2, kernel_size, padding = 'same', name = name_base + 'conv2')(x) x = BatchNormalization(name = name_base + 'bn2')(x) x = Activation('relu', name = name_base + 'relu2')(x) # 第三个卷积层,1x1卷积,用于升维 x = Conv2D(filters3, (1,1), name = name_base + 'conv3')(x) x = BatchNormalization(name = name_base + 'bn3')(x) # 将输入张量与卷积结果相加,实现残差连接 x = layers.add([x, input_tensor], name = name_base + 'add') x = Activation('relu', name = name_base + 'relu4')(x) return x def conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2,2)): """ 实现ResNet中的卷积块(Convolutional Block)。 参数: - input_tensor: 输入张量,形状为 (batch_size, height, width, channels)。 - kernel_size: 卷积核的大小,通常为 (3, 3)。 - filters: 三个整数的列表,表示三个卷积层的滤波器数量。 - stage: 当前块的阶段标识,用于命名。 - block: 当前块的标识,用于命名。 - strides: 卷积步幅,默认为 (2, 2)。 返回: - 输出张量,形状与输入张量相同。 """ filters1, filters2, filters3 = filters res_name_base = str(stage) + block + '_conv_block_res_' name_base = str(stage) + block + '_conv_block_' # 第一个卷积层,1x1卷积,用于降维 x = Conv2D(filters1, (1,1), strides = strides, name = name_base + 'conv1')(input_tensor) x = BatchNormalization(name = name_base + 'bn1')(x) x = Activation('relu', name = name_base + 'relu1')(x) # 第二个卷积层,使用指定的kernel_size进行卷积 x = Conv2D(filters2, kernel_size, padding = 'same', name = name_base + 'conv2')(x) x = BatchNormalization(name = name_base + 'bn2')(x) x = Activation('relu', name = name_base + 'relu2')(x) # 第三个卷积层,1x1卷积,用于升维 x = Conv2D(filters3, (1,1), name = name_base + 'conv3')(x) x = BatchNormalization(name = name_base + 'bn3')(x) # 对输入张量进行1x1卷积,以匹配输出张量的维度 shortcut = Conv2D(filters3, (1,1), strides = strides, name = res_name_base + 'conv1')(input_tensor) shortcut = BatchNormalization(name = res_name_base + 'bn1')(shortcut) # 将卷积结果与输入张量相加,实现残差连接 x = layers.add([x, shortcut], name = res_name_base + 'add') x = Activation('relu', name = res_name_base + 'relu4')(x) return x def ResNet50(input_shape=[224, 224, 3], classes=1000): """ 构建ResNet50模型。 参数: - input_shape: 输入图像的形状,默认为 [224, 224, 3]。 - classes: 分类任务的类别数,默认为 1000。 返回: - 构建好的ResNet50模型。 """ img_input = Input(shape=input_shape) x = ZeroPadding2D((3,3))(img_input) # 初始卷积层 x = Conv2D(64, (7,7), strides = (2,2), name = 'conv1')(x) x = BatchNormalization(name = 'bn_conv1')(x) x = Activation('relu')(x) x = MaxPooling2D((3,3), strides = (2,2))(x) # 第一阶段:包含一个卷积块和两个恒等块 x = conv_block(x, 3, [64,64,256], stage=2, block='a', strides=(1,1)) x = identity_block(x, 3, [64,64,256], stage=2, block='b') x = identity_block(x, 3, [64,64,256], stage=2, block='c') # 第二阶段:包含一个卷积块和三个恒等块 x = conv_block(x, 3, [128,128,512], stage=3, block='a') x = identity_block(x, 3, [128,128,512], stage=3, block='b') x = identity_block(x, 3, [128,128,512], stage=3, block='c') x = identity_block(x, 3, [128,128,512], stage=3, block='d') # 第三阶段:包含一个卷积块和五个恒等块 x = conv_block(x, 3, [256,256,1024], stage=4, block='a') x = identity_block(x, 3, [256,256,1024], stage=4, block='b') x = identity_block(x, 3, [256,256,1024], stage=4, block='c') x = identity_block(x, 3, [256,256,1024], stage=4, block='d') x = identity_block(x, 3, [256,256,1024], stage=4, block='e') x = identity_block(x, 3, [256,256,1024], stage=4, block='f') # 第四阶段:包含一个卷积块和两个恒等块 x = conv_block(x, 3, [512,512,2048], stage=5, block='a') x = identity_block(x, 3, [512,512,2048], stage=5, block='b') x = identity_block(x, 3, [512,512,2048], stage=5, block='c') # 全局平均池化层和全连接层 x = AveragePooling2D((7,7), name = 'avg_pool')(x) x = Flatten()(x) x = Dense(classes, activation='softmax', name='fc1000')(x) model = Model(img_input, x, name='resnet50') # 加载预训练权重 model.load_weights('./models/resnet50_weights_tf_dim_ordering_tf_kernels.h5') return model # 初始化一个ResNet50模型实例
# 参数说明:
# - input_shape: 输入图像的形状,格式为[height, width, channels],此处为[224, 224, 3],表示224x224像素的RGB图像
# - classes: 分类任务的类别数量,此处为class_names列表的长度,表示模型将输出对应类别的概率
model = ResNet50() # 打印模型的摘要信息,包括每一层的名称、输出形状和参数数量
model.summary() model.compile( # 使用Adam优化器,学习率初始值为0.001 optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), # 设置损失函数为交叉熵损失函数 loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), # 设置性能指标列表,将在模型训练时监控列表中的指标 metrics=['accuracy']
) # 训练模型并记录训练过程中的历史数据
#
# 参数:
# train_ds: 训练数据集,通常是一个tf.data.Dataset对象,包含训练数据。
# validation_data: 验证数据集,通常是一个tf.data.Dataset对象,用于在训练过程中评估模型性能。
# epochs: 训练的轮数,即模型将遍历整个训练数据集的次数。
#
# 返回值:
# history: 一个History对象,包含训练过程中的损失和评估指标的历史记录。 epochs = 10
history = 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)
epochs_range = range(epochs) # 创建一个大小为12x4的图形窗口
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() # 预测
# 该函数用于展示验证数据集中的图片,并使用训练好的模型对图片进行预测,显示预测结果。
# 函数的主要步骤包括:
# 1. 创建一个大小为10x5的图形窗口。
# 2. 设置图形的总标题为“图片预测”。
# 3. 从验证数据集中取出一批图片和标签。
# 4. 对每张图片进行预测,并在子图中显示图片和预测结果。
# 5. 关闭子图的坐标轴显示。 plt.figure(figsize=(10, 5)) # 创建一个大小为10x5的图形窗口
plt.suptitle("图片预测") # 设置图形的总标题为“图片预测” # 从验证数据集中取出一批图片和标签
for images, labels in val_ds.take(1): # 遍历前8张图片,并在子图中显示图片和预测结果 for i in range(8): ax = plt.subplot(2, 4, i+1) # 创建2行4列的子图,并选择第i+1个子图 plt.imshow(images[i].numpy().astype("uint8")) # 显示第i张图片 # 对图片进行预测 img_array = tf.expand_dims(images[i], 0) # 扩展图片的维度以适应模型输入 predictions = model.predict(img_array) # 使用模型进行预测 # 在子图标题中显示预测结果 plt.title(class_names[np.argmax(predictions)]) plt.axis("off") # 关闭子图的坐标轴显示