ASGNet论文和代码解读( 三 )


PS:的nn.()详解
它的形参由手册可以查得,前三个参数是必须手动提供的,后面的有默认值 。接下来将一一介绍:
2.21 函数完整代码如下:参数为block=、=64、=3、=1
# block:基础块的类型,是BasicBlock,还是Bottleneck# planes:当前块的输入输入通道数# blocks:块的数目def _make_layer(self, block, planes, blocks, stride=1):downsample = None# downSample的作用于在残差连接时 将输入的图像的通道数变成和卷积操作的尺寸一致# 根据ResNet的结构特点,一般只在每层开始时进行判断if stride != 1 or self.inplanes != planes * block.expansion:# 通道数恢复成一致downsample = nn.Sequential(nn.Conv2d(self.inplanes, planes * block.expansion,kernel_size=1, stride=stride, bias=False),BatchNorm(planes * block.expansion),)layers = []layers.append(block(self.inplanes, planes, stride, downsample))self.inplanes = planes * block.expansionfor i in range(1, blocks):layers.append(block(self.inplanes, planes))return nn.Sequential(*layers)
在使用构造时,self. = 128、block.=4
所以128 != 64*4,这时将会定义一个:通过一个卷积和批归一化将通道数恢复成一致
将参数传递给.(block(self., , , ))
四个参数为:=128、=64、=1、
接下来转到block类中,为

ASGNet论文和代码解读

文章插图
2.22 类(下采样)
其完整代码如下:
class Bottleneck(nn.Module):expansion = 4def __init__(self, inplanes, planes, stride=1, downsample=None):super(Bottleneck, self).__init__()self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False)self.bn1 = BatchNorm(planes)self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride,padding=1, bias=False)self.bn2 = BatchNorm(planes)self.conv3 = nn.Conv2d(planes, planes * self.expansion, kernel_size=1, bias=False)self.bn3 = BatchNorm(planes * self.expansion)self.relu = nn.ReLU(inplace=True)self.downsample = downsampleself.stride = stridedef forward(self, x):residual = xout = self.conv1(x)out = self.bn1(out)out = self.relu(out)out = self.conv2(out)out = self.bn2(out)out = self.relu(out)out = self.conv3(out)out = self.bn3(out)if self.downsample is not None:residual = self.downsample(x)out += residualout = self.relu(out)return out
中:def (self, , , =1, =None):
四个参数为:=128、=64、=1、
中定义了一些卷积、归一化和激活函数,然后中
对照,out = self.conv1(x) out = self.bn1(out) out = self.relu(out)
out = self.conv2(out) out = self.bn2(out) out = self.relu(out)
out = self.conv3(out) out = self.bn3(out)
if self.downsample is not None:residual = self.downsample(x)out += residualout = self.relu(out)return out
最后改变输入self. =* block.=256,=3,循环1-2两次,加上上一次正好构造了三次网络(只有第一次有):
self.inplanes = planes * block.expansionfor i in range(1, blocks):layers.append(block(self.inplanes, planes))
正好符合,即:
PS:., ., ., .都是同理,都是通过得到的
符合下图的50-layer结构:
2.3 .py的 2.31 、、、、 2.2小节有讲解,在定义好每一个layer之后:
PS:中()和()的区别
从定义上讲:
二者返回的都是模型的迭代器,只不过一个返回的是子模块的迭代器,另一个返回的是所有模块的迭代器 。
写个程序测试一下:
import torchimport torch.nn as nnclass TestModule(nn.Module):def __init__(self):super(TestModule,self).__init__()self.layer1 = nn.Sequential(nn.Conv2d(16,32,3,1),nn.ReLU(inplace=True))self.layer2 = nn.Sequential(nn.Linear(32,10))def forward(self,x):x = self.layer1(x)x = self.layer2(x)model = TestModule()for name, module in model.named_children():print('children module:', name)for name, module in model.named_modules():print('modules:', name)