欢迎光临散文网 会员登陆 & 注册

深度学习快速上手——基于 MegEngine 的 LeNet 快速训练与部署

2023-01-29 16:55 作者:旷视天元MegEngine  | 我要投稿

|本文转载自知乎  @嘿呀嘿   个人 blog。

1. 前言

Megengine 是旷视科技开发的一款训练推理一体化的深度学习框架,类似于 pytorch,tensorflow。

使用 Megengine 可以快速实现常见的深度学习模型,本文将使用 Megengine 实现手写数字识别,以完成深度学习的两大步骤:训练和预测。通过本文,读者对深度学习的最基本流程和 Megengine 框架的使用方法有大致了解。

2. 环境安装

在命令行输入下列语句即可安装 Megengine ,建议使用 python 版本为 3.5 到 3.8

安装完成后可以在命令行测试是否安装成功。

3. 训练

本部分训练代码来自 Megengine 官方教程,需要详细了解细节请前往 MegEngine 快速上手

3.1 数据集准备

3.1.1 下载数据集

深度学习的第一步为准备数据集,通常会为数据集写一个接口来访问数据集,并对数据进行预处理。

Megengine 中已经实现了 MNIST 数据集的接口,我们可以通过以下代码直接获取。如果想要制作或使用其他数据集,可以点击这里进行学习。

3.1.2 数据加载及预处理

上面使用 MNIST()完成数据集的加载和 Dataset 的构建,接下来将对数据进行加载,修改数据。使用 DataLoader、Sampler 和 Transform 实现。

DataLoader

功能: 构建可迭代的数据装载器,非常灵活地从数据集连续获取小批量数据 参数:

  • dataset – 需要从中分批加载的数据集。

  • sampler (Optional) – 定义从数据集中采样数据的策略。

  • transform (Optional) – 定义抽样批次的转换策略。对数据需要作的变换 默认:None

  • ...

RandomSampler

功能:创建一个列表,包含所有数据的索引,可实现数据的随机取样 参数:

  • dataset – 待采样的目标数据集。

  • batch_size – 使用 batch 方法时指定 batch 大小。

  • drop_last – 如果 batch 大小不能整除数据集大小时,为 True 则放弃最后一个不完整的batch; 为 False 则最后一个batch可能比较小。默认:False

  • ...

3.2 模型

接下来定义网络结构,LeNet 的网络结构如下图所示。 [图片上传失败...(image-41aaca-1660811354056)] 定义网络结构主要为两步:定义网络子模块和连接网络子模块。如下代码所示,使用 init 方法创建子模块,forward()方法连接子模块。

  • class LeNet 继承自 Module 的类,想要了解更多关于构建模型的细节,可以参考参考 module 定义模型结构

3.3 训练准备

  • GradManager 负责计算梯度,管理需要优化的参数,用attach()方法添加,加入的参数才会被计算保存梯度值。对梯度计算了解更多请点击 Autodiff 基本原理与使用

  • optimizer 选择使用的优化方法,这里使用 Optimizer.SGD(随机梯度下降法)作为优化器,对优化器了解更多请点击使用 optimizer 优化参数

3.4 训练迭代

接下来进入程序的主逻辑,开始训练模型。使用两个嵌套循环,一个大循环为一个 epoch,遍历一次数据集,计算一次准确度。

每个小循环为一个 batch,将一批数据传入模型中,进行前向计算得到预测概率,使用交叉熵(cross_entropy)来计算 loss, 接着调用 GradManager.backward 方法进行反向计算并且记录每个 tensor 的梯度信息。然后使用 Optimizer.step 方法更新模型中的参数。由于每次更新参数后不自动清除梯度,所以还需要调用 clear_grad 方法。

3.5 保存模型

常用的神经网络都具有非常大数量级的参数,每次训练需要花费很长时间,为了能够训练中断后能够按照上次训练的成果接着训练,我们可以每10个 epoch 保存一次模型(或更多)。保存模型有几种方法,如表所示。方法详细介绍请点击保存与加载模型。https://www.megengine.org.cn/doc/stable/zh/user-guide/model-development/serialization/index.html#save-load-entire-model

我们选择保存加载检查点,既可以用于恢复训练也可以推理。保存时调用 megengine.save()方法,参数如下:

然后就可以愉快的进行训练了,观察训练结果,当 loss 下降到一定地步,准确率满足要求后,终止训练.

如果训练发生中断,可以调用 load()方法和 optimizer.load_state_dict()方法,对模型的加载,重新开始训练。代码如下:

4. 推理

上面几个章节已经完成深度学习大部分内容,已经能够产生一个需要的算法模型。这个算法对准备好的数据集有比较好的拟合效果,但是我们的最终目的是用模型进行推理,即能够对新的数据进行预测。这将是下面介绍的内容。

首先有一种很简单的方法,使用 python 加载模型并设定 model.eval(),代码如下所示,这样就可以简单调用训练好的模型用以实际。

不过在实际部署中,还需要考虑部署环境,推理速度等因素,所以从训练好模型到部署落地还有很长的路。Megengine 由于其设计特点——训练推理一体化,可以方便地将训练模型部署。这将是下一章介绍的内容,下一章将使用 C++ 调用 Megengine lite,进行高效部署。

参考文献

[1]: MegEngine 快速上手 [2]: Yann LeCun, Corinna Cortes, and CJ Burges. Mnist handwritten digit database. ATT Labs [Online]. Available: http://yann.lecun.com/exdb/mnist, 2010. [3]: Yann LeCun, Léon Bottou, Yoshua Bengio, and Patrick Haffner. Gradient-based learning applied to document recognition. Proceedings of the IEEE, 86(11):2278–2324, 1998.

附录:train.py

C++ 推理

前半部分我们完成了深度学习的训练,得到了LeNet训练权重文件,后面我们将使用训练权重文件导出静态图模型。并使用C++调用模型完成实际部署的模拟。

准备工作

在上一章中,我们提到有四种保存模型的方法,如下表所示,为了训练方便起见,保存了checkpoint文件。但实际部署中我们经常使用静态图模型,所以我们首先要完成静态图导出。

到处静态图在megengine中有较完整的教程,请参考导出序列化模型文件(Dump)。主要分为三步:

  1. 将循环内的前向计算、反向传播和参数优化代码提取成单独的函数,如下面例子中的 train_func()

  2. 将网络所需输入作为训练函数的参数,并返回任意你需要的结果(如输出结果、损失函数值等);

  3. 用 jit 模块中的 trace 装饰器来装饰这个函数,将其中的代码变为静态图代码。

在上一章最后的附录train.py中有dump静态图的方法,代码如下:

调用dump_mge方法即可完成静态图导出。

inference代码

代码的主逻辑为:

  1. 创建Network

  2. 使用load_model()载入模型

  3. 使用stb预处理图片(加载和resize),然后归一化,载入进input tensor

  4. 使用network->forward()和network->wait()完成推理逻辑。

  5. 获取模型输出tensor,并对其进行处理。

推理代码为:

推理的代码已经编写完成,还需要对其进行编译,根据我们部署的平台,选择编译方式,比如安卓,可以选择交叉编译。这里我们选择部署在本机上。

可以使用g++进行编译,编译时需要连接MegEngine Lite库文件,并且准备好stb头文件。

配置环境

由于使用C++调用MegEngine Lite接口,所以我们首先需要编译出MegEngine Lite的库。 安装MegEngine:从源代码编译MegEngine。请参考编译MegEngine Lite。

  1. clone MegEngine工程,进入根目录

  1. 安装MegEngine所需的依赖

  1. 使用cmake进行编译工程得到c++推理所需的库文件

编译完成后,需要的库文件所在地址为:

MegEngine/build_dir/host/MGE_WITH_CUDA_OFF/MGE_INFERENCE_ONLY_ON/Release/install/lite/

这里为了在g++编译时添加库文件方便,可以将库文件地址设为环境变量

安装stb: stb是一个轻量化的图片加载库,可以替代opencv完成图片的解码。想要使用它,只需要将对应的头文件包含到项目内,不像opencv需要编译产生链接库。

这里为了调用方便直接将stb的项目下载下来:

想要使用图片加载函数stbi_load(),只需在cpp文件中define STB_IMAGE_IMPLEMENTATION并且include stb_image.h头文件

动态链接编译

最后使用g++或者clang完成对inference.cpp的编译。

  • -I选项添加编译时头文件搜索路径

  • -l添加动态链接库

  • -L添加动态链接库搜索路径

编译后会在本目录下会得到inference二进制文件

执行二进制文件

准备好一张手写数字图片,将图片与模型放到同一目录,执行编译好的文件即可得到推理结果。

以上就完成了LeNet神经网络的部署。

更多 MegEngine 信息获取,您可以查看:

文档:https://www.megengine.org.cn/doc/stable/zh/ 

深度学习框架 MegEngine 官网:https://www.megengine.org.cn/

GitHub 项目:https://github.com/MegEngine,或加入 MegEngine 用户交流 QQ 群:1029741705


深度学习快速上手——基于 MegEngine 的 LeNet 快速训练与部署的评论 (共 条)

分享到微博请遵守国家法律