import torch.nn as nn
from torchinfo import summary
import torch
class BasicBlock(nn.Module):
expansion = 1
def __init__(self, inplanes, planes, stride=1, downsample=None):
"""
:param inplanes: 输入通道数
:param planes: 输出通道数
:param stride: 步长
:param downsample: 基础结构里有一个从x直接连到下面的线,
如果上一个ResidualBlock的输出维度和当前的ResidualBlock的维度不一样,
那就对这个x进行downSample操作,如果维度一样,直接加就行了,这时直接output=x+residual
"""
super(BasicBlock, self).__init__()
self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=3)
self.bn1 = nn.BatchNorm2d(planes)
self.relu = nn.ReLU(inplace=True)
self.conv2 = nn.Conv2d(planes, planes, kernel_size=3)
self.bn2 = nn.BatchNorm2d(planes)
self.downsample = downsample
self.stride = stride
def forward(self, x):
residual = x
x = self.conv1(x)
x = self.bn1(x)
x = self.relu(x)
x = self.conv2(x)
x = self.bn2(x)
if self.downsample is not None:
residual = self.downsample(residual)
out =x+ residual
out = self.relu(out)
return out
class ResNet_18(nn.Module):
def __init__(self, block, layers, num_classes=1000):
"""
:param block: 调用basicblock
:param layers: 使用一个列表 储存想搭建的layer
:param num_classes: fc的输出维度
"""
self.inplanes = 64
super(ResNet_18, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3,bias=False)
self.bn1 = nn.BatchNorm2d(64)
self.relu = nn.ReLU(inplace=True)
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
self.layer1 = self.make_layer(block, 64, layers[0])
self.layer2 = self.make_layer(block, 128, layers[1], stride=2)
self.layer3 = self.make_layer(block, 256, layers[2], stride=2)
self.layer4 = self.make_layer(block, 512, layers[3], stride=2)
self.avgpool = nn.AvgPool2d(7, stride=1)
self.fc = nn.Linear(512 * block.expansion, num_classes)
for m in self.modules():
if isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
elif isinstance(m, nn.BatchNorm2d):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, 0)
#构建layer
def make_layer(self, block, planes, blocks, stride=1):
"""
:param block: 调用basicblock
:param planes: 输出通道大小
:param blocks: 调用列表
:param stride: 步长
:return: nn.Sequential(*layers)
"""
downsample = None
# 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),
# nn.BatchNorm2d(planes * block.expansion),
# )
layers = []
layers.append(block(self.inplanes, planes, stride, downsample))
self.inplanes = planes * block.expansion
for i in range(1, blocks):
layers.append(block(self.inplanes, planes))
return nn.Sequential(*layers)
def forward(self, x):
x = self.conv1(x)
x = self.bn1(x)
x = self.relu(x)
x = self.maxpool(x)
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
x = self.avgpool(x)
x = x.view(x.size(0), -1)
output = self.fc(x)
return output
resnet=ResNet_18(BasicBlock,[2,2,2,2])
summary(resnet)
结果:
=================================================================
Layer (type:depth-idx) Param #
=================================================================
ResNet_18 --
├─Conv2d: 1-1 9,408
├─BatchNorm2d: 1-2 128
├─ReLU: 1-3 --
├─MaxPool2d: 1-4 --
├─Sequential: 1-5 --
│ └─BasicBlock: 2-1 --
│ │ └─Conv2d: 3-1 36,928
│ │ └─BatchNorm2d: 3-2 128
│ │ └─ReLU: 3-3 --
│ │ └─Conv2d: 3-4 36,928
│ │ └─BatchNorm2d: 3-5 128
│ └─BasicBlock: 2-2 --
│ │ └─Conv2d: 3-6 36,928
│ │ └─BatchNorm2d: 3-7 128
│ │ └─ReLU: 3-8 --
│ │ └─Conv2d: 3-9 36,928
│ │ └─BatchNorm2d: 3-10 128
├─Sequential: 1-6 --
│ └─BasicBlock: 2-3 --
│ │ └─Conv2d: 3-11 73,856
│ │ └─BatchNorm2d: 3-12 256
│ │ └─ReLU: 3-13 --
│ │ └─Conv2d: 3-14 147,584
│ │ └─BatchNorm2d: 3-15 256
│ └─BasicBlock: 2-4 --
│ │ └─Conv2d: 3-16 147,584
│ │ └─BatchNorm2d: 3-17 256
│ │ └─ReLU: 3-18 --
│ │ └─Conv2d: 3-19 147,584
│ │ └─BatchNorm2d: 3-20 256
├─Sequential: 1-7 --
│ └─BasicBlock: 2-5 --
│ │ └─Conv2d: 3-21 295,168
│ │ └─BatchNorm2d: 3-22 512
│ │ └─ReLU: 3-23 --
│ │ └─Conv2d: 3-24 590,080
│ │ └─BatchNorm2d: 3-25 512
│ └─BasicBlock: 2-6 --
│ │ └─Conv2d: 3-26 590,080
│ │ └─BatchNorm2d: 3-27 512
│ │ └─ReLU: 3-28 --
│ │ └─Conv2d: 3-29 590,080
│ │ └─BatchNorm2d: 3-30 512
├─Sequential: 1-8 --
│ └─BasicBlock: 2-7 --
│ │ └─Conv2d: 3-31 1,180,160
│ │ └─BatchNorm2d: 3-32 1,024
│ │ └─ReLU: 3-33 --
│ │ └─Conv2d: 3-34 2,359,808
│ │ └─BatchNorm2d: 3-35 1,024
│ └─BasicBlock: 2-8 --
│ │ └─Conv2d: 3-36 2,359,808
│ │ └─BatchNorm2d: 3-37 1,024
│ │ └─ReLU: 3-38 --
│ │ └─Conv2d: 3-39 2,359,808
│ │ └─BatchNorm2d: 3-40 1,024
├─AvgPool2d: 1-9 --
├─Linear: 1-10 513,000
=================================================================
Total params: 11,519,528
Trainable params: 11,519,528
Non-trainable params: 0
=================================================================
Resnet-34
import torch.nn as nn
from torchinfo import summary
import torch
class BasicBlock(nn.Module):
expansion = 1
def __init__(self, inplanes, planes, stride=1, downsample=None):
"""
:param inplanes: 输入通道数
:param planes: 输出通道数
:param stride: 步长
:param downsample: 基础结构里有一个从x直接连到下面的线,
如果上一个ResidualBlock的输出维度和当前的ResidualBlock的维度不一样,
那就对这个x进行downSample操作,如果维度一样,直接加就行了,这时直接output=x+residual
"""
super(BasicBlock, self).__init__()
self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=3)
self.bn1 = nn.BatchNorm2d(planes)
self.relu = nn.ReLU(inplace=True)
self.conv2 = nn.Conv2d(planes, planes, kernel_size=3)
self.bn2 = nn.BatchNorm2d(planes)
self.downsample = downsample
self.stride = stride
def forward(self, x):
residual = x
x = self.conv1(x)
x = self.bn1(x)
x = self.relu(x)
x = self.conv2(x)
x = self.bn2(x)
if self.downsample is not None:
residual = self.downsample(residual)
out =x+ residual
out = self.relu(out)
return out
class ResNet_34(nn.Module):
def __init__(self, block, layers, num_classes=1000):
"""
:param block: 调用basicblock
:param layers: 使用一个列表 储存想搭建的layer
:param num_classes: fc的输出维度
"""
self.inplanes = 64
super(ResNet_34, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3,bias=False)
self.bn1 = nn.BatchNorm2d(64)
self.relu = nn.ReLU(inplace=True)
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
self.layer1 = self.make_layer(block, 64, layers[0])
self.layer2 = self.make_layer(block, 128, layers[1], stride=2)
self.layer3 = self.make_layer(block, 256, layers[2], stride=2)
self.layer4 = self.make_layer(block, 512, layers[3], stride=2)
self.avgpool = nn.AvgPool2d(7, stride=1)
self.fc = nn.Linear(512 * block.expansion, num_classes)
for m in self.modules():
if isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
elif isinstance(m, nn.BatchNorm2d):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, 0)
#构建layer
def make_layer(self, block, planes, blocks, stride=1):
"""
:param block: 调用basicblock
:param planes: 输出通道大小
:param blocks: 调用列表
:param stride: 步长
:return: nn.Sequential(*layers)
"""
downsample = None
# 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),
# nn.BatchNorm2d(planes * block.expansion),
# )
layers = []
layers.append(block(self.inplanes, planes, stride, downsample))
self.inplanes = planes * block.expansion
for i in range(1, blocks):
layers.append(block(self.inplanes, planes))
return nn.Sequential(*layers)
def forward(self, x):
x = self.conv1(x)
x = self.bn1(x)
x = self.relu(x)
x = self.maxpool(x)
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
x = self.avgpool(x)
x = x.view(x.size(0), -1)
output = self.fc(x)
return output
resnet=ResNet_34(BasicBlock,[3,4,6,3])
summary(resnet)
结果:
=================================================================
Layer (type:depth-idx) Param #
=================================================================
ResNet_18 --
├─Conv2d: 1-1 9,408
├─BatchNorm2d: 1-2 128
├─ReLU: 1-3 --
├─MaxPool2d: 1-4 --
├─Sequential: 1-5 --
│ └─BasicBlock: 2-1 --
│ │ └─Conv2d: 3-1 36,928
│ │ └─BatchNorm2d: 3-2 128
│ │ └─ReLU: 3-3 --
│ │ └─Conv2d: 3-4 36,928
│ │ └─BatchNorm2d: 3-5 128
│ └─BasicBlock: 2-2 --
│ │ └─Conv2d: 3-6 36,928
│ │ └─BatchNorm2d: 3-7 128
│ │ └─ReLU: 3-8 --
│ │ └─Conv2d: 3-9 36,928
│ │ └─BatchNorm2d: 3-10 128
│ └─BasicBlock: 2-3 --
│ │ └─Conv2d: 3-11 36,928
│ │ └─BatchNorm2d: 3-12 128
│ │ └─ReLU: 3-13 --
│ │ └─Conv2d: 3-14 36,928
│ │ └─BatchNorm2d: 3-15 128
├─Sequential: 1-6 --
│ └─BasicBlock: 2-4 --
│ │ └─Conv2d: 3-16 73,856
│ │ └─BatchNorm2d: 3-17 256
│ │ └─ReLU: 3-18 --
│ │ └─Conv2d: 3-19 147,584
│ │ └─BatchNorm2d: 3-20 256
│ └─BasicBlock: 2-5 --
│ │ └─Conv2d: 3-21 147,584
│ │ └─BatchNorm2d: 3-22 256
│ │ └─ReLU: 3-23 --
│ │ └─Conv2d: 3-24 147,584
│ │ └─BatchNorm2d: 3-25 256
│ └─BasicBlock: 2-6 --
│ │ └─Conv2d: 3-26 147,584
│ │ └─BatchNorm2d: 3-27 256
│ │ └─ReLU: 3-28 --
│ │ └─Conv2d: 3-29 147,584
│ │ └─BatchNorm2d: 3-30 256
│ └─BasicBlock: 2-7 --
│ │ └─Conv2d: 3-31 147,584
│ │ └─BatchNorm2d: 3-32 256
│ │ └─ReLU: 3-33 --
│ │ └─Conv2d: 3-34 147,584
│ │ └─BatchNorm2d: 3-35 256
├─Sequential: 1-7 --
│ └─BasicBlock: 2-8 --
│ │ └─Conv2d: 3-36 295,168
│ │ └─BatchNorm2d: 3-37 512
│ │ └─ReLU: 3-38 --
│ │ └─Conv2d: 3-39 590,080
│ │ └─BatchNorm2d: 3-40 512
│ └─BasicBlock: 2-9 --
│ │ └─Conv2d: 3-41 590,080
│ │ └─BatchNorm2d: 3-42 512
│ │ └─ReLU: 3-43 --
│ │ └─Conv2d: 3-44 590,080
│ │ └─BatchNorm2d: 3-45 512
│ └─BasicBlock: 2-10 --
│ │ └─Conv2d: 3-46 590,080
│ │ └─BatchNorm2d: 3-47 512
│ │ └─ReLU: 3-48 --
│ │ └─Conv2d: 3-49 590,080
│ │ └─BatchNorm2d: 3-50 512
│ └─BasicBlock: 2-11 --
│ │ └─Conv2d: 3-51 590,080
│ │ └─BatchNorm2d: 3-52 512
│ │ └─ReLU: 3-53 --
│ │ └─Conv2d: 3-54 590,080
│ │ └─BatchNorm2d: 3-55 512
│ └─BasicBlock: 2-12 --
│ │ └─Conv2d: 3-56 590,080
│ │ └─BatchNorm2d: 3-57 512
│ │ └─ReLU: 3-58 --
│ │ └─Conv2d: 3-59 590,080
│ │ └─BatchNorm2d: 3-60 512
│ └─BasicBlock: 2-13 --
│ │ └─Conv2d: 3-61 590,080
│ │ └─BatchNorm2d: 3-62 512
│ │ └─ReLU: 3-63 --
│ │ └─Conv2d: 3-64 590,080
│ │ └─BatchNorm2d: 3-65 512
├─Sequential: 1-8 --
│ └─BasicBlock: 2-14 --
│ │ └─Conv2d: 3-66 1,180,160
│ │ └─BatchNorm2d: 3-67 1,024
│ │ └─ReLU: 3-68 --
│ │ └─Conv2d: 3-69 2,359,808
│ │ └─BatchNorm2d: 3-70 1,024
│ └─BasicBlock: 2-15 --
│ │ └─Conv2d: 3-71 2,359,808
│ │ └─BatchNorm2d: 3-72 1,024
│ │ └─ReLU: 3-73 --
│ │ └─Conv2d: 3-74 2,359,808
│ │ └─BatchNorm2d: 3-75 1,024
│ └─BasicBlock: 2-16 --
│ │ └─Conv2d: 3-76 2,359,808
│ │ └─BatchNorm2d: 3-77 1,024
│ │ └─ReLU: 3-78 --
│ │ └─Conv2d: 3-79 2,359,808
│ │ └─BatchNorm2d: 3-80 1,024
├─AvgPool2d: 1-9 --
├─Linear: 1-10 513,000
=================================================================
Total params: 21,631,400
Trainable params: 21,631,400
Non-trainable params: 0
=================================================================