前向传播代码解析——你真的明白了吗?

我们知道预训练模型通常包括两部分:def _ _init _ _(self,last_conv_stride=2): def forward(self,x): 两部分,前者主要用来继承nn.Module模块,并载入预训练模型(如ResNet-50),后者用来前向传播:

  def forward(self, x):
    # shape [N, C, H, W]
    x = self.base(x) 
    x = F.avg_pool2d(x, x.size()[2:])  
    # shape [N, C]
    x = x.view(x.size(0), -1) 
    return x

千万别小瞧了这几行代码,里面包含的内容可不少,接下来我们来逐行解析。

在解析之前,我们要先复习Python里的一段基础知识。

一、对[ : n]、[m : ]、[-1]、[:-1]、[::-1]、[2::-1]和[1:]的理解

要理解它们,最好的方法就是举例,我们来看下面的例子:

import numpy as np
a=[1,2,3.4,5]
print(a)
   


input:[ 1 2 3 4 5 ]

1.[ : n] 代表取列表中的第一项到第n项

2.[m : ] 代表取列表中的第m+1项到最后一项(注意Python的列表规则)

3.a[-1] 取最后一个元素,即5

4.a[:-1] 除了最后一个取全部,即[1 2 3 4 ]

5.a[::-1] 取从后向前(相反)的元素,即[5 4 3 2 1 ]

6.a[2::-1] 取从下标为2的元素翻转读取,即[3 2 1 ]

6.a[1:] 取第二个到最后一个元素,即[2 3 4 5]

二、前向传播源码解析

咱们一行一行的来看

x = self.base(x) 

base是一个基础网络,如果你用的预训练网络是ResNet-50,那base就是ResNet-50。x是输入input,x的维度一般是[N,C,H,W],其中N代表batchsize,C代表channel,H/W分别是高和宽

x = F.avg_pool2d(x, x.size()[2:])

这一行是在干嘛呢?没错,是在池化。首先avg_pool2有好几个参数,我们这里就写常用的:avg_pool2d(input, kernel_size, stride=None, padding=0, ceil_mode=False),那么显然,上面代码中,x就是input;x.size()[2:]就是池化核的大小,那我们如何理解第二个参数x.size()[2:]呢?很简单,x的维度我们刚才说了是[N,C,H,W],所以x.size()[2:]就表示取x.size()的第三个到最后一个元素,也就是[H W],所以池化核的大小为H * W

x = x.view(x.size(0), -1)

紧接着看到我们的重点:x = x.view(x.size(0), -1) 

首先,在pytorch中,view()函数是用来改变tensor的形状的,例如将2行3列的tensor变为1行6列,其中-1表示会自适应的调整剩余的维度。在CNN中卷积或者池化之后需要接全连接层,所以需要把多维度的tensor展平成一维,x.view(x.size(0), -1)就实现了这个功能。通过上面的分析,我们很容易得出x.size(0)表示 N(batchsize),那么-1就表示自适应的调整剩余维度,那么剩余了谁?不就是 [C H W] 嘛。所以最后通过x.view(x.size(0), -1)将tensor的结构转换为了(batchsize, C*H*W),即将 [C H W] 拉直,然后就可以和fc层连接了.

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值