ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

代码分析--模型的创建

2022-03-09 10:00:20  阅读:226  来源: 互联网

标签:nn -- 创建 代码 modules ReLU Sequential model Conv2d


https://blog.csdn.net/Dear_learner/article/details/122920181

 

构建模型的两大要素:
● 构建子模块(比如网络结构中的卷积层、池化层、激活层、全连接层);
● 拼接子模块(将子模块按照一定的顺序拼接起来,最终得到想到的网络结构)。

 

LeNet类继承了nn.Module,并且在__init__方法中实现了各个子模块的构建。

LetNet类里面的forward方法——通过调用forward方法来实现子模块的拼接操作。

 

在构造模型中继承了 nn.Module 类,所有的网络层都是继承于这个类的。

torch.nn: 这是 Pytorch 的神经网络模块,这里的 Module 就是它的子模块之一,另外还有几个与 Module 并列的子模块。如:

nn.init:权值初始化   nn.functional:函数的具体实现,如卷积,池化,激活等  nn.Parameter:张量子类,表示可学习的参数,如权重,偏置。

nn.Module:所有网络的基类,管理网络的属性。

 

在构造网络结构是需要继承 nn.Module 类,并重新构造 __init__和forward两个方法,但需要注意的有:
● 一般将网络中具有可学习参数的层(如卷积层、全连接层)放在构造函数 __init__中,当然也可以把不具有参数的层也放在里面;
● 一般把不具有可学习参数的层(如ReLU、dropout、BatchNormanation层)可放在构造函数中,也可不放在构造函数中,如果不放在构造函数__init__里面,则在forward方法里面可以使用nn.functional来代替;
● forward方法是必须要重写的,它是实现模型的功能,实现各个层之间的连接关系的核心。
例如:
1、将所有的层都放在构造函数 __init__中,然后在forward中将这些层按顺序连接起来。

2、将没有训练参数的层放到forward中,所以这些层没有出现在model中,但是在运行关系是在forward中通过torch.nn.function实现。

 

 

nn.Module的三种Sequential 实现方法:通过Sequential来包装层
即将几个层包装成一个大的层(块),然后直接调用包装成后的层。

第一种:Sequential 的输出结果的模型的每一层没有名称,默认是0,1,2,3来命名的。

 1 import torch.nn as nn
 2 
 3 model = nn.Sequential(
 4                       nn.Conv2d(3, 24, 3),
 5                       nn.ReLU(),
 6                       nn.Conv2d(24, 5, 3),
 7                       nn.ReLU())
 8 print(model)
 9 
10 #输出
11 Sequential(
12   (0): Conv2d(3, 24, kernel_size=(3, 3), stride=(1, 1))
13   (1): ReLU()
14   (2): Conv2d(24, 5, kernel_size=(3, 3), stride=(1, 1))
15   (3): ReLU()
16 )

第二种:可以给每一层添加名称,但是并不能通过名称来获取层,依然要通过索引来获取,即model[2]是正确的,而model[‘conv2’]是错误的。

import torch.nn as nn
from collections import OrderedDict
model = nn.Sequential(OrderedDict([
                  ('conv1', nn.Conv2d(1,20,5)),
                  ('relu1', nn.ReLU()),
                  ('conv2', nn.Conv2d(20,64,5)),
                  ('relu2', nn.ReLU())
                ]))
 
print(model)
print(model[2]) # 通过索引获取第几个层
"""
输出结果:
Sequential(
  (conv1): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))
  (relu1): ReLU()
  (conv2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))
  (relu2): ReLU()
)
Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))
"""

 

第三种:add_module方法是Sequential继承了父类Module的方法。

import torch.nn as nn
from collections import OrderedDict

model = nn.Sequential()
model.add_module("conv1",nn.Conv2d(1,20,5))
model.add_module('relu1', nn.ReLU())
model.add_module('conv2', nn.Conv2d(20,64,5))
model.add_module('relu2', nn.ReLU())
 
print(model)
print(model[2]) # 通过索引获取第几个层

”“”
输出结果:
Sequential(
  (conv1): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))
  (relu1): ReLU()
  (conv2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))
  (relu2): ReLU()
)
Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))
“”“

 

nn.Module中几个常见获取网络曾的方法:

def children(self):
 
def named_children(self):
 
def modules(self):
 
def named_modules(self, memo=None, prefix=''):
 
'''
注意:这几个方法返回的都是一个Iterator迭代器,故而通过for循环访问,当然也可以通过next
'''

总结:
(1)model.children()和model.named_children()方法返回的是迭代器iterator;

(2)model.children():每一次迭代返回的每一个元素实际上是 Sequential 类型,而Sequential类型又可以使用下标index索引来获取每一个Sequenrial 里面的具体层,比如conv层、dense层等;

(3)model.named_children():每一次迭代返回的每一个元素实际上是 一个元组类型,元组的第一个元素是名称,第二个元素就是对应的层或者是Sequential。


总结:

(1)model.modules()和model.named_modules()方法返回的是迭代器iterator;

(2)model的modules()方法和named_modules()方法都会将整个模型的所有构成(包括包装层、单独的层、自定义层等)由浅入深依次遍历出来,只不过modules()返回的每一个元素是直接返回的层对象本身,而named_modules()返回的每一个元素是一个元组,第一个元素是名称,第二个元素才是层对象本身。

(3)如何理解children和modules之间的这种差异性。注意pytorch里面不管是模型、层、激活函数、损失函数都可以当成是Module的拓展,所以modules和named_modules会层层迭代,由浅入深,将每一个自定义块block、然后block里面的每一个层都当成是module来迭代。而children就比较直观,就表示的是所谓的“孩子”,所以没有层层迭代深入。

标签:nn,--,创建,代码,modules,ReLU,Sequential,model,Conv2d
来源: https://www.cnblogs.com/ethan-tao/p/15983662.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有