forked from Mayurji/Image-Classification-PyTorch
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Darknet53.py
79 lines (64 loc) · 2.85 KB
/
Darknet53.py
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
"""
Darknet-53
Darknet-53 is the backbone architecture of the YOLOV3, an Object detection model. Similar to
Darknet-53, there is Darknet-19, which is the backbone for YOLOV2 model. Darknet has it roots
in VGG network with most of the conv layers begin 3x3. In addition to VGGNet, Darknet-53 includes
residual connection as in ResNet model.
"""
import torch
from torch import nn
def conv_batch(in_num, out_num, kernel_size=3, padding=1, stride=1):
return nn.Sequential(
nn.Conv2d(in_num, out_num, kernel_size=kernel_size, stride=stride, padding=padding, bias=False),
nn.BatchNorm2d(out_num),
nn.LeakyReLU())
# Residual block
class DarkResidualBlock(nn.Module):
def __init__(self, in_channels):
super(DarkResidualBlock, self).__init__()
reduced_channels = int(in_channels/2)
self.layer1 = conv_batch(in_channels, reduced_channels, kernel_size=1, padding=0)
self.layer2 = conv_batch(reduced_channels, in_channels)
def forward(self, x):
residual = x
out = self.layer1(x)
out = self.layer2(out)
out += residual
return out
class Darknet53(nn.Module):
def __init__(self, input_channel, n_classes):
super(Darknet53, self).__init__()
self.conv1 = conv_batch(input_channel, 32)
self.conv2 = conv_batch(32, 64, stride=2)
self.residual_block1 = self.make_layer(block = DarkResidualBlock, in_channels=64, num_blocks=1)
self.conv3 = conv_batch(64, 128, stride=2)
self.residual_block2 = self.make_layer(block = DarkResidualBlock, in_channels=128, num_blocks=2)
self.conv4 = conv_batch(128, 256, stride=2)
self.residual_block3 = self.make_layer(block = DarkResidualBlock, in_channels=256, num_blocks=8)
self.conv5 = conv_batch(256, 512, stride=2)
self.residual_block4 = self.make_layer(block = DarkResidualBlock, in_channels=512, num_blocks=8)
self.conv6 = conv_batch(512, 1024, stride=2)
self.residual_block5 = self.make_layer(block = DarkResidualBlock, in_channels=1024, num_blocks=4)
self.global_avg_pool = nn.AdaptiveAvgPool2d((1, 1))
self.fc = nn.Linear(1024, n_classes)
def forward(self, x):
out = self.conv1(x)
out = self.conv2(out)
out = self.residual_block1(out)
out = self.conv3(out)
out = self.residual_block2(out)
out = self.conv4(out)
out = self.residual_block3(out)
out = self.conv5(out)
out = self.residual_block4(out)
out = self.conv6(out)
out = self.residual_block5(out)
out = self.global_avg_pool(out)
out = out.view(-1, 1024)
out = self.fc(out)
return out
def make_layer(self, in_channels, num_blocks, block):
layers = []
for i in range(0, num_blocks):
layers.append(block(in_channels))
return nn.Sequential(*layers)