今天在写一个分类网络时,要使用nn.Sequential中的一个模块,因为nn.Sequential中模块都没有名字,我一时竟无从下笔。于是决定写这篇博客梳理pytorch的nn.Module类,看完这篇博客,你大概率可以学会:

  • 提取nn.Sequential中任意一个模块
  • 能初始化一个网络的所有权重,不管是随机初始化还是使用权重文件
  • 对nn.Module类有个总体把握

1 __init__方法

  我们先不看代码,自己小脑袋里想一想这个类应该有什么东西。既然这个类是和各种layer相关,里面一定存着各种layer,如卷积或者relu,肯定还会有layer对应的权重。没错,这些东西类里都有:


from ..backends.thnn import backend as thnn_backend
def __init__(self):
        self._backend = thnn_backend
        self._parameters = OrderedDict()
        self._buffers = OrderedDict()
        self._backward_hooks = OrderedDict()
        self._forward_hooks = OrderedDict()
        self._forward_pre_hooks = OrderedDict()
        self._modules = OrderedDict()
        self.training = True

  其中_modules和_parameters就是存储这些的,那么剩下这些奇奇怪怪的属性是什么呢?第一个奇怪的东西就是这个_backend属性,他的值是thnn_backend,好像和torch的底层代码有关,有点麻烦啊!不用怕,这个属性我们只要大概了解它的意思就可以,对之后这个模块的使用没有任何影响。举个例子来帮助我们理解,想象说我们有maxpooling层,pytorch底层会用cudnn实现,也会用cunn实现,pytorch在前向传播时会自动选择一个速度最快的实现,这里thnn_backend就是指定我们前向传播时用thnn这种实现方式。更多过于backend的直觉理解可以参考这个thread

  第二个奇怪的东西就是_buffer属性,如果我说这个buffer存储的也是网络参数,你会感觉到更加迷惑吗?一个提示:batch norm的参数。(花一分钟想一想。)batch norm中除了有参数$ alpha $和$ beta $外,还有running_mean和running_var,这些在整个学习过程中也需要存储起来但是不需要学习的参数我们就把它们存储到_buffer中。

  第三个奇怪的东西就是3个钩子,这三个钩子具体的实现我可能很后面才会讲,不过为了一些好奇宝宝,如果我说forward_hook的功能是在module完成前向传播时做一些事,你能推断出其他两个钩子的功能吗?(答案

2 children方法和modules方法

  children方法和modules方法的作用是很类似的,我们先看一下children方法的代码。

def named_children(self):
    memo = set()
    for name, module in self._modules.items():
        if module is not None and module not in memo:
            memo.add(module)
            yield name, module
def children(self):
    for name, module in self.named_children():
        yield module

  我们看完代码发现children方法的作用就是把_modules遍历一遍,我们来看一下具体例子(你也可以自己在命令行中把这两个命令输入进去,尽量不要复制粘贴):

>>>model=nn.Sequential(nn.Linear(3,1), \
                       nn.Sequential(nn.BatchNorm2d(1), \
                       nn.Linear(1,3)))
>>> for m in model.children():
...     print(m)
Linear(in_features=3, out_features=1, bias=True)
Sequential(
  (0): BatchNorm2d(1, eps=1e-05, momentum=0.1, affine=True)
  (1): Linear(in_features=1, out_features=3, bias=True)
)    

  如果我们还要把更里层的modules提取出来,我们就需要用到modules方法:

def named_modules(self, memo=None, prefix=''):
    if memo is None:
        memo = set()
    if self not in memo:
       memo.add(self)     yield prefix, self    for name, module in self._modules.items():       if module is None:             continue       submodule_prefix = prefix + ('.' if prefix else '') + name       for m in module.named_modules(memo, submodule_prefix):         yield mdef modules(self):
    for name, module in self.named_modules():
        yeild module
>>> for m in model.modules():
...     print(m)
Sequential(
  (0): Linear(in_features=3, out_features=1, bias=True)
  (1): Sequential(
    (0): BatchNorm2d(1, eps=1e-05, momentum=0.1, affine=True)
    (1): Linear(in_features=1, out_features=3, bias=True)
  )
)
Linear(in_features=3, out_features=1, bias=True)
Sequential(
  (0): BatchNorm2d(1, eps=1e-05, momentum=0.1, affine=True)
  (1): Linear(in_features=1, out_features=3, bias=True)
)
BatchNorm2d(1, eps=1e-05, momentum=0.1, affine=True)
Linear(in_features=1, out_features=3, bias=True)  

了解了这两个方法你应该可以完成我们的第一个目标:提取nn.Sequential的任一个模块。在下一节中我们会完成我们的第二个目标,初始化权重。在结束之前给大家个小问题:有时候你只需要底层的module,而不需要module的子类,如nn.Sequential,那么怎么去除呢?

机器学习小贴士:支持向量机的意思就是我们最后选择的模型只与支持向量有关。

                                                  最后编辑于2018-10-1019:39:53 有什么错误请不吝赐教

pytroch nn.Module源码解析(1)的更多相关文章

  1. Cognitive Graph for Multi-Hop Reading Comprehension at Scale(ACL2019) 阅读笔记与源码解析

    论文地址为:Cognitive Graph for Multi-Hop Reading Comprehension at Scale github地址:CogQA 背景 假设你手边有一个维基百科的搜索 ...

  2. [源码解析] 深度学习流水线并行Gpipe(1)---流水线基本实现

    [源码解析] 深度学习流水线并行Gpipe(1)---流水线基本实现 目录 [源码解析] 深度学习流水线并行Gpipe(1)---流水线基本实现 0x00 摘要 0x01 概述 1.1 什么是GPip ...

  3. [源码解析] 深度学习流水线并行GPipe (2) ----- 梯度累积

    [源码解析] 深度学习流水线并行GPipe (2) ----- 梯度累积 目录 [源码解析] 深度学习流水线并行GPipe (2) ----- 梯度累积 0x00 摘要 0x01 概述 1.1 前文回 ...

  4. [源码解析] 深度学习流水线并行之PopeDream(1)--- Profile阶段

    [源码解析] 深度学习流水线并行之PopeDream(1)--- Profile阶段 目录 [源码解析] 深度学习流水线并行之PopeDream(1)--- Profile阶段 0x00 摘要 0x0 ...

  5. [源码解析] 深度学习流水线并行 PipeDream(3)--- 转换模型

    [源码解析] 深度学习流水线并行 PipeDream(3)--- 转换模型 目录 [源码解析] 深度学习流水线并行 PipeDream(3)--- 转换模型 0x00 摘要 0x01 前言 1.1 改 ...

  6. [源码解析] 深度学习流水线并行 PipeDream(4)--- 运行时引擎

    [源码解析] 深度学习流水线并行 PipeDream(4)--- 运行时引擎 目录 [源码解析] 深度学习流水线并行 PipeDream(4)--- 运行时引擎 0x00 摘要 0x01 前言 1.1 ...

  7. [源码解析] 深度学习分布式训练框架 horovod (21) --- 之如何恢复训练

    [源码解析] 深度学习分布式训练框架 horovod (21) --- 之如何恢复训练 目录 [源码解析] 深度学习分布式训练框架 horovod (21) --- 之如何恢复训练 0x00 摘要 0 ...

  8. [源码解析] PyTorch 流水线并行实现 (1)--基础知识

    [源码解析] PyTorch 流水线并行实现 (1)--基础知识 目录 [源码解析] PyTorch 流水线并行实现 (1)--基础知识 0x00 摘要 0x01 历史 1.1 GPipe 1.2 t ...

  9. [源码解析] PyTorch 流水线并行实现 (2)--如何划分模型

    [源码解析] PyTorch 流水线并行实现 (2)--如何划分模型 目录 [源码解析] PyTorch 流水线并行实现 (2)--如何划分模型 0x00 摘要 0x01 问题 0x01 自动平衡 1 ...

随机推荐

  1. FFT学习笔记

    快速傅里叶变换FFT(Fast Fourior Transform) 先说一下它能干嘛qwq ​ 傅里叶变换有两种,连续傅里叶变换和离散傅里叶变换,OI中主要用来快速计算多项式卷积. 等一下,卷积是啥 ...

  2. MySQL2.字符集乱码

    MySQL2.字符集 此节记录下MySQL出现乱码的原因.还是参考小册子~ 字符集简介 计算机中只能存储二进制数据,建立字符与二进制数据的映射关系来存储字符. 从两方面考虑: 1.界定清楚字符范围,即 ...

  3. python笔记01-05

    作者:Vamei 出处:http://www.cnblogs.com/vamei https://blog.csdn.net/flyfrommath/article/details/77447587 ...

  4. git rejected - non-fast-forward

    di第一次提交时可能提示此错误,应该是.gitignore冲突,建议码云创建时不要初始化,如果已经出现了.可以从git  repostitory里合并. 参考:https://blog.csdn.ne ...

  5. gitlab 随笔

    输入: $ git init $ git add . $ git commit -m 'init commit' 绿色部分为gitlab网页的项目创建后下面的ssh路径,也可以通过查看gitlab网页 ...

  6. 详解Django的CSRF认证

    1.csrf原理 csrf要求发送post,put或delete请求的时候,是先以get方式发送请求,服务端响应时会分配一个随机字符串给客户端,客户端第二次发送post,put或delete请求时携带 ...

  7. C#获取指定的文件是否是内部特殊版本的代码

    把内容过程经常用到的内容片段珍藏起来,下面的内容内容是关于C#获取指定的文件是否是内部特殊版本的内容,希望对各朋友有所用处. using System;using System.Diagnostics ...

  8. Java常见的10个异常

    1.NullPointerException: 空指针异常,当操作一个 null 对象的方法或属性时会抛出这个异常.是一个很头疼的异常,因为它是运行时异常,不需要手动捕获,但运行时碰到这个异常会中断程 ...

  9. java servlet的域对象

    在进行网络编程中的项目时 经常用到的域对象主要包括以下三种: 1. ServletContext  作用范围比较大 代码如下: //一个请求代码: ServletContext sc = reques ...

  10. MongoDB,从数组中删除对象

    { _id: 5150a1199fac0e6910000002, name: 'some name, items: [{ id: 23, name: 'item name 23' },{ id: 24 ...