旷视MegEngine网络搭建
在 基本概念 中,介绍了计算图、张量和算子,神经网络可以看成一个计算图。在 MegEngine 中,按照计算图的拓扑结构,将张量和算子连接起来,即可完成对网络的搭建。MegEngine 提供了基于 functional 和基于 Module 的两种方式搭建网络。 functional 仅提供最基本的算子功能,数据连接的工作完全由用户完成; Module 对网络模块(包含若干算子及其参数的基本单元)进行了进一步的封装,代码更易复用和维护。
基于 functional 搭建网络
functional 包提供了常用的算子函数(如 conv2d() 、 batch_norm() 等)。这些函数接受参与计算的张量并返回计算结果。参与计算的张量通常包括两类:输入数据和算子自身的参数,其中后者是网路中需要学习的变量。比如,二维卷积( conv2d() )接受多通道的二维图像作为输入数据,把卷积核作为参数,输出经卷积操作后的多通道二维图像。
算子的输入和输出数据都是 Tensor 类型。算子的参数通常由 Parameter 类表示。 Parameter 是 Tensor 的子类,其对象(即网络参数)可以被优化器更新。更多内容参见 网络的训练和测试 。
下面的例子实现了一个两层卷积网络(使用 ReLU 作为激活函数):
import megengine as mge
import megengine.functional as F
import numpy as np

def two_layer_conv(x):
# (8, 3, 3, 3) 代表(输出信道数,输入信道数,卷积核高度,卷积核宽度)
conv_weight = mge.Parameter(np.random.randn(8, 3, 3, 3).astype(np.float32))
# 对于 8 个卷积核,提供 8 个 bias
conv_bias = mge.Parameter(np.zeros((1, 8, 1, 1), dtype=np.float32))
x = F.conv2d(x, conv_weight, conv_bias)
x = F.relu(x)
conv_weight = mge.Parameter(np.random.randn(16, 8, 3, 3).astype(np.float32))
conv_bias = mge.Parameter(np.zeros((1, 16, 1, 1), dtype=np.float32))
x = F.conv2d(x, conv_weight, conv_bias)
x = F.relu(x)
return x

输入形状为 (2, 3, 32, 32) 的张量

x = mge.tensor(np.random.randn(2, 3, 32, 32).astype(np.float32))
out = two_layer_conv(x)
print(out.shape)
输出:
(2, 16, 28, 28)
基于 Module 搭建网络
在上面的代码中,对于每一个需要参数的算子,需要单独定义其网络参数。由于“ conv + relu ”这样的组合出现了两次,代码显得臃肿。对于更加复杂的网络,这样的写法可读性、可复用性和可维护性会比较差。
为了更好的封装和复用算子, MegEngine 在 functional 基础上提供了 module 包。
megengine.module 包定义了抽象的网络模块基类 Module 。它是构造网络的基本单元,可以被组合和叠加。它定义了网络模块的基本接口和属性,如“前向传播”等。所有 Module 子类都需要实现 Module 定义的两个抽象方法,介绍如下:
init() :在构造方法中创建这个模块,包括定义网络参数、构造和连接其子模块等工作。
• forward() : 该方法定义前向传播计算流程。接受输入数据并返回前向传播的计算结果。注意, Module 对象是可被调用的 ( callable ),其实现就是 forward() 。
megengine.module 包提供了常用的网络基本模块,如 Conv2d 、Linear 等。以 Conv2d 为例,该类的 init() 方法定义并初始化卷积核参数,其 forward() 方法执行卷积操作。
基于各种常用的网络模块,可以方便地搭建非常复杂的网络。例如,上一个例子的网络定义可以简化成如下写法:
import megengine.module as M

为了演示,在这里定义了一个简单的卷积模块。注意: MegEngine 已经提供了更为通用的 Conv2d 模块。

class ConvReLU(M.Module):
def init(self, in_channels, out_channels):
# 先调用父类的初始化
super().init()

    # 定义卷积权重和 bias ,作为模块参数self.conv_weight = mge.Parameter(np.random.randn(out_channels, in_channels, 3, 3).astype(np.float32))self.conv_bias = mge.Parameter(np.zeros((1, out_channels, 1, 1), dtype=np.float32))# 将激活函数 ReLU 作为子模块self.relu = M.ReLU()def forward(self, x):x = F.conv2d(x, self.conv_weight, self.conv_bias)x = self.relu(x)return x

基于 ConvReLU ,定义一个两层卷积网络

class TwoLayerConv(M.Module):
def init(self):
super().init()
self.conv_relu1 = ConvReLU(3, 8)
self.conv_relu2 = ConvReLU(8, 16)

