MindSpore基础教程:LeNet-5 神经网络在MindSpore中的实现与训练

MindSpore基础教程:LeNet-5 神经网络在MindSpore中的实现与训练

官方文档教程使用已经弃用的MindVision模块,本文是对官方文档的更新

深度学习在图像识别领域取得了显著的成功,LeNet-5 作为卷积神经网络的经典之作,在诸多研究和应用中占有重要地位。本文将详细介绍如何使用 MindSpore 框架实现并训练一个 LeNet-5 神经网络,专注于处理MNIST手写数字数据集。

前言

MindSpore 是华为推出的一种新型深度学习框架,旨在为用户提供高效、易用的编程体验。接下来,我们将通过实例来展示如何在 MindSpore 中构建、训练和评估一个经典的 LeNet-5 神经网络。

环境配置

MindSpore官网

LeNet-5 网络结构简介

LeNet-5 是一个简单的卷积神经网络,包含两个卷积层和三个全连接层。它经常被用于图像识别任务,特别是在处理像 MNIST 这样的手写数字数据集时表现出色。

数据集准备与预处理

首先,我们需要准备并预处理数据集。在这个例子中,我们将使用 MNIST 数据集。以下函数 create_dataset 负责加载数据集,并进行必要的预处理:

python 复制代码
def create_dataset(data_path, batch_size=32, repeat_size=1):
    """
    创建用于训练的MNIST数据集。

    此函数负责加载MNIST数据集,对数据进行预处理和转换,以便它们可以用于训练神经网络。数据预处理包括调整图像大小、重新缩放和类型转换。

    参数:
        data_path (str): MNIST数据集的路径。这应该是包含MNIST数据文件的目录路径。
        batch_size (int, 可选): 每个数据批次的大小。默认值为32。
        repeat_size (int, 可选): 数据集重复的次数。这用于增加数据集的大小。默认值为1。

    步骤:
        1. 加载MNIST数据集。
        2. 对图像执行大小调整操作,将图像大小统一调整为32x32像素。
        3. 对图像进行重新缩放和标准化处理。先将像素值缩放到0-1之间,然后进行标准化。
        4. 将图像的格式从高宽通道(HWC)转换为通道高宽(CHW)。
        5. 对标签进行类型转换,将其转换为整型(int32)。
        6. 对数据集进行洗牌、批处理和重复操作,以准备训练过程。

    返回:
        返回一个处理过的MNIST数据集,可以直接用于模型训练。

    注意:
        - 数据集的预处理步骤对于训练深度学习模型来说是非常重要的,它们会影响训练的效果和速度。
        - 调整batch_size和repeat_size可以影响模型训练时的内存消耗和速度。
    """
    mnist_dataset = ds.MnistDataset(data_path)

    resize_operation = vision.Resize((32, 32), interpolation=Inter.LINEAR)
    rescale_normalization_op = vision.Rescale(1 / 0.3081, -1 * 0.1307 / 0.3081)
    rescale_op = vision.Rescale(1.0 / 255.0, 0.0)
    hwc_to_chw_op = vision.HWC2CHW()
    type_cast_op = transforms.TypeCast(mstype.int32)

    mnist_dataset = mnist_dataset.map(input_columns="label", operations=type_cast_op)
    mnist_dataset = mnist_dataset.map(input_columns="image",
                                      operations=[resize_operation, rescale_op, rescale_normalization_op,
                                                  hwc_to_chw_op])
    mnist_dataset = mnist_dataset.shuffle(buffer_size=10000)
    mnist_dataset = mnist_dataset.batch(batch_size, drop_remainder=True)
    mnist_dataset = mnist_dataset.repeat(repeat_size)

    return mnist_dataset

这个函数将数据集中的图像调整为统一的大小,并进行重新缩放和标准化。

构建 LeNet-5 模型

LeNet-5 模型的构建在 LeNet5 类中实现。此类定义了网络的各层及其排列:

