深度学习-->卷积神经网络(LeNet)

发布时间 2023-08-04 15:58:26作者: o-Sakurajimamai-o

LeNet:

# LeNet


import d2lzh as d2l
import mxnet as mx
from mxnet import autograd, gluon, init, nd
from mxnet.gluon import loss as gloss, nn
import time

# 构建模型

# 输入数据:神经网络的输入是一个4维张量,形状为(批量大小, 通道数, 高度, 宽度)。这里的通道数表示图像的颜色通道数,对于灰度图像为1,对于RGB图像为3。
#
# 第1个卷积层:输入的4维张量通过第一个卷积层。这个卷积层会对输入进行卷积操作,得到6个输出通道的特征图。使用sigmoid激活函数处理特征图。
#
# 第1个最大池化层:经过第1个卷积层的输出被送入第1个最大池化层。最大池化层将特征图的空间维度(高度和宽度)减小一半,并保留每个2x2区域内的最大值。
#
# 第2个卷积层:第1个最大池化层的输出被送入第2个卷积层。这个卷积层将6个输入通道的特征图转换为16个输出通道的特征图。同样使用sigmoid激活函数。
#
# 第2个最大池化层:经过第2个卷积层的输出被送入第2个最大池化层。这个池化层也会将特征图的空间维度减小一半。
#
# 全连接层1:第2个最大池化层的输出被展平为一个1维张量,并送入全连接层1。这个全连接层有120个神经元,使用sigmoid激活函数。
#
# 全连接层2:全连接层1的输出被送入全连接层2。这个全连接层有84个神经元,同样使用sigmoid激活函数。
#
# 输出层:全连接层2的输出被送入输出层。这是一个没有显式激活函数的全连接层,通常称为“输出层”。它有10个神经元,对应于最终的分类类别数量。
#
# 输出结果:输出层的结果就是最终的预测结果,其中每个神经元对应一个类别的预测概率。通常,我们会选取概率最高的类别作为最终的预测类别。


net = nn.Sequential()  # 创建一个空的神经网络容器
net.add(nn.Conv2D(channels=6, kernel_size=5, activation='sigmoid'),
        # 添加第一个卷积层,有6个输出通道,卷积核大小为5x5,使用sigmoid激活函数
        nn.MaxPool2D(pool_size=2, strides=2),
        # 添加第一个最大池化层,池化窗口大小为2x2,步幅为2
        nn.Conv2D(channels=16, kernel_size=5, activation='sigmoid'),
        # 添加第二个卷积层,有16个输出通道,卷积核大小为5x5,使用sigmoid激活函数
        nn.MaxPool2D(pool_size=2, strides=2),
        # 添加第二个最大池化层,池化窗口大小为2x2,步幅为2
        # Dense会默认将(批量大小, 通道, 高, 宽)形状的输入转换成
        # (批量大小, 通道 * 高 * 宽)形状的输入
        nn.Dense(120, activation='sigmoid'),
        # 添加一个全连接层,有120个神经元,使用sigmoid激活函数.
        # 进入这个全连接层之前,会被展平,也就是从一个4维张量(batch_size, channels, height, width)
        # 转换为一个2维张量(batch_size, channels * height * width)。激活函数使用sigmoid。
        nn.Dense(84, activation='sigmoid'),
        # 添加另一个全连接层,有84个神经元,使用sigmoid激活函数
        nn.Dense(10))  # 最后添加一个输出层,有10个神经元,用于分类任务

ctx = d2l.try_gpu()

# 构造样本

# 构造一个高和宽均为28的单通道数据样本,并逐层进行前向计算来查看每个层的输出形状。

# 创建输入数据

x = nd.random_uniform(shape=(1, 1, 28, 28))  # 创建一个形状为(1, 1, 28, 28)的随机输入张量

net.initialize()  # 初始化神经网络

# 对每一层进行前向计算,并打印输出形状

for layer in net:  # 对神经网络中的每一层进行循环遍历
    x = layer(x)  # 将输入数据通过当前层进行前向计算
    print(layer.name, 'output shape:\t', x.shape)  # 打印当前层的名称和输出形状

# 获取数据和训练模型

batch_size = 256  # 定义批量大小
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size=batch_size)  # 加载Fashion-MNIST数据集


# 计算精确率
def evaluate_accuracy(data_iter, net, ctx):  # 定义计算精确率的函数
    acc_sum, n = nd.array([0], ctx=ctx), 0  # 初始化正确分类数和样本总数

    for x, y in data_iter:  # 对数据迭代器进行遍历,获取输入和标签
        x, y = x.as_in_context(ctx), y.as_in_context(ctx).astype('float32')  # 将标签转换为浮点数类型
        acc_sum += (net(x).argmax(axis=1) == y).sum()  # 统计正确分类的个数
        n += y.size  # 统计样本总数
    return acc_sum.asscalar() / n  # 返回精确率(正确分类数除以样本总数)


# 训练模型
def train(net, train_iter, test_iter, batch_size, trainer, num_epochs):  # 定义训练模型的函数
    loss = gloss.SoftmaxCrossEntropyLoss()  # 定义交叉熵损失函数

    for epoch in range(num_epochs):  # 对每个epoch进行循环
        train_loss, train_acc, n, start = 0.0, 0.0, 0, time.time()  # 初始化训练损失、训练精确率、样本数和起始时间
        for data, label in train_iter:  # 对训练数据进行迭代
            data, label = data.as_in_context(ctx), label.as_in_context(ctx)
            with autograd.record():  # 开启自动求导
                output = net(data)  # 进行前向计算,获取模型输出
                _loss = loss(output, label).sum()  # 计算损失

            _loss.backward()  # 反向传播,计算梯度
            trainer.step(batch_size)  # 更新模型参数
            label = label.astype('float32')  # 将标签转换为浮点数类型

            train_loss += _loss.asscalar()  # 累加训练损失
            train_acc += (output.argmax(axis=1) == label).sum().asscalar()  # 累加训练精确率

            n += label.size  # 累加样本数
        test_acc = evaluate_accuracy(test_iter, net, ctx)  # 计算测试精确率

        print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f, ''time %.1f sec' % (
            epoch + 1, train_loss / n, train_acc / n, test_acc, time.time() - start))  # 打印每个epoch的训练损失、训练精确率、测试精确率和训练时间


# 训练模型

lr, num_epochs = 0.9, 5  # 定义学习率和训练的epoch数
net.initialize(force_reinit=True, ctx=ctx, init=init.Xavier())  # 强制初始化神经网络的参数,使用Xavier初始化方法

trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': lr})  # 定义优化器
train(net, train_iter, test_iter, batch_size, trainer, num_epochs)  # 训练模型,获取训练和测试精确率