|
|
|
|
|
import torch |
|
|
import torch.nn as nn |
|
|
|
|
|
|
|
|
class ResidualInceptionBlock(nn.Module): |
|
|
def __init__(self, in_channels, out_channels, stride=1): |
|
|
super(ResidualInceptionBlock, self).__init__() |
|
|
|
|
|
self.branch1 = nn.Conv2d(in_channels, out_channels // 4, kernel_size=1, stride=stride) |
|
|
|
|
|
|
|
|
self.branch2 = nn.Sequential( |
|
|
nn.Conv2d(in_channels, out_channels // 4, kernel_size=1, stride=stride), |
|
|
nn.BatchNorm2d(out_channels // 4), |
|
|
nn.ReLU(inplace=True), |
|
|
nn.Conv2d(out_channels // 4, out_channels // 4, kernel_size=3, stride=1, padding=1) |
|
|
) |
|
|
|
|
|
|
|
|
self.branch3 = nn.Sequential( |
|
|
nn.Conv2d(in_channels, out_channels // 4, kernel_size=1, stride=stride), |
|
|
nn.BatchNorm2d(out_channels // 4), |
|
|
nn.ReLU(inplace=True), |
|
|
nn.Conv2d(out_channels // 4, out_channels // 4, kernel_size=5, stride=1, padding=2) |
|
|
) |
|
|
|
|
|
|
|
|
self.branch_pool = nn.Sequential( |
|
|
nn.MaxPool2d(kernel_size=3, stride=stride, padding=1), |
|
|
nn.Conv2d(in_channels, out_channels // 4, kernel_size=1, stride=1, padding=0) |
|
|
) |
|
|
|
|
|
|
|
|
self.bn = nn.BatchNorm2d(out_channels) |
|
|
self.relu = nn.ReLU(inplace=True) |
|
|
|
|
|
|
|
|
self.shortcut = nn.Sequential() |
|
|
if in_channels != out_channels or stride != 1: |
|
|
self.shortcut = nn.Sequential( |
|
|
nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride), |
|
|
nn.BatchNorm2d(out_channels) |
|
|
) |
|
|
|
|
|
def forward(self, x): |
|
|
branch1 = self.branch1(x) |
|
|
branch2 = self.branch2(x) |
|
|
branch3 = self.branch3(x) |
|
|
branch4 = self.branch_pool(x) |
|
|
outputs = torch.cat([branch1, branch2, branch3, branch4], 1) |
|
|
outputs = self.bn(outputs) |
|
|
residual = self.shortcut(x) |
|
|
outputs += residual |
|
|
outputs = self.relu(outputs) |
|
|
return outputs |
|
|
|
|
|
|
|
|
def make_layer(block, in_channels, out_channels, num_blocks, stride=1): |
|
|
layers = [] |
|
|
layers.append(block(in_channels, out_channels, stride=stride)) |
|
|
in_channels = out_channels |
|
|
for _ in range(1, num_blocks): |
|
|
layers.append(block(in_channels, out_channels, stride=1)) |
|
|
return nn.Sequential(*layers) |
|
|
|
|
|
|
|
|
class DeeperDetectionModel(nn.Module): |
|
|
def __init__(self, num_classes=4): |
|
|
super(DeeperDetectionModel, self).__init__() |
|
|
self.module1 = nn.Sequential( |
|
|
nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3), |
|
|
nn.BatchNorm2d(64), |
|
|
nn.ReLU(inplace=True), |
|
|
nn.MaxPool2d(kernel_size=3, stride=2, padding=1) |
|
|
) |
|
|
self.layer1 = make_layer(ResidualInceptionBlock, 64, 256, num_blocks=3, stride=1) |
|
|
self.layer2 = make_layer(ResidualInceptionBlock, 256, 512, num_blocks=4, stride=2) |
|
|
self.layer3 = make_layer(ResidualInceptionBlock, 512, 1024, num_blocks=6, stride=2) |
|
|
self.layer4 = make_layer(ResidualInceptionBlock, 1024, 2048, num_blocks=3, stride=2) |
|
|
self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) |
|
|
self.fc = nn.Linear(2048, num_classes) |
|
|
|
|
|
def forward(self, x): |
|
|
x = self.module1(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) |
|
|
x = self.fc(x) |
|
|
return x |
|
|
|
|
|
|
|
|
def create_detection_model(num_classes=4): |
|
|
"""Factory function to create the model""" |
|
|
model = DeeperDetectionModel(num_classes=num_classes) |
|
|
return model |