python 复制代码
class LeNet5(nn.Cell):
    """
    LeNet-5 神经网络结构。

    这是一个经典的卷积神经网络,通常用于图像识别任务。它包含了两个卷积层和三个全连接层。

    参数:
        num_class (int): 输出层的类别数量。默认为10,适用于MNIST数据集。
        num_channel (int): 输入图像的通道数。对于灰度图像,此值为1。

    组件:
        - conv1: 第一个卷积层,使用有效填充。
        - conv2: 第二个卷积层,同样使用有效填充。
        - fc1: 第一个全连接层。
        - fc2: 第二个全连接层。
        - fc3: 第三个全连接层,输出层。
        - relu: 激活函数,使用ReLU。
        - max_pool2d: 最大池化层。
        - flatten: 扁平化层,用于全连接层之前的数据转换。

    方法:
        - construct(x): 定义了前向传播的过程。
    """

    def __init__(self, num_class=10, num_channel=1):
        super(LeNet5, self).__init__()
        self.conv1 = nn.Conv2d(num_channel, 6, 5, pad_mode='valid')
        self.conv2 = nn.Conv2d(6, 16, 5, pad_mode='valid')
        self.fc1 = nn.Dense(16 * 5 * 5, 120, weight_init=Normal(0.02))
        self.fc2 = nn.Dense(120, 84, weight_init=Normal(0.02))
        self.fc3 = nn.Dense(84, num_class, weight_init=Normal(0.02))
        self.relu = nn.ReLU()
        self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)
        self.flatten = nn.Flatten()

    def construct(self, x):
        x = self.conv1(x)
        x = self.relu(x)
        x = self.max_pool2d(x)
        x = self.conv2(x)
        x = self.relu(x)
        x = self.max_pool2d(x)
        x = self.flatten(x)
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        x = self.relu(x)
        x = self.fc3(x)
        return x

训练模型

接下来,我们定义 train_network 函数来训练模型。此函数接受模型实例、数据集路径和其他训练参数:

python 复制代码
def train_network(model, epoch_size, data_path, repeat_size, checkpoint_callback):
    """
    训练神经网络模型。

    此函数负责初始化数据集,然后使用指定的模型进行训练。在训练过程中,它将记录损失并保存模型的检查点。

    参数:
        model (Model): 要训练的神经网络模型。
        epoch_size (int): 训练过程中遍历数据集的次数。
        data_path (str): 训练数据集的路径。
        repeat_size (int): 数据集的重复次数,用于扩充数据集。
        checkpoint_callback (Callback): 用于保存模型检查点的回调函数。

    过程:
        - 使用 `create_dataset` 函数创建训练数据集。
        - 调用模型的 `train` 方法进行训练。
        - 在训练过程中,会通过回调函数记录损失和保存检查点。

    注意:
        - 确保提供的 `data_path` 包含适当格式的数据。
    """
    print("============== 开始训练 ==============")
    ds_train = create_dataset(data_path, 32, repeat_size)
    model.train(epoch_size, ds_train, callbacks=[checkpoint_callback, LossMonitor(), TimeMonitor()],
                dataset_sink_mode=False)
    print("============== 训练结束 ==============")

主函数

最后,我们通过 train 函数和 parse_arguments 函数将所有步骤串联起来。train 函数负责初始化模型、损失函数、优化器和检查点回调,然后调用 train_network 进行训练:

python 复制代码
def train(args):
    """
    初始化并训练LeNet-5神经网络模型。

    此函数设置了网络模型、损失函数、优化器,并定义了模型检查点。然后,使用指定的参数调用 `train_network` 函数来进行模型的训练。

    参数:
        args (Namespace): 一个包含训练参数的命名空间对象。此对象应该包含以下属性:
            - epochs (int): 模型训练的迭代次数。
            - data_url (str): 训练数据集的路径。
            - output_path (str): 保存模型检查点的路径。

    过程:
        1. 创建 LeNet-5 网络实例。
        2. 定义损失函数为 Softmax Cross-Entropy。
        3. 定义优化器为 Momentum 优化器。
        4. 创建模型实例,并指定网络、损失函数、优化器和评估指标。
        5. 设置模型检查点配置。
        6. 初始化模型检查点回调函数。
        7. 调用 `train_network` 函数进行训练。

    注意:
        - 确保 `args` 对象包含正确和完整的训练参数。
        - 调整优化器和损失函数的参数可以对训练结果产生影响。
        - 模型检查点将保存在 `args.output_path` 指定的路径中。
    """
    net = LeNet5()
    net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction="mean")
    net_opt = nn.Momentum(net.trainable_params(), 0.01, 0.9)

    model = Model(net, net_loss, net_opt, metrics={"Accuracy": nn.Accuracy()})

    config_checkpoint = CheckpointConfig(save_checkpoint_steps=1875, keep_checkpoint_max=10)
    checkpoint_callback = ModelCheckpoint(prefix="checkpoint_lenet", directory=args.output_path,
                                          config=config_checkpoint)

    train_network(model, args.epochs, args.data_url, 1, checkpoint_callback)

