做网站如何赚钱,上海商业连锁设计,商旅100网页版,三只松鼠商务网站建设目的1.卷积神经网络 卷积神经网络#xff08;Convolutional Neural Network, CNN#xff09;是一种专门用于处理数据网格结构#xff08;如图像、视频等#xff09;的深度学习模型#xff0c;在计算机视觉任务中被广泛应用#xff0c;如图像分类、目标检测、图像分割等。以下…1.卷积神经网络 卷积神经网络Convolutional Neural Network, CNN是一种专门用于处理数据网格结构如图像、视频等的深度学习模型在计算机视觉任务中被广泛应用如图像分类、目标检测、图像分割等。以下是卷积神经网络的详细介绍
1.1 卷积神经网络 (CNN) 结构及原理
核心组件
卷积层 使用卷积核对输入数据如图像进行滑动生成特征图feature map。池化层 通过下采样减少特征图的尺寸降低计算复杂度和内存消耗。常见方法包括最大池化 (max pooling)和平均池化 (average pooling)。全连接层 将卷积和池化提取到的特征映射为输出类别实现分类或回归任务。Dropout层 防止过拟合通过随机丢弃部分神经元。
激活函数 常用ReLU函数引入非线性帮助模型学习复杂模式。
特点
局部连接 每一层只与相邻节点连接减少参数数量。权重共享 同一卷积核在不同位置重复使用进一步降低计算复杂度。 CNN 结构 典型的卷积神经网络由卷积层、池化层和全连接层 3 部分组成。在图像分类中表现良好的深度卷积神经网络往往由多个“卷积层池化层”的组合堆叠而成通常多达十几层甚至上百层 卷积层用于提取图像中的局部特征池化层用于对提取出的局部特征 进行降维处理防止过拟合全连接层用于接收池化层的输出为后续分类任务 做准备。 1.2 经典卷积神经网络结构
LeNet-5 主要用于手写数字识别包括多个卷积层和池化层组合。
网络结构输入层 → 卷积层 → 池化层 → 卷积层 → 池化层 → 全连接层 → 输出层
VGGNet 探索卷积网络深度与性能的关系VGG16和VGG19为其常见变体。
特点多组3×3卷积核每组卷积后接2×2最大池化层。
ResNet 引入残差模块允许数据直接跳过某些层提高网络性能。 2.基于 Cifar-10 数据集的彩色图像识别分类
2.1 导入所需的模块和包并进行数据预处理 2.1.1 实现目的
导入TensorFlow等所需模块用于加载 CIFAR-10 数据集并完成数据类型转换和标准化处理确保模型可以正常使用这些数据进行训练和测试。
2.1. 代码片段与结果
步骤一导入本项目所需要的模块和包从 Keras 中导入 Cifar-10 数据集将训练集的特征值和标签值分别存储在
x_train 和 y_train 中将测试集的特征值和标签值分别存储在 x_test 和 y_test 中。将特征值 x_train 和 x_test
的数据类型转换为 tf.float32并进行标准化处理使其取值范围为 01将标签值 y_train 和 y_test的数据类型转换为 tf.int32。# 导入所需要的模块与包
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import os# 导入Cifar-10数据集将训练集和测试集存储在相应变量中
cifar10 tf.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) cifar10.load_data()# 转换特征值的数据类型并进行标准化处理
x_train, x_test tf.cast(x_train, dtypetf.float32) / 255.0, tf.cast(x_test, dtypetf.float32) / 255.0# 转换标签值的数据类型
y_train, y_test tf.cast(y_train, dtypetf.int32), tf.cast(y_test, dtypetf.int32)# 显示数据集的特征值和标签值的 shape 属性值
print(x_train.shape , x_train.shape)
print(y_train.shape , y_train.shape)
print(x_test.shape , x_test.shape)
print(y_test.shape , y_test.shape)2.1.3 代码解释
1.导入 TensorFlow、NumPy、Matplotlib 和 OS 模块
TensorFlow用于深度学习模型构建和数据处理。NumPy用于数值计算和数据操作。Matplotlib用于数据的可视化。OS用于文件和目录操作。
2.加载 CIFAR-10 数据集
tf.keras.datasets.cifar10 提供了 CIFAR-10 数据集。该数据集包含 10 类图片适用于图像分类任务。load_data() 将数据集拆分为训练集和测试集并存储在 (x_train, y_train) 和 (x_test, y_test) 中。
3.数据类型转换与标准化
使用 tf.cast() 将特征值转换为 tf.float32 数据类型。将像素值标准化到 [0, 1] 范围内方便模型训练。将标签值转换为 tf.int32用于模型的分类任务。
4.显示数据形状
通过 print() 输出训练集和测试集的特征值及标签值的形状以验证数据加载是否正确。
2.1.4 结果与结果分析 x_train.shape (50000, 32, 32, 3) x_train.shape (50000, 32, 32, 3) y_train.shape (50000, 1) y_test.shape (10000, 1) 1. 训练集数据 (x_train, y_train)
x_train.shape (50000, 32, 32, 3)
50000训练集包含 50,000 张图像。32 × 32每张图像的大小是 32 × 32 像素。3代表图像的 3 个颜色通道RGB即每个像素点包含红、绿、蓝三种颜色值。
y_train.shape (50000, 1)
每张图像有 1 个标签表示其所属类别。CIFAR-10 有 10 个类别用标签 09 表示。
2. 测试集数据 (x_test, y_test)
x_test.shape (10000, 32, 32, 3)
10000测试集包含 10,000 张图像。32 × 32每张图像的尺寸为 32 × 32 像素。3表示每张图像有 3 个颜色通道RGB。
y_test.shape (10000, 1)
每张测试图像也有 1 个标签对应其类别。 2.2 构建 CNN 模型
2.2.1 实现目的
构建一个用于 CIFAR-10 图像分类的卷积神经网络CNN模型。通过多个卷积层、池化层和全连接层的组合来提取图像特征并最终完成分类任务。
2.2.2 代码片段
步骤二构建 CNN 模型图像识别分类网络模型采用卷积神经网络包括两
个卷积层、两个池化层、4 个 Dropout 层、一个拉伸层、两个全连接层和一个输
出层
# 构建 CNN 模型
model tf.keras.models.Sequential([# 使用 Input 层明确指定输入形状tf.keras.Input(shapex_train.shape[1:]), # 创建卷积层tf.keras.layers.Conv2D(32, kernel_size(3, 3), paddingsame, activationtf.nn.relu),# 创建最大池化层tf.keras.layers.MaxPool2D(pool_size(2, 2), strides(1, 1), paddingsame), # 创建 Dropout 层tf.keras.layers.Dropout(0.2), # 创建第二个卷积层tf.keras.layers.Conv2D(64, kernel_size(3, 3), paddingsame, activationtf.nn.relu),# 创建最大池化层tf.keras.layers.MaxPool2D(pool_size(2, 2), strides(1, 1), paddingsame), # 创建 Dropout 层tf.keras.layers.Dropout(0.2), # 创建拉伸层Flattentf.keras.layers.Flatten(), # 创建全连接层tf.keras.layers.Dense(512, activationrelu), # 创建 Dropout 层tf.keras.layers.Dropout(0.2), # 创建另一个全连接层tf.keras.layers.Dense(256, activationrelu), # 创建 Dropout 层tf.keras.layers.Dropout(0.5), # 创建全连接层作为输出层tf.keras.layers.Dense(10, activationsoftmax)
])# 打印模型结构
model.summary()
2.2.3 代码解释
1.Sequential 模型
使用 tf.keras.models.Sequential() 按顺序定义模型结构。
2.输入层
tf.keras.Input() 定义输入层输入数据的形状与训练数据集的形状一致。
3.卷积层
第一层卷积Conv2D(32, (3, 3)) 使用 32 个大小为 3x3 的卷积核提取低层次特征。第二层卷积Conv2D(64, (3, 3)) 使用 64 个卷积核提取更复杂的特征。
4.池化层
使用 MaxPool2D(pool_size(2, 2), strides(1, 1)) 进行最大池化减少特征图的尺寸保留主要信息。
5.Dropout 层
在多处使用 Dropout() 随机丢弃神经元防止过拟合。丢弃概率分别为 0.2 和 0.5。
6.拉伸层Flatten
使用 Flatten() 将二维特征图展开为一维向量方便传入全连接层。
7.全连接层
第一层全连接层512 个神经元激活函数为 ReLU。第二层全连接层256 个神经元激活函数为 ReLU。
8.输出层
使用 Dense(10, activationsoftmax) 作为输出层适用于 CIFAR-10 的 10 分类任务。
9.打印模型结构
使用 model.summary() 打印模型的结构、参数数量和层次关系。
2.2.4 结果与结果分析 1模型层结构
1.Conv2D (卷积层)
输出形状(None, 32, 32, 32) 说明32 个 3×3 的卷积核输出 32 个特征图。参数数量896 计算$(3 \times 3 \times 3 1) \times 32 896$包含偏置项。
2.MaxPooling2D (最大池化层)
输出形状(None, 32, 32, 32) 说明池化窗口为 2×2没有改变输出形状。
3.Dropout (丢弃层)
丢弃部分神经元防止过拟合。
4.第二个 Conv2D (卷积层)
输出形状(None, 32, 32, 64) 说明64 个 3×3 的卷积核。参数数量18,496 计算$(3 \times 3 \times 32 1) \times 64 18,496$。
5.Flatten (拉伸层)
输出形状(None, 65536) 说明将 32×32×64 的特征图展平为一维向量。
6.Dense (全连接层)
输出形状(None, 512) 参数数量33,554,944 计算$65536 \times 512 512 33,554,944$。
7.Dense (全连接层)
输出形状(None, 256) 参数数量131,328 计算$512 \times 256 256 131,328$。
8.输出层 (Dense)
输出形状(None, 10) 说明10 个神经元表示 10 个分类类别。参数数量2,570 计算$256 \times 10 10 2,570$。
2模型总参数
总参数数量33,708,234可训练参数数量33,708,234非可训练参数0
2.3 编译、训练和评估 CNN 模型
2.3.1 实现目的
编译模型配置优化器、损失函数和评估指标为训练过程做好准备。训练模型用训练集训练模型并在训练过程中监控验证集性能。评估模型在测试集上评估模型性能确保模型的泛化能力。
2.3.3 代码片段
步骤三编译、训练和评估 CNN 模型
# 编译网络模型
model.compile(optimizeradam, losstf.keras.losses.SparseCategoricalCrossentropy(), metrics[sparse_categorical_accuracy])os.environ[CUDA_VISIBLE_DEVICES] -1
# 训练网络模型
history model.fit(x_train, y_train, batch_size128, epochs10, validation_split0.2)# 评估网络模型
model.evaluate(x_test, y_test, batch_size64, verbose2)
2.3.3 代码解释
1.模型编译 (model.compile)
optimizeradamAdam 优化器兼具自适应学习率和动量优化的特点。losstf.keras.losses.SparseCategoricalCrossentropy()用于多分类任务的损失函数。metrics[sparse_categorical_accuracy]评估指标为稀疏分类准确率用于处理标签是整数编码的情况。
2.训练模型 (model.fit)
batch_size128每次梯度更新时处理 128 个样本。epochs10训练模型 10 个完整的周期轮次。validation_split0.2将 20% 的训练数据用于验证模型性能。
3.评估模型 (model.evaluate)
在测试集上评估模型性能batch_size64 指定每次处理的样本数。verbose2 控制输出日志的详细程度。
2.3.4 结果与结果分析 1训练过程
1.趋势分析
1.Epoch 1/10
训练损失loss1.3763训练准确率sparse_categorical_accuracy51.22%验证损失val_loss1.1739验证准确率val_sparse_categorical_accuracy59.02%
2.Epoch 10/10
训练损失0.3544训练准确率87.84%验证损失1.0411验证准确率69.57%
趋势分析
训练损失和训练准确率逐渐优化模型在训练数据上的表现不断提高最终训练准确率达到 87.84%。
验证集的准确率逐渐提高到 69.57%但验证损失val_loss在第 7-10 轮趋于不稳定略有增加表明模型可能出现了一些过拟合。
2测试集评估结果
loss: 1.0738 sparse_categorical_accuracy: 69.16%
解释
测试损失1.0738测试准确率69.16%在测试集上的准确率为 69.16%与验证集准确率69.57%非常接近表明模型的泛化能力良好。测试损失与验证损失接近进一步验证模型的性能稳定。
2.4 可视化训练的结果
2.4.1 实现目的
使用 Matplotlib 将训练损失、验证损失以及训练准确率、验证准确率随轮次的变化情况绘制成折线图帮助分析模型的训练过程和性能。
2.4.2 代码片段
步骤四可视化训练的结果
print(history.history)# 确保 epochs 数组的定义与 loss 和 acc 的数据一致
epochs range(1, len(history.history[loss]) 1)# 创建画布并设置画面大小
plt.figure(figsize(10, 3))# 在子图1中绘制损失函数的折线图
plt.subplot(121)
plt.plot(epochs, history.history[loss], colorb, labeltrain) # 蓝色线表示训练集损失
plt.plot(epochs, history.history[val_loss], colorr, labelvalidate) # 红色线表示验证集损失
plt.xlabel(Epochs) # 添加横轴标签
plt.ylabel(Loss) # 添加纵轴标签
plt.legend() # 显示图例# 在子图2中绘制准确率的折线图
plt.subplot(122)
plt.plot(epochs, history.history[sparse_categorical_accuracy], colorb, labeltrain) # 蓝色线表示训练集准确率
plt.plot(epochs, history.history[val_sparse_categorical_accuracy], colorr, labelvalidate) # 红色线表示验证集准确率
plt.xlabel(Epochs) # 添加横轴标签
plt.ylabel(Accuracy) # 添加纵轴标签
plt.legend() # 显示图例# 显示图像
plt.show()
2.4.3 代码解释
1.打印训练历史
history.history 中包含每一轮训练和验证的损失与准确率。
2.绘制损失函数曲线
子图 1 展示训练和验证的损失随轮次的变化 蓝线训练集损失红线验证集损失
3.绘制准确率曲线
子图 2 展示训练和验证的准确率随轮次的变化 蓝线训练集准确率红线验证集准确率
4.显示图像
使用 plt.show() 将两张图同时显示出来。
2.4.4 结果与结果分析 1损失曲线左图
蓝色线train训练集的损失值逐渐下降说明模型在逐步学习特征。红色线validate验证集的损失在前几轮下降后逐渐趋于平稳并略有上升。
分析
训练损失持续降低而验证损失在后期上升表明模型可能出现过拟合。改进建议 增加 Dropout 层的使用或增大丢弃率。使用更多正则化如 L2 正则化。尝试减少模型的复杂度或收集更多数据。
2准确率曲线右图
蓝色线train训练集的准确率逐渐提升最终接近 90%。红色线validate验证集的准确率在 70% 附近趋于平稳。
分析
训练准确率不断上升而验证准确率停滞在约 70% 左右。这进一步表明模型可能在训练集上表现良好但在验证集上出现过拟合。
2.5 应用卷积神经网络模型
2.5.1 实现目的
随机选取 10 张测试集中的图片使用训练好的 CNN 模型对其进行预测并将标签值和预测值显示在图像上方。验证模型的效果观察模型在测试集上的分类准确性。
2.5.2 代码片段 步骤五应用卷积神经网络模型
plt.figure() # 创建画布for i in range(10): # 循环显示10张图片n np.random.randint(1, 10000) # 生成随机整数 nplt.subplot(2, 5, i 1) # 创建子图 (2行5列)plt.axis(off) # 不显示坐标轴plt.rcParams[font.sans-serif] [SimHei] # 设置字体为 SimHei支持中文显示# 显示测试集中随机图片使用灰度颜色映射plt.imshow(x_test[n], cmapgray)# 将图片 reshape 为模型输入的形状 (1, 32, 32, 3)demo tf.reshape(x_test[n], (1, 32, 32, 3))# 使用模型预测该图片的类别y_pred np.argmax(model.predict(demo))# 设置子图标题显示标签值与预测值title 标签值: str((y_test.numpy())[n, 0]) \n预测值: str(y_pred)plt.title(title)# 展示图像
plt.show()
2.5.3 代码解释
1.画布与子图
plt.figure()创建一个用于显示图像的画布。plt.subplot(2, 5, i 1)将画布分成 2 行 5 列的子图每次在新的子图中显示一张图片。
2.随机选取测试图片
使用 np.random.randint(1, 10000) 生成 1 到 9999 之间的随机数作为图片索引。
3.显示图片
使用 plt.imshow() 在子图中显示随机图片使用 灰度颜色映射 (cmapgray)。
4.模型预测
将选中的图片 reshape 为模型的输入形状 (1, 32, 32, 3)。使用 model.predict() 对图片进行预测并使用 np.argmax() 获取预测的类别。
5.设置标题
子图标题中显示标签值和预测值标签值来自 y_test预测值来自模型的预测结果。
6.展示图像
使用 plt.show() 展示 10 张图片及其标签与预测结果。
2.5.4 结果与分析 1展示内容
每个子图显示了一张来自 CIFAR-10 测试集的随机图片且每张图片的标题标注了
标签值真实类别来自 y_test表示图片的真实类别标签。预测值模型预测结果模型根据输入图像预测的类别。
2分析结果
1.正确预测的示例
标签值6预测值6模型正确地识别出图片中的类别。标签值7预测值7另一个成功分类的示例。
2.错误预测的示例
标签值4预测值3模型将真实类别 4 误判为 3。标签值3预测值2该图片也被模型错误分类。
3模型表现观察
部分图片的预测结果是正确的说明模型对某些类别的识别效果较好。某些类别的预测出现错误这可能是因为 类别之间的相似性导致分类困难如狗和猫。数据不足或模型过拟合使得模型在某些类别上泛化能力不足。
3.基于 CNN 的手写数字识别的实验
3.1 随机选取并保存测试图片
3.1.1 实现目的
通过随机从 MNIST 测试集中选取一些图片并将它们以 PNG 格式保存到指定目录。这有助于我们检查数据集的样本内容并在后续使用这些图片进行预测和验证。
3.1.2 代码片段
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.datasets import mnist# 加载 MNIST 数据集
(x_train, y_train), (x_test, y_test) mnist.load_data()# 创建保存路径
import os
save_path test_images
os.makedirs(save_path, exist_okTrue)# 保存一些图片为 PNG
def save_images(images, labels, indices):for i in indices:img images[i]label labels[i]file_name f{save_path}/{label}_{i}.pngplt.imsave(file_name, img, cmapgray)print(f保存图片: {file_name})# 从测试集里保存 3 张图片 (你可以指定其他索引)
save_images(x_test, y_test, [0, 3, 9]) # 保存索引 0, 3, 9 处的图片
3.1.3 代码解释
1.导入库
numpy用于处理数组和数值操作。matplotlib.pyplot用于保存和显示图片。tensorflow.keras.datasets用于加载 MNIST 数据集。
2.加载数据集
使用 mnist.load_data() 加载 MNIST 手写数字数据集该数据集包含 60,000 张训练图片和 10,000 张测试图片。 x_train、x_test保存图片的 numpy 数组每张图片大小为 28x28 像素。y_train、y_test保存图片对应的标签0-9。
3.创建保存路径
使用 os.makedirs() 创建 test_images 文件夹如果文件夹不存在则会自动创建。
4.定义 save_images() 函数
遍历传入的索引列表 indices根据索引获取图片和对应标签。使用 plt.imsave() 将图片保存为 PNG 格式并以 {标签}_{索引}.png 命名。
5.调用 save_images() 函数
选取测试集中的第 0、3、9 张图片并将其保存到 test_images 文件夹中。
3.1.4 结果与分析 保存图片: test_images/7_0.png 保存图片: test_images/0_3.png 保存图片: test_images/9_9.png 1.图片内容检查
打开 test_images 文件夹检查是否存在 3 张 PNG 图片。图片的名称格式为 {标签}_{索引}.png其中 标签 是图片的真实类别。
2.潜在问题与解决方案
路径问题确保有权限在当前工作目录下创建文件夹和保存文件。图片内容错误如果保存的图片标签与预期不符请检查代码中的索引是否正确。
3.实际应用
这些保存的图片可以用于模型的预测测试验证训练模型的准确性。在接下来的步骤中我们将使用这些保存的图片并通过训练好的模型进行预测。
3.2 数据的读取与预处理
3.2.1 实现目的
本步骤的目的是加载 MNIST 数据集并对其进行预处理。具体目标包括
检查本地是否存在数据集如果没有则自动从网上下载。为每张图片增加通道维度以适配 CNN 模型的输入需求。将图片的像素值缩放至 [0, 1] 区间提高模型的训练性能。打印数据集的形状并验证每张图片是否为单通道灰度图。
3.2.2 代码片段
import os
import tensorflow as tf
from tensorflow.keras.datasets.mnist import load_dataclass DataSource:def __init__(self):# 数据集路径配置使用当前目录data_path os.path.join(os.getcwd(), data, mnist.npz)# 检查本地是否存在数据集if os.path.exists(data_path):(x_train, y_train), (x_test, y_test) load_data(pathdata_path)else:print(mnist.npz 文件不存在从网上下载数据集...)(x_train, y_train), (x_test, y_test) load_data()# 增加一个通道维度x_train x_train[..., tf.newaxis]x_test x_test[..., tf.newaxis]# 像素值缩放到 [0, 1] 之间x_train, x_test x_train / 255.0, x_test / 255.0self.train_images, self.train_labels x_train, y_trainself.test_images, self.test_labels x_test, y_test# 创建 DataSource 实例加载数据
data DataSource()# 打印训练集和测试集的形状
print(f训练集图片形状: {data.train_images.shape})
print(f训练集标签形状: {data.train_labels.shape})
print(f测试集图片形状: {data.test_images.shape})
print(f测试集标签形状: {data.test_labels.shape})# 验证是否为单通道
print(f训练集单张图片通道数: {data.train_images.shape[-1]})
print(f测试集单张图片通道数: {data.test_images.shape[-1]})3.2.3 代码解释
1.导入库
os用于文件和目录的路径操作。tensorflow用于加载 MNIST 数据集并进行张量操作。
2.定义 DataSource 类
检查数据集是否存在于 data 目录中。如果存在则加载本地数据集否则自动从网上下载。增加通道维度将每张图片从 (28, 28) 形状扩展为 (28, 28, 1)以适应 CNN 模型的输入格式。像素值缩放将图片的像素值从 [0, 255] 缩放到 [0, 1] 区间提高模型训练的效率和收敛速度。
3.创建 DataSource 实例
实例化 DataSource 类并加载数据将数据集保存在 train_images、train_labels、test_images 和 test_labels 中。
4.打印数据集的形状
输出训练集和测试集的图片形状与标签形状。检查每张图片的通道数是否为 1确保数据为灰度图。
3.2.4 结果与分析 训练集图片形状: (60000, 28, 28, 1)
训练集标签形状: (60000,)
测试集图片形状: (10000, 28, 28, 1)
测试集标签形状: (10000,)
训练集单张图片通道数: 1
测试集单张图片通道数: 1 1.预期结果分析
形状正确训练集有 60,000 张图片测试集有 10,000 张图片每张图片大小为 (28, 28, 1)。通道数每张图片应为单通道灰度图。
2.潜在问题与解决方案
数据集不存在如果程序提示 mnist.npz 文件不存在确保程序有网络访问权限以从网上下载数据集。维度错误如果图片形状不符合 (28, 28, 1)检查是否正确添加了新维度。
3.实际应用
预处理后的数据可直接用于训练 CNN 模型提高模型的训练效率。数据集结构清晰确保了模型输入格式的一致性。
3.3 搭建卷积神经网络CNN模型
3.3.1 实现目的
本步骤旨在构建一个卷积神经网络CNN用于对 MNIST 手写数字数据集进行分类。卷积神经网络是一种适用于图像数据的深度学习模型通过卷积层提取特征并通过全连接层进行分类。本模型设计为一个简单的多层 CNN适用于 MNIST 数据集。
3.3.2 代码片段
from tensorflow.keras import layers, modelsclass CNN:def __init__(self):# 构建 Sequential 模型按层堆叠模型结构model models.Sequential([# 第1层卷积层 最大池化层layers.Conv2D(32, (3, 3), activationrelu, input_shape(28, 28, 1)),layers.MaxPooling2D((2, 2)),# 第2层卷积层 最大池化层layers.Conv2D(64, (3, 3), activationrelu),layers.MaxPooling2D((2, 2)),# 第3层卷积层layers.Conv2D(64, (3, 3), activationrelu),# 展平层 全连接层layers.Flatten(),layers.Dense(64, activationrelu),# 输出层10类用 softmax 激活函数layers.Dense(10, activationsoftmax)])# 打印模型结构model.summary()self.model model # 将模型存储为类的属性3.3.3 代码解释
1.导入所需模块
layers 和 models来自 TensorFlow 的 Keras API分别用于创建网络层和模型。
2.模型构建
Sequential顺序模型按层堆叠每一层。卷积层提取图像的局部特征通过 ReLU 激活函数引入非线性。 第1层32 个 3x3 卷积核输入形状为 (28, 28, 1)。第2层64 个 3x3 卷积核。第3层64 个 3x3 卷积核。
3.池化层
最大池化层每次将 2x2 区域的最大值作为特征减少特征维度。
4.展平层
将卷积层输出的多维张量展平为一维向量便于输入到全连接层。
5.全连接层
Dense全连接层包含 64 个神经元并使用 ReLU 激活函数。
6.输出层
Dense输出层包含 10 个神经元对应 10 个类别使用 softmax 激活函数进行多分类。
7.模型摘要
model.summary()打印模型结构包括每层的输出形状和参数数量。
3.3.4 结果此结果在下一段代码打印与分析 1.Conv2D (卷积层)
功能提取图像特征如边缘、纹理等。输出形状(None, 26, 26, 32)表示卷积后的输出尺寸为 26×26每个像素点有 32 个通道。参数数量 (Param #)320。这由卷积核的数量和大小决定。
2.MaxPooling2D (最大池化层)
功能缩减图像尺寸保留重要特征减少参数。输出形状(None, 13, 13, 32)池化层将图像尺寸缩小了一半。
3.Flatten (展平层)
功能将多维的特征图展平为一维供全连接层使用。输出形状(None, 576)将图像的特征展平为 576 维向量。
4.Dense (全连接层)
功能用于分类或回归任务将展平的特征映射到输出类别上。输出形状第一层为 (None, 64)第二层为 (None, 10)表示 10 个输出类别。
5.总参数数量
Total params (总参数数量) 93,322Trainable params (可训练参数) 93,322Non-trainable params (不可训练参数) 0
3.4 训练模型、保存结果与可视化
3.4.1 实现目的
本部分的目的是对构建的卷积神经网络CNN进行训练并在训练过程中记录日志、保存模型检查点以便可视化和模型的复用。训练结束后打印测试结果以评估模型性能。
3.4.2 代码片段
import numpy as np
from datetime import datetime
from tensorflow.keras.callbacks import TensorBoard, ModelCheckpoint
# 忽略警告
import warnings
warnings.filterwarnings(ignore, categoryUserWarning)class Train:def __init__(self):self.network CNN() # 创建CNN实例self.data DataSource() # 加载数据集def train(self):# 设置 TensorBoard 日志路径logdir ./logs/scalars/ datetime.now().strftime(%Y%m%d-%H%M%S)tensorboard_cb TensorBoard(log_dirlogdir)# # 设置模型检查点路径# check_path ./ckpt/cp-{epoch:04d}.ckpt# save_model_cb ModelCheckpoint(check_path, save_weights_onlyTrue, verbose1)# 设置模型检查点路径每5个epoch保存一次check_path ./ckpt/cp-{epoch:04d}.weights.h5save_model_cb tf.keras.callbacks.ModelCheckpoint(filepathcheck_path, # 修改文件后缀为 .weights.h5save_weights_onlyTrue,verbose1)# 编译模型self.network.model.compile(optimizeradam,losssparse_categorical_crossentropy,metrics[accuracy])# 训练模型并保存日志training_history self.network.model.fit(self.data.train_images,self.data.train_labels,epochs10,validation_data(self.data.test_images, self.data.test_labels),callbacks[tensorboard_cb, save_model_cb])# 保存模型为 .keras 格式os.makedirs(./keras, exist_okTrue)self.network.model.save(./keras/model.keras)print(模型已保存为 ./keras/model.keras)# 打印最终测试结果test_loss, test_acc self.network.model.evaluate(self.data.test_images, self.data.test_labels)print(f准确率{test_acc * 100:.2f}%共测试了 {len(self.data.test_labels)} 张图片)print(平均误差, np.average(training_history.history[loss]))if __name__ __main__:mnist_train Train()mnist_train.train()3.4.3 代码解释
1.引入必要的库
TensorBoard 和 ModelCheckpoint 用于训练过程的监控和模型权重保存。warnings 模块用于忽略不必要的警告信息保持输出清晰。
2.初始化训练实例
Train 类的 __init__() 方法创建了 CNN 模型实例并加载了数据源。
3.训练配置
TensorBoard 可视化 配置 TensorBoard 的日志路径每次运行生成新的日志目录使用当前时间戳命名。模型检查点 使用 ModelCheckpoint 在每个 epoch 结束后保存模型权重。文件名以 cp-{epoch:04d}.weights.h5 形式保存确保每个 epoch 都有独立的权重文件。
4.模型编译
使用 Adam 优化器和 sparse_categorical_crossentropy 损失函数。指定 accuracy 为评估指标用于监控训练和验证过程的分类准确率。
5.模型训练
训练数据和标签通过 fit() 方法传入训练 10 个 epoch。每个 epoch 结束时验证集上的损失和准确率会被计算并打印。使用回调函数记录训练过程的 TensorBoard 日志并在每 5 个 epoch 保存一次模型权重。
6.模型保存
训练完成后将模型保存为 .keras 格式方便后续加载和预测。
7.模型评估
使用 evaluate() 方法在测试集上评估模型性能并打印准确率和平均损失。
3.4.4 结果与分析 Epoch 1/10
1871/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - accuracy: 0.8945 - loss: 0.3399
Epoch 1: saving model to ./ckpt/cp-0001.weights.h5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 14s 6ms/step - accuracy: 0.8947 - loss: 0.3394 - val_accuracy: 0.9853 - val_loss: 0.0450
Epoch 2/10
1867/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - accuracy: 0.9863 - loss: 0.0462
Epoch 2: saving model to ./ckpt/cp-0002.weights.h5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 11s 6ms/step - accuracy: 0.9863 - loss: 0.0462 - val_accuracy: 0.9860 - val_loss: 0.0424
Epoch 3/10
1871/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - accuracy: 0.9899 - loss: 0.0324
Epoch 3: saving model to ./ckpt/cp-0003.weights.h5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 11s 6ms/step - accuracy: 0.9899 - loss: 0.0324 - val_accuracy: 0.9875 - val_loss: 0.0379
Epoch 4/10
1871/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - accuracy: 0.9918 - loss: 0.0257
Epoch 4: saving model to ./ckpt/cp-0004.weights.h5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 11s 6ms/step - accuracy: 0.9918 - loss: 0.0257 - val_accuracy: 0.9916 - val_loss: 0.0264
Epoch 5/10
1870/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - accuracy: 0.9948 - loss: 0.0178
Epoch 5: saving model to ./ckpt/cp-0005.weights.h5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 11s 6ms/step - accuracy: 0.9948 - loss: 0.0178 - val_accuracy: 0.9906 - val_loss: 0.0293
Epoch 6/10
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - accuracy: 0.9952 - loss: 0.0138
Epoch 6: saving model to ./ckpt/cp-0006.weights.h5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 11s 6ms/step - accuracy: 0.9952 - loss: 0.0138 - val_accuracy: 0.9919 - val_loss: 0.0270
Epoch 7/10
1868/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - accuracy: 0.9962 - loss: 0.0119
Epoch 7: saving model to ./ckpt/cp-0007.weights.h5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 11s 6ms/step - accuracy: 0.9962 - loss: 0.0119 - val_accuracy: 0.9925 - val_loss: 0.0293
Epoch 8/10
1874/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - accuracy: 0.9977 - loss: 0.0079
Epoch 8: saving model to ./ckpt/cp-0008.weights.h5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 11s 6ms/step - accuracy: 0.9977 - loss: 0.0079 - val_accuracy: 0.9894 - val_loss: 0.0419
Epoch 9/10
1870/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - accuracy: 0.9972 - loss: 0.0080
Epoch 9: saving model to ./ckpt/cp-0009.weights.h5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 11s 6ms/step - accuracy: 0.9972 - loss: 0.0080 - val_accuracy: 0.9921 - val_loss: 0.0317
Epoch 10/10
1870/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - accuracy: 0.9977 - loss: 0.0072
Epoch 10: saving model to ./ckpt/cp-0010.weights.h5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 11s 6ms/step - accuracy: 0.9977 - loss: 0.0072 - val_accuracy: 0.9921 - val_loss: 0.0382
模型已保存为 ./keras/model.keras
313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 2ms/step - accuracy: 0.9886 - loss: 0.0526
准确率99.21%共测试了 10000 张图片
平均误差 0.032886080257594581.结果分析
训练表现随着 epoch 数的增加模型的训练准确率逐渐提高损失函数逐渐降低。测试集表现在测试集上的准确率达到了 99.21%表明模型在 MNIST 数据集上有非常好的表现。平均误差训练的平均误差较低表明模型已成功拟合训练数据。
2.优化建议
正则化可以引入 Dropout 或 L2 正则化来防止过拟合。数据增强通过随机裁剪或旋转图片提高模型的泛化能力。
3.5 小标题加载模型并进行预测
3.5.1 实现目的
本步骤的目标是使用训练好的卷积神经网络CNN模型对手写数字图片进行预测验证模型的分类能力。通过加载保存的模型读取测试图片并显示模型的预测结果判断模型是否能够准确识别输入图片中的数字。
3.5.2 代码片段
# 步骤4加载模型并进行预测
from PIL import Imageclass Predict:def __init__(self):# 加载已训练的模型self.model tf.keras.models.load_model(./keras/model.keras)def predict(self, image_path):# 读取并预处理图片img Image.open(image_path).convert(L)img img.resize((28, 28)) # 确保图片大小为 28x28img_array np.array(img).reshape(1, 28, 28, 1) / 255.0 # 归一化# 进行预测prediction self.model.predict(img_array)predicted_label np.argmax(prediction[0])print(f{image_path} - 预测数字为{predicted_label})# 测试预测
if __name__ __main__:app Predict()app.predict(./test_images/7_0.png)app.predict(./test_images/0_3.png)app.predict(./test_images/9_9.png)
3.5.3 代码解释
1.加载模型
使用 tf.keras.models.load_model() 加载保存为 model.keras 格式的训练模型。该模型已经通过训练并保存在目录 ./keras 下。
2.读取和预处理图片
使用 PIL 库中的 Image.open() 读取指定路径的图片并将其转换为灰度模式L。使用 img.resize((28, 28)) 将图片大小调整为 28x28以符合模型的输入要求。使用 np.array() 将图片转换为 NumPy 数组并 reshape 为 (1, 28, 28, 1)以便输入到模型中进行预测。最后对像素值归一化到 [0, 1] 范围内。
3.模型预测
使用 self.model.predict() 对图片数据进行预测得到一个概率数组。使用 np.argmax() 获取预测结果中概率最高的类别标签即模型认为的数字。
4.测试代码
代码通过调用 app.predict()对三张测试图片进行预测并打印结果到控制台。
3.5.4 结果与分析 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 95ms/step
./test_images/7_0.png - 预测数字为7
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 20ms/step
./test_images/0_3.png - 预测数字为0
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 19ms/step
./test_images/9_9.png - 预测数字为9 1.预测分析
这些结果表明模型对这几张测试图片的识别非常准确。 对于输入图片 7_0.png模型成功预测为数字 7。对于输入图片 0_3.png模型成功预测为数字 0。对于输入图片 9_9.png模型成功预测为数字 9。
2.模型表现
模型在这些测试图片上的预测结果全部正确说明模型在训练过程中已经学习到了有效的特征。预测速度较快每次预测耗时在 20ms-95ms 之间表明模型推理效率较高。
3.优化建议
异常处理 在加载图片时增加异常捕获以避免文件缺失或路径错误导致程序崩溃 try:img Image.open(image_path).convert(L)
except FileNotFoundError:print(f文件未找到: {image_path})批量预测 如果需要对多张图片进行预测可以编写循环批量加载和预测提升效率。