【深度之眼】Pytorch框架班第五期-模型容器之nn.Sequential代码调试

模型容器(Containers)

在这里插入图片描述

nn.Sequential

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

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

在这里插入图片描述

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

代码调试

1、在71行设置断点,进入LeNetSequential这个类。
在这里插入图片描述
2、运行到24行进入到nn.Sequential这个类中。
在这里插入图片描述
3、在24行由于池化层和nn.Sequential的构建都在这一行,所以我们先进入池化层,然后退出来,再进入nn.Sequential类中。在这里插入图片描述
我们可以看到nn.Sequential类继承于Module类,所以它包含8个有序的字典来管理属性。程序首先判断输入的数据类型是不是OrderedDict有序字典类型,不是进入else语句。

在这里插入图片描述
通过for循环取出每一个网络层,采用self.add_module类方法,将网络层添加到类中。
在这里插入图片描述
4、返回到主函数,运行完self.feature的代码,我们可以看到在self的module中多了key为feature,value为Sequential的值。
在这里插入图片描述
而在feature中的module里面多了6个网络层,他们是按照顺序构建的。当LeNetSequential完成船舰子模块后,我们接下来就要进行子模块的拼接。
在这里插入图片描述
5、进入76行的output = net(fake_img),来观察forward是怎么实现的。
在这里插入图片描述
此时我们会进入Module的__call__函数。
在这里插入图片描述
6、我们运行到541行,并进入self.forward函数,查看其实现方法。
在这里插入图片描述
此时,我们来到了LeNetSequential这个类当中。只要把x分给self.feature这个Sequential,那么程序就会实现Sequential中的六个网络层的前向传播。
在这里插入图片描述
7、进入self.features查看其实现方法,由于Sequential继承于Module,因此我们又一次进入到Module类的__call__函数中,我们继续点击到541行,并进入。
在这里插入图片描述
此时我们来到了Sequential类的forward函数中。利用for循环对Sequential中的网络层进行for循环的forward。
在这里插入图片描述

由于当前层的output就是下一层的input,所以我们要注意数据的格式,形状和大小。
在这里插入图片描述
以此类推。这样我们就实现了使用Sequential构建一个LeNet,然后实现了前向传播。
我们打印出网络结构,网络层是没有名称的,只能通过序号进行索引,而不能通过网络的名称进行索引。
在这里插入图片描述

nn.SequentialOrderDict

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.SequentialOrderDict

1、在72行设置断点,并进入LeNetSequentialOrderDict类。
在这里插入图片描述

运行至51行,进入池化层后退出来,再进入self.features的SequentialOrderDict类中。
在这里插入图片描述
2、我们进入到nn.Sequential类中的__init__()函数中,由于我们传入的类型为OrderedDict所以程序进入第一个for循环中。代码会将Dict中的key和value取出来加入到Sequential中。

在这里插入图片描述

此时,key的值为conv1,value为Conv2d卷积层。for循环后续以此类推。

在这里插入图片描述

退回到主程序中,我们可以发现,net中的feature的_modules中每个网络层都有名称,我们可以通过名称索引网络层。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值