Pytorch学习笔记(深度之眼)(4)之模型容器

21 篇文章 2 订阅
17 篇文章 1 订阅

1.容器.Containers

在这里插入图片描述nn.Sequential是nn.module的容器,用于按顺序包装一组网络层。
在这里插入图片描述

code

import torch.nn as nn


class LeNetSequential(nn.Module):
    def __init__(self, classes):
        super(LeNetSequential, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 6, 5),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Conv2d(6, 16, 5),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),)

        self.classifier = nn.Sequential(
            nn.Linear(16*5*5, 120),
            nn.ReLU(),
            nn.Linear(120, 84),
            nn.ReLU(),
            nn.Linear(84, classes),)

    def forward(self, x):
        x = self.features(x)
        x = x.view(x.size()[0], -1)  # 展开,形状变换
        x = self.classifier(x)
        return x

在__init__()模块中,采用sequential()对卷积层和池化层进行包装,把sequential类属性赋予feature,然后对三个全连接层进行sequential包装,赋值为classifier类属性,这就完成了模型构建的第一步。foward构建了前向传播过程,只有三行,非常简洁。

我们用sequential构建LeNet,LeNet中有一个features,类型为sequential,sequential中有六个网络层,以序号(0)-(5)命名;还有一个classifier,一样是sequential。这里存在一个问题,这里的网络层是没有名字的,是通过序号索引的,如果在一个上千层的网络中,很难采用序号去进行索引每一个网络层。这时候可以对网络层进行命名,这就是第二种sequential的方法,对sequential输入一个头有序的字典,以这种方式构建网络,代码如下所示。

class LeNetSequentialOrderDict(nn.Module):
    def __init__(self, classes):
        super(LeNetSequentialOrderDict, self).__init__()

        self.features = nn.Sequential(OrderedDict({
            'conv1': nn.Conv2d(3, 6, 5),
            'relu1': nn.ReLU(inplace=True),
            'pool1': nn.MaxPool2d(kernel_size=2, stride=2),

            'conv2': nn.Conv2d(6, 16, 5),
            'relu2': nn.ReLU(inplace=True),
            'pool2': nn.MaxPool2d(kernel_size=2, stride=2),
        }))

        self.classifier = nn.Sequential(OrderedDict({
            'fc1': nn.Linear(16*5*5, 120),
            'relu3': nn.ReLU(),

            'fc2': nn.Linear(120, 84),
            'relu4': nn.ReLU(inplace=True),

            'fc3': nn.Linear(84, classes),
        }))

    def forward(self, x):
        x = self.features(x)
        x = x.view(x.size()[0], -1)
        x = self.classifier(x)
        return x

总结

nn.Sequential是nn.module的容器,用于按顺序包装一组网络层:

顺序性:各网络层之间严格按照顺序构建;
自带forward():自带的forward里,通过for循环依次执行前向传播运算;

2.容器.ModuleList

![在这里插入图片描述](https://img-blog.csdnimg.cn/20201227173401577.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQ1ODY2NzE4,size_16,color_FFFFFF,t_70

class ModuleList(nn.Module):
    def __init__(self):
        super(ModuleList, self).__init__()
        self.linears = nn.ModuleList([nn.Linear(10, 10) for i in range(20)])  # 列表生成式,采用for循环

    def forward(self, x):
        for i, linear in enumerate(self.linears):
            x = linear(x)
        return x
        
net = ModuleList()

通过单步调试,进入了nn.ModuleList的init()函数当中,通过代码可以发现,如果mpdules不是空的话,则会不断进行叠加,得到linear。

可以看到,通过nn.ModuleList可以简便地建立一个二十层的全连接网络模型。

3.容器.moduleLDict

在这里插入图片描述

class ModuleDict(nn.Module):
    def __init__(self):
        super(ModuleDict, self).__init__()
        self.choices = nn.ModuleDict({
            'conv': nn.Conv2d(10, 10, 3),
            'pool': nn.MaxPool2d(3)
        })

        self.activations = nn.ModuleDict({
            'relu': nn.ReLU(),
            'prelu': nn.PReLU()
        })

    def forward(self, x, choice, act):
        x = self.choices[choice](x)
        x = self.activations[act](x)
        return x

net = ModuleDict()

fake_img = torch.randn((4, 10, 32, 32))

output = net(fake_img, 'conv', 'relu')

容器总结

nn.Sequential:顺序性:各网络层之间严格按顺序执行,常用于block构建;
nn.ModuleList:迭代性,常用于大量重复网的构建,通过for循环实现重复构建;
nn.ModuleDict:索引性,常用于可选择的网络层;


相关函数:

1.x.view(x.size()[0], -1)

这句话一般出现在model类的forward函数中,具体位置一般都是在调用分类器之前。分类器是一个简单的nn.Linear()结构,输入输出都是维度为一的值,x = x.view(x.size(0), -1) 这句话的出现就是为了将前面多维度的tensor展平成一维。

iew()函数的功能根reshape类似,用来转换size大小。x = x.view(batchsize, -1)中batchsize指转换后有几行,而-1指在不告诉函数有多少列的情况下,根据原tensor数据和batchsize自动分配列数。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值