def forward(self, x):x = self.conv_relu1(x)x = self.conv_relu2(x)return x

输入形状为 (2, 3, 32, 32) 的张量

x = mge.tensor(np.random.randn(2, 3, 32, 32).astype(np.float32))
two_layer_conv_module = TwoLayerConv()
out = two_layer_conv_module(x)
print(out.shape)
输出:
(2, 16, 28, 28)
使用 Module 定义的网络比使用 functional 进一步封装了内部实现,更易复用,统一的接口使得代码更易维护。推荐使用 Module 搭建网络。
此外, Module 其它常用的方法如下:
• parameters() : 该方法返回包含网络参数的迭代器。
• named_parameters() : 该方法返回包含参数名称及对应网络参数的迭代器。
• state_dict():返回以参数名称和网络参数为键值对的有序字典,可用于保存训练好的模型。比如,对于上面定义的 ConvReLU 模块,打印它的一个实例的 state_dict :
conv_relu = ConvReLU(2, 3)
print(conv_relu.state_dict())
输出的参数信息有卷积的权重项 ‘conv_weight’ 和偏置项 ‘conv_bias’ :
OrderedDict([(‘conv_bias’, array([[[[0.]],

    [[0.]],[[0.]]]], dtype=float32)), ('conv_weight', array([[[[-0.53457755,  0.2799128 , -0.6624546 ],[-0.9222688 ,  1.2226251 , -0.5591961 ],[-0.45538583, -0.95166504,  1.1570141 ]],[[-0.89926094,  0.09956062, -0.7329557 ],[-0.67284465,  0.34817234,  0.6731445 ],[ 0.61970276,  1.8007269 ,  1.6130987 ]]],[[[ 1.7108068 , -1.7188625 , -0.52539474],[-0.04049037,  0.03099988, -1.4271212 ],[-0.9138133 ,  0.3976046 , -1.1582668 ]],[[-1.2193677 ,  0.24107741, -0.50833786],[ 0.9088649 , -0.2747458 , -0.1261102 ],[ 0.00594431,  0.65737075,  1.5280651 ]]],[[[ 0.24874896, -1.3824748 ,  2.2161844 ],[-0.6629168 ,  1.0220655 , -0.53007567],[ 0.37829646,  1.1993718 ,  1.0667052 ]],[[-0.66264534, -0.6392335 , -0.41280702],[ 1.7417566 ,  0.75295806, -0.4228349 ],[-0.94973356,  2.4136777 , -0.06665667]]]], dtype=float32))])

最后,来搭建更加复杂的、经典的 LeNet 网络,其结构如下图:

图1 LeNet ( http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf )
使用 Module 搭建 LeNet 的代码如下:
class LeNet(M.Module):
def init(self):
super(LeNet, self).init()
# 单信道图片, 两层 5x5 卷积 + ReLU + 池化
self.conv1 = M.Conv2d(1, 6, 5)
self.relu1 = M.ReLU()
self.pool1 = M.MaxPool2d(2, 2)
self.conv2 = M.Conv2d(6, 16, 5)
self.relu2 = M.ReLU()
self.pool2 = M.MaxPool2d(2, 2)
# 两层全连接 + ReLU
self.fc1 = M.Linear(16 * 5 * 5, 120)
self.relu3 = M.ReLU()
self.fc2 = M.Linear(120, 84)
self.relu4 = M.ReLU()
# 分类器
self.classifier = M.Linear(84, 10)

def forward(self, x):x = self.pool1(self.relu1(self.conv1(x)))x = self.pool2(self.relu2(self.conv2(x)))# F.flatten 将原本形状为 (N, C, H, W) 的张量x从第一个维度(即C)开始拉平成一个维度,# 得到的新张量形状为 (N, C*H*W) 。 等价于 reshape 操作: x = x.reshape(x.shape[0], -1)x = F.flatten(x, 1)x = self.relu3(self.fc1(x))x = self.relu4(self.fc2(x))x = self.classifier(x)return x

输入形状为 (2, 1, 32, 32) 的张量

x = mge.tensor(np.random.randn(2, 1, 32, 32).astype(np.float32))
le_net = LeNet()

调用网络,即执行 le_net 的 forward 成员方法,返回网络处理结果

out = le_net(x)
print(out.shape)
输出:
(2, 10)