推理

python 复制代码
# 加载网络
param_dict = load_checkpoint("/root/MyCode/pycharm/lenet5/ckpt/checkpoint_lenet-19_1884.ckpt")
network = LeNet5(num_class=NUM_CLASS, num_channel=1)  # 用您定义的LeNet5类创建模型实例
load_param_into_net(network, param_dict)  # 将参数加载到网络中
model = Model(network)


def predict_digit(img):
    # 图像预处理
    img = cv2.resize(img, (32, 32))  # 调整图像大小为32x32
    img = np.array(img, dtype=np.float32)  # 转换图像数据类型
    img = (img - 0.1307) / 0.3081  # 对图像进行标准化处理
    img = img[np.newaxis, np.newaxis, :, :]  # 改变图像形状以符合网络输入要求(1, 1, 32, 32)

    # 将图像数据转换为MindSpore张量
    img_tensor = Tensor(img)

    # 使用模型进行预测
    output = model.predict(img_tensor)

    # 将输出转换为概率分布
    probabilities = Softmax()(output)

    # 获取每个类别的概率
    probabilities_np = probabilities.asnumpy()[0]

    # 将概率转换为字典格式
    labels = [str(i) for i in range(10)]  # 类别标签,例如"0", "1", "2", ..., "9"
    probabilities_dict = {label: prob for label, prob in zip(labels, probabilities_np)}

    return probabilities_dict


gr.Interface(
    fn=predict_digit,
    inputs=gr.Image(image_mode='L'),
    outputs=gr.Label(num_top_classes=NUM_CLASS),
    live=False,
    css=".footer {display:none !important}",
    title="0-9数字画板",
    description="画0-9数字",
    thumbnail="https://raw.githubusercontent.com/gradio-app/real-time-mnist/master/thumbnail2.png"
).launch()

结论

通过本文的指南,您可以在 MindSpore 框架中实现并训练一个经典的 LeNet-5 神经网络。LeNet-5 在图像识别任务中展现了卓越的性能,而 MindSpore 的高效和易用性使得深度学习研究和开发更加便捷。您可以根据本文的指导进行实验,并根据需要调整网络结构和训练参数。

相关推荐
weixin_4487816213 分钟前
第T8周:猫狗识别
深度学习·神经网络·tensorflow
HenrySmale36 分钟前
信息科技伦理与道德0:课程安排
人工智能·科技·计算机视觉
yngsqq1 小时前
CAD 像素点显示图片——CAD二次开发 OpenCV实现
人工智能·opencv·计算机视觉
Luke Ewin1 小时前
一个基于OpenAI Whisper开发的音视频字幕文件生成工具
人工智能·whisper·音视频·语音识别·asr·语音转写·视频字幕生成
老马啸西风2 小时前
AgentGPT 在浏览器中组装、配置和部署自主 AI 代理 入门介绍
人工智能·ai·openai·agent·robot·deepseek·mcp
京东零售技术2 小时前
京东3D空间视频生成技术探索与应用
人工智能
Jamence2 小时前
多模态大语言模型arxiv论文略读(十六)
人工智能·语言模型·自然语言处理
武汉唯众智创2 小时前
人工智能(机器人)通识实验室解决方案
人工智能·机器人·人工智能实验室·人工智能通识实验室·人工智能通识·机器人通识实验室·机器人实验室
巷9552 小时前
深入理解卷积神经网络(CNN):从原理到实践
人工智能·神经网络·cnn