注:仅用以记录学习
打印出来的网络结构如下:
- from torchvision import models
- model = models.resnet50(pretrained=False)
- print("model: ", model)
结构:
- ResNet(
- (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
- (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
- (layer1): Sequential(
- (0): Bottleneck(
- (conv1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
- (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- (downsample): Sequential(
- (0): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- )
- )
- (1): Bottleneck(
- (conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
- (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- )
- (2): Bottleneck(
- (conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
- (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- )
- )
- (layer2): Sequential(
- (0): Bottleneck(
- (conv1): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
- (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- (downsample): Sequential(
- (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)
- (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- )
- )
- (1): Bottleneck(
- (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
- (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- )
- (2): Bottleneck(
- (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
- (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- )
- (3): Bottleneck(
- (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
- (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- )
- )
- (layer3): Sequential(
- (0): Bottleneck(
- (conv1): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
- (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- (downsample): Sequential(
- (0): Conv2d(512, 1024, kernel_size=(1, 1), stride=(2, 2), bias=False)
- (1): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- )
- )
- (1): Bottleneck(
- (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
- (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- )
- (2): Bottleneck(
- (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
- (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- )
- (3): Bottleneck(
- (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
- (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- )
- (4): Bottleneck(
- (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
- (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- )
- (5): Bottleneck(
- (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
- (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- )
- )
- (layer4): Sequential(
- (0): Bottleneck(
- (conv1): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
- (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- (downsample): Sequential(
- (0): Conv2d(1024, 2048, kernel_size=(1, 1), stride=(2, 2), bias=False)
- (1): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- )
- )
- (1): Bottleneck(
- (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
- (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- )
- (2): Bottleneck(
- (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
- (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
- (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU(inplace=True)
- )
- )
- (avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
- (fc): Linear(in_features=2048, out_features=1000, bias=True)
- )
修改最后一层(fc层)代码:
用于特定的分类任务,其中最后一层全连接层的输出类别数量被指定为输入参数
- class ResNet50(nn.Module):
- def __init__(
- self,
- num_classes
- ):
- super().__init__()
- model = models.resnet50(pretrained=False)
-
- num_ftrs = model.fc.in_features #获取ResNet-50模型最后一层全连接层的输入特征数量
- model.fc = nn.Linear(num_ftrs, num_classes) #将原fc层替换为一个新的全连接层,其中输出特征数量为num_classes
-
- layers = [v for v in model.children()] # 获取ResNet-50模型的所有子模块(层)
- self.model = nn.Sequential(*layers[:-2]) # 创建一个新的nn.Sequential模块,包含ResNet-50模型的所有子模块,除了最后的两个子模块。这个nn.Sequential模块将用作新模型的主体部分。
- self.pool = layers[-2] # ResNet-50模型的倒数第二个子模块,即全局平均池化层
- self.fc = layers[-1] # 获取ResNet-50模型的最后一个子模块,即全连接层
-
- def forward(self, x, **kwargs): # 定义前向传播方法
- x = self.model(x) # [B, C, H, W] # 将输入x通过ResNet-50模型的主体部分传递,得到特征表示
- outs = Munch()
-
- x = self.fc(torch.flatten(self.pool(x), 1)) # 通过全局平均池化的特征进行扁平化,然后通过新的全连接层得到最终的输出
- outs.sup = x
- return outs