ResNet 概念 吴恩达老师讲的ResNet理论,通俗易懂(吴恩达老师yyds)传送门
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import torchfrom torch import nnfrom torch.nn import functional as Ffrom d2l import torch as d2lclass Residual (nn.Module): def __init__ (self, input_channels, num_channels, use_1x1conv=False , strides=1 ): super ().__init__() self.conv1 = nn.Conv2d(input_channels, num_channels, kernel_size=3 , padding=1 , stride=strides) self.conv2 = nn.Conv2d(num_channels, num_channels, kernel_size=3 , padding=1 ) if use_1x1conv: self.conv3 = nn.Conv2d(input_channels, num_channels, kernel_size=1 , stride=strides) else : self.conv3 = None self.bn1 = nn.BatchNorm2d(num_channels) self.bn2 = nn.BatchNorm2d(num_channels) def forward (self, X ): Y = F.relu(self.bn1(self.conv1(X))) Y = self.bn2(self.conv2(Y)) if self.conv3: X = self.conv3(X) Y += X return F.relu(Y)
ResNet实现
ResNet则使用4个由残差块组成的模块,每个模块使用若干个同样输出通道数的残差块。 第一个模块的通道数同输入通道数一致。之后的每个模块在第一个残差块里将上一个模块的通道数翻倍,并将高和宽减半。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 b1 = nn.Sequential(nn.Conv2d(1 , 64 , kernel_size=7 , stride=2 , padding=3 ), nn.BatchNorm2d( 64 ), nn.ReLU(), nn.MaxPool2d(kernel_size=3 , stride=2 , padding=1 )) def resnet_block (input_channels, num_channels, num_residuals, first_block=False ): blk = [] for i in range (num_residuals): if i == 0 and not first_block: blk.append(Residual(input_channels, num_channels, use_1x1conv=True , strides=2 )) else : blk.append(Residual(num_channels, num_channels)) return blk
1 2 3 4 5 b2 = nn.Sequential(*resnet_block(64 , 64 , 2 , first_block=True )) b3 = nn.Sequential(*resnet_block(64 , 128 , 2 )) b4 = nn.Sequential(*resnet_block(128 , 256 , 2 )) b5 = nn.Sequential(*resnet_block(256 , 512 , 2 ))
封装一个整的网络
1 2 net = nn.Sequential(b1, b2, b3, b4, b5, nn.AdaptiveAvgPool2d( (1 , 1 )), nn.Flatten(), nn.Linear(512 , 10 ))
打印一下每一层的信息
1 2 3 4 X = torch.rand(size=(1 , 1 , 224 , 224 )) for layer in net: X = layer(X) print (layer.__class__.__name__,'output shape:\t' , X.shape)
Sequential output shape: torch.Size([1, 64, 56, 56])
Sequential output shape: torch.Size([1, 64, 56, 56])
Sequential output shape: torch.Size([1, 128, 28, 28])
Sequential output shape: torch.Size([1, 256, 14, 14])
Sequential output shape: torch.Size([1, 512, 7, 7])
AdaptiveAvgPool2d output shape: torch.Size([1, 512, 1, 1])
Flatten output shape: torch.Size([1, 512])
Linear output shape: torch.Size([1, 10])