旷视MegEngine网络搭建相关推荐

  1. 旷视MegEngine核心技术升级

    旷视MegEngine核心技术升级 7 月 11 日,旷视研究院在 2020 WAIC · 开发者日「深度学习框架与技术生态论坛」上围绕 6 月底发布的天元深度学习框架(MegEngine)Beta ...

  2. 旷视MegEngine数据加载与处理

    旷视MegEngine数据加载与处理 在网络训练与测试中,数据的加载和预处理往往会耗费大量的精力. MegEngine 提供了一系列接口来规范化这些处理工作. 利用 Dataset 封装一个数据集 数 ...

  3. 旷视MegEngine基本概念

    旷视MegEngine基本概念 MegEngine 是基于计算图的深度神经网络学习框架. 本文简要介绍计算图及其相关基本概念,以及它们在 MegEngine 中的实现. 计算图(Computation ...

  4. 旷视ThunderNet网络学习笔记

    关于Thundernet的实现细节: 一.Backbone 部分 输入分辨率: 一般情况下,two-stage检测器的输入分辨率比较大,如FPN网络使用了800*800的分辨率,这虽然带来了一些优势但 ...

  5. 旷视SLAM组负责人刘骁:三维视觉与机器人

    点击我爱计算机视觉标星,更快获取CVML新技术 大家好,我是旷视研究院SLAM组负责人刘骁,很高兴能和大家分享机器人领域一些有关三维视觉技术的思考. 这次分享的主题集中在SLAM与三维重建两方面,大纲 ...

  6. 旷视天元 MegEngine 开源 CUDA INT4 量化源码实现

    当下人工智能技术正加速发展,渗透到云.边.端和应用的各个层面,与海量IoT设备进行深度融合,不断拓展应用场景.然而在AIoT场景中,嵌入式设备往往算力有限,难以承载庞大的AI模型.如何在资源有限的终端 ...

  7. 旷视提双边分支网络BBN:攻坚长尾分布的现实世界任务 | CVPR 2020 Oral

    作者 | 旷视研究院 出品 | AI科技大本营(ID:rgznai100) 导读:本文是旷视 CVPR 2020 论文系列解读文章,也是 CVPR 2020 Oral展示论文之一,它揭示了再平衡方法解 ...

  8. LIVE 预告 | 旷视王剑锋:全卷积网络,可以实现更好的端到端目标检测吗?

    目标检测是计算机视觉领域的一个基础研究主题,它利用每张图像的预定义类标签来预测边界框.大多数主流检测器使用的是基于锚的标签分配和非极大值抑制(NMS)等手动设计.近来,很多研究者提出方法通过距离感知和 ...

  9. 北航、旷视联合,打造最强实时语义分割网络

    来源:AI科技评论 编辑:Camel 导语:MSFNet在Cityscapes测试集上达到77.1%mIoU/41FPS(注意是1024*2048),在Camvid测试集上达到75.4 mIoU/97 ...

最新文章

  1. stm32 flash和sram
  2. PHP框架编写和应用知识点,写PHP框架需要具备那些知识?
  3. Unix网络协议分析
  4. Linux文件查找命令find
  5. dnSpy 强大的.Net反编译软件
  6. JAVA和javascrito_JAVA 和JavaScript的split方法异同
  7. C#如何去掉字符串中所有空格
  8. leetcode题解54-螺旋矩阵
  9. git HEAD detached from origin 问题的解决
  10. 实验室计算机系统权限管理规程,计算机辅助建筑设计实验室使用规范(试行)...
  11. 《巴菲特的第一桶金》读书笔记
  12. 106572050018总是发彩信?实用办法关闭彩信提醒
  13. 监控摄像机的视频摘要(Video Summarization of Surveillance Cameras)
  14. python输入一个浮点数、输出其整数部分和小数部分_输入一个浮点数,并输出该数的整数部分和小数部分...
  15. 前额出现痘斑是肝脏含过多毒素所致(图)
  16. JdbcTemplate空指针异常
  17. spring cloud: TX-LCN解决分布式事务
  18. 【U8+】用友U8成本管理模块下,定额分配标准中无法取到新增存货的数据。
  19. ethereumjs/ethereumjs-icap
  20. 金山WPS软件测试笔试题目总结

热门文章

  1. flask 学习实战项目实例
  2. HA: SHERLOCK 靶机渗透取证
  3. learning to rank_排序
  4. dataframe构建
  5. CVPR2020论文解析:视频分类Video Classification
  6. 2021年大数据HBase(二):HBase集群安装操作
  7. Laravel Redis操作大全
  8. PyCharm 配置远程python解释器和在本地修改服务器代码
  9. 零起点学算法01——第一个程序Hello World!
  10. cs嵌html5页面,在.cs c#.net中包含HTML页面