Skip to content

Commit d065b47

Browse files
committed
code refactoring
1 parent 4bc9c23 commit d065b47

File tree

6 files changed

+76
-81
lines changed

6 files changed

+76
-81
lines changed

data/config.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
cfg = {
44
'name': 'FaceBoxes',
5-
'feature_maps': [[32, 32], [16, 16], [8, 8]],
6-
'min_dim': 1024,
7-
'steps': [32, 64, 128],
5+
#'min_dim': 1024,
6+
#'feature_maps': [[32, 32], [16, 16], [8, 8]],
7+
# 'aspect_ratios': [[1], [1], [1]],
88
'min_sizes': [[32, 64, 128], [256], [512]],
9-
'aspect_ratios': [[1], [1], [1]],
9+
'steps': [32, 64, 128],
1010
'variance': [0.1, 0.2],
1111
'clip': False,
1212
'loc_weight': 2.0,

layers/functions/prior_box.py

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,21 @@
11
import torch
22
from itertools import product as product
33
import numpy as np
4+
from math import ceil
45

56

67
class PriorBox(object):
7-
def __init__(self, cfg, box_dimension=None, image_size=None, phase='train'):
8+
def __init__(self, cfg, image_size=None, phase='train'):
89
super(PriorBox, self).__init__()
9-
self.variance = cfg['variance']
10+
#self.aspect_ratios = cfg['aspect_ratios']
1011
self.min_sizes = cfg['min_sizes']
1112
self.steps = cfg['steps']
12-
self.aspect_ratios = cfg['aspect_ratios']
1313
self.clip = cfg['clip']
14-
if phase == 'train':
15-
self.image_size = (cfg['min_dim'], cfg['min_dim'])
16-
self.feature_maps = cfg['feature_maps']
17-
elif phase == 'test':
18-
self.feature_maps = box_dimension.cpu().numpy().astype(np.int)
19-
self.image_size = image_size
20-
for v in self.variance:
21-
if v <= 0:
22-
raise ValueError('Variances must be greater than 0')
14+
self.image_size = image_size
15+
self.feature_maps = [[ceil(self.image_size[0]/step), ceil(self.image_size[1]/step)] for step in self.steps]
2316

2417
def forward(self):
25-
mean = []
18+
anchors = []
2619
for k, f in enumerate(self.feature_maps):
2720
min_sizes = self.min_sizes[k]
2821
for i, j in product(range(f[0]), range(f[1])):
@@ -33,18 +26,18 @@ def forward(self):
3326
dense_cx = [x*self.steps[k]/self.image_size[1] for x in [j+0, j+0.25, j+0.5, j+0.75]]
3427
dense_cy = [y*self.steps[k]/self.image_size[0] for y in [i+0, i+0.25, i+0.5, i+0.75]]
3528
for cy, cx in product(dense_cy, dense_cx):
36-
mean += [cx, cy, s_kx, s_ky]
29+
anchors += [cx, cy, s_kx, s_ky]
3730
elif min_size == 64:
3831
dense_cx = [x*self.steps[k]/self.image_size[1] for x in [j+0, j+0.5]]
3932
dense_cy = [y*self.steps[k]/self.image_size[0] for y in [i+0, i+0.5]]
4033
for cy, cx in product(dense_cy, dense_cx):
41-
mean += [cx, cy, s_kx, s_ky]
34+
anchors += [cx, cy, s_kx, s_ky]
4235
else:
4336
cx = (j + 0.5) * self.steps[k] / self.image_size[1]
4437
cy = (i + 0.5) * self.steps[k] / self.image_size[0]
45-
mean += [cx, cy, s_kx, s_ky]
38+
anchors += [cx, cy, s_kx, s_ky]
4639
# back to torch land
47-
output = torch.Tensor(mean).view(-1, 4)
40+
output = torch.Tensor(anchors).view(-1, 4)
4841
if self.clip:
4942
output.clamp_(max=1, min=0)
5043
return output

layers/modules/multibox_loss.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def forward(self, predictions, priors, targets):
5454
shape: [batch_size,num_objs,5] (last idx is the label).
5555
"""
5656

57-
loc_data, conf_data, _ = predictions
57+
loc_data, conf_data = predictions
5858
priors = priors
5959
num = loc_data.size(0)
6060
num_priors = (priors.size(0))

models/faceboxes.py

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,20 @@ def __init__(self):
2727
self.branch3x3_reduce_2 = BasicConv2d(128, 24, kernel_size=1, padding=0)
2828
self.branch3x3_2 = BasicConv2d(24, 32, kernel_size=3, padding=1)
2929
self.branch3x3_3 = BasicConv2d(32, 32, kernel_size=3, padding=1)
30-
30+
3131
def forward(self, x):
3232
branch1x1 = self.branch1x1(x)
33-
33+
3434
branch1x1_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
3535
branch1x1_2 = self.branch1x1_2(branch1x1_pool)
36-
36+
3737
branch3x3_reduce = self.branch3x3_reduce(x)
3838
branch3x3 = self.branch3x3(branch3x3_reduce)
39-
39+
4040
branch3x3_reduce_2 = self.branch3x3_reduce_2(x)
4141
branch3x3_2 = self.branch3x3_2(branch3x3_reduce_2)
4242
branch3x3_3 = self.branch3x3_3(branch3x3_2)
43-
43+
4444
outputs = [branch1x1, branch1x1_2, branch3x3, branch3x3_3]
4545
return torch.cat(outputs, 1)
4646

@@ -51,38 +51,38 @@ def __init__(self, in_channels, out_channels, **kwargs):
5151
super(CRelu, self).__init__()
5252
self.conv = nn.Conv2d(in_channels, out_channels, bias=False, **kwargs)
5353
self.bn = nn.BatchNorm2d(out_channels, eps=1e-5)
54-
54+
5555
def forward(self, x):
5656
x = self.conv(x)
5757
x = self.bn(x)
5858
x = torch.cat([x, -x], 1)
5959
x = F.relu(x, inplace=True)
6060
return x
61-
62-
61+
62+
6363
class FaceBoxes(nn.Module):
6464

6565
def __init__(self, phase, size, num_classes):
6666
super(FaceBoxes, self).__init__()
6767
self.phase = phase
6868
self.num_classes = num_classes
6969
self.size = size
70-
70+
7171
self.conv1 = CRelu(3, 24, kernel_size=7, stride=4, padding=3)
7272
self.conv2 = CRelu(48, 64, kernel_size=5, stride=2, padding=2)
73-
73+
7474
self.inception1 = Inception()
7575
self.inception2 = Inception()
7676
self.inception3 = Inception()
77-
77+
7878
self.conv3_1 = BasicConv2d(128, 128, kernel_size=1, stride=1, padding=0)
7979
self.conv3_2 = BasicConv2d(128, 256, kernel_size=3, stride=2, padding=1)
80-
80+
8181
self.conv4_1 = BasicConv2d(256, 128, kernel_size=1, stride=1, padding=0)
8282
self.conv4_2 = BasicConv2d(128, 256, kernel_size=3, stride=2, padding=1)
83-
83+
8484
self.loc, self.conf = self.multibox(self.num_classes)
85-
85+
8686
if self.phase == 'test':
8787
self.softmax = nn.Softmax(dim=-1)
8888

@@ -108,13 +108,12 @@ def multibox(self, num_classes):
108108
loc_layers += [nn.Conv2d(256, 1 * 4, kernel_size=3, padding=1)]
109109
conf_layers += [nn.Conv2d(256, 1 * num_classes, kernel_size=3, padding=1)]
110110
return nn.Sequential(*loc_layers), nn.Sequential(*conf_layers)
111-
111+
112112
def forward(self, x):
113-
114-
sources = list()
113+
114+
detection_sources = list()
115115
loc = list()
116116
conf = list()
117-
detection_dimension = list()
118117

119118
x = self.conv1(x)
120119
x = F.max_pool2d(x, kernel_size=3, stride=2, padding=1)
@@ -123,33 +122,28 @@ def forward(self, x):
123122
x = self.inception1(x)
124123
x = self.inception2(x)
125124
x = self.inception3(x)
126-
detection_dimension.append(x.shape[2:])
127-
sources.append(x)
125+
detection_sources.append(x)
126+
128127
x = self.conv3_1(x)
129128
x = self.conv3_2(x)
130-
detection_dimension.append(x.shape[2:])
131-
sources.append(x)
129+
detection_sources.append(x)
130+
132131
x = self.conv4_1(x)
133132
x = self.conv4_2(x)
134-
detection_dimension.append(x.shape[2:])
135-
sources.append(x)
136-
137-
detection_dimension = torch.tensor(detection_dimension, device=x.device)
133+
detection_sources.append(x)
138134

139-
for (x, l, c) in zip(sources, self.loc, self.conf):
135+
for (x, l, c) in zip(detection_sources, self.loc, self.conf):
140136
loc.append(l(x).permute(0, 2, 3, 1).contiguous())
141137
conf.append(c(x).permute(0, 2, 3, 1).contiguous())
142-
138+
143139
loc = torch.cat([o.view(o.size(0), -1) for o in loc], 1)
144140
conf = torch.cat([o.view(o.size(0), -1) for o in conf], 1)
145141

146142
if self.phase == "test":
147143
output = (loc.view(loc.size(0), -1, 4),
148-
self.softmax(conf.view(-1, self.num_classes)),
149-
detection_dimension)
144+
self.softmax(conf.view(-1, self.num_classes)))
150145
else:
151146
output = (loc.view(loc.size(0), -1, 4),
152-
conf.view(conf.size(0), -1, self.num_classes),
153-
detection_dimension)
154-
147+
conf.view(conf.size(0), -1, self.num_classes))
148+
155149
return output

test.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,12 @@ def load_model(model, pretrained_path, load_to_cpu):
113113
scale = scale.to(device)
114114

115115
_t['forward_pass'].tic()
116-
out = net(img) # forward pass
116+
loc, conf = net(img) # forward pass
117117
_t['forward_pass'].toc()
118118
_t['misc'].tic()
119-
priorbox = PriorBox(cfg, out[2], (im_height, im_width), phase='test')
119+
priorbox = PriorBox(cfg, image_size=(im_height, im_width))
120120
priors = priorbox.forward()
121121
priors = priors.to(device)
122-
loc, conf, _ = out
123122
prior_data = priors.data
124123
boxes = decode(loc.data.squeeze(0), prior_data, cfg['variance'])
125124
boxes = boxes * scale / resize

train.py

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from layers.modules import MultiBoxLoss
1010
from layers.functions.prior_box import PriorBox
1111
import time
12+
import datetime
1213
import math
1314
from models.faceboxes import FaceBoxes
1415

@@ -30,13 +31,19 @@
3031
if not os.path.exists(args.save_folder):
3132
os.mkdir(args.save_folder)
3233

33-
img_dim = 1024
34-
rgb_means = (104, 117, 123) #bgr order
34+
img_dim = 1024 # only 1024 is supported
35+
rgb_mean = (104, 117, 123) # bgr order
3536
num_classes = 2
37+
num_gpu = args.ngpu
38+
num_workers = args.num_workers
3639
batch_size = args.batch_size
40+
momentum = args.momentum
3741
weight_decay = args.weight_decay
42+
initial_lr = args.lr
3843
gamma = args.gamma
39-
momentum = args.momentum
44+
max_epoch = args.max_epoch
45+
training_dataset = args.training_dataset
46+
save_folder = args.save_folder
4047
gpu_train = cfg['gpu_train']
4148

4249
net = FaceBoxes('train', img_dim, num_classes)
@@ -58,17 +65,17 @@
5865
new_state_dict[name] = v
5966
net.load_state_dict(new_state_dict)
6067

61-
if args.ngpu > 1 and gpu_train:
62-
net = torch.nn.DataParallel(net, device_ids=list(range(args.ngpu)))
68+
if num_gpu > 1 and gpu_train:
69+
net = torch.nn.DataParallel(net, device_ids=list(range(num_gpu)))
6370

6471
device = torch.device('cuda:0' if gpu_train else 'cpu')
6572
cudnn.benchmark = True
6673
net = net.to(device)
6774

68-
optimizer = optim.SGD(net.parameters(), lr=args.lr, momentum=args.momentum, weight_decay=args.weight_decay)
75+
optimizer = optim.SGD(net.parameters(), lr=initial_lr, momentum=momentum, weight_decay=weight_decay)
6976
criterion = MultiBoxLoss(num_classes, 0.35, True, 0, True, 7, 0.35, False)
7077

71-
priorbox = PriorBox(cfg)
78+
priorbox = PriorBox(cfg, image_size=(img_dim, img_dim))
7279
with torch.no_grad():
7380
priors = priorbox.forward()
7481
priors = priors.to(device)
@@ -79,10 +86,10 @@ def train():
7986
epoch = 0 + args.resume_epoch
8087
print('Loading Dataset...')
8188

82-
dataset = VOCDetection(args.training_dataset, preproc(img_dim, rgb_means), AnnotationTransform())
89+
dataset = VOCDetection(training_dataset, preproc(img_dim, rgb_mean), AnnotationTransform())
8390

84-
epoch_size = math.ceil(len(dataset) / args.batch_size)
85-
max_iter = args.max_epoch * epoch_size
91+
epoch_size = math.ceil(len(dataset) / batch_size)
92+
max_iter = max_epoch * epoch_size
8693

8794
stepvalues = (200 * epoch_size, 250 * epoch_size)
8895
step_index = 0
@@ -95,15 +102,15 @@ def train():
95102
for iteration in range(start_iter, max_iter):
96103
if iteration % epoch_size == 0:
97104
# create batch iterator
98-
batch_iterator = iter(data.DataLoader(dataset, batch_size, shuffle=True, num_workers=args.num_workers, collate_fn=detection_collate))
105+
batch_iterator = iter(data.DataLoader(dataset, batch_size, shuffle=True, num_workers=num_workers, collate_fn=detection_collate))
99106
if (epoch % 10 == 0 and epoch > 0) or (epoch % 5 == 0 and epoch > 200):
100-
torch.save(net.state_dict(), args.save_folder + 'FaceBoxes_epoch_' + repr(epoch) + '.pth')
107+
torch.save(net.state_dict(), save_folder + 'FaceBoxes_epoch_' + str(epoch) + '.pth')
101108
epoch += 1
102109

103110
load_t0 = time.time()
104111
if iteration in stepvalues:
105112
step_index += 1
106-
lr = adjust_learning_rate(optimizer, args.gamma, epoch, step_index, iteration, epoch_size)
113+
lr = adjust_learning_rate(optimizer, gamma, epoch, step_index, iteration, epoch_size)
107114

108115
# load train data
109116
images, targets = next(batch_iterator)
@@ -112,33 +119,35 @@ def train():
112119

113120
# forward
114121
out = net(images)
115-
122+
116123
# backprop
117124
optimizer.zero_grad()
118125
loss_l, loss_c = criterion(out, priors, targets)
119126
loss = cfg['loc_weight'] * loss_l + loss_c
120127
loss.backward()
121128
optimizer.step()
122129
load_t1 = time.time()
123-
print('Epoch:' + repr(epoch) + ' || epochiter: ' + repr(iteration % epoch_size) + '/' + repr(epoch_size) +
124-
'|| Totel iter ' + repr(iteration) + ' || L: %.4f C: %.4f||' % (cfg['loc_weight']*loss_l.item(), loss_c.item()) +
125-
'Batch time: %.4f sec. ||' % (load_t1 - load_t0) + 'LR: %.8f' % (lr))
130+
batch_time = load_t1 - load_t0
131+
eta = int(batch_time * (max_iter - iteration))
132+
print('Epoch:{}/{} || Epochiter: {}/{} || Iter: {}/{} || L: {:.4f} C: {:.4f} || LR: {:.8f} || Batchtime: {:.4f} s || ETA: {}'.format(epoch, max_epoch, (iteration % epoch_size) + 1, epoch_size, iteration + 1, max_iter, loss_l.item(), loss_c.item(), lr, batch_time, str(datetime.timedelta(seconds=eta))))
126133

127-
torch.save(net.state_dict(), args.save_folder + 'Final_FaceBoxes.pth')
134+
135+
torch.save(net.state_dict(), save_folder + 'Final_FaceBoxes.pth')
128136

129137

130138
def adjust_learning_rate(optimizer, gamma, epoch, step_index, iteration, epoch_size):
131-
"""Sets the learning rate
139+
"""Sets the learning rate
132140
# Adapted from PyTorch Imagenet example:
133141
# https://github.com/pytorch/examples/blob/master/imagenet/main.py
134142
"""
135-
if epoch < 0:
136-
lr = 1e-6 + (args.lr-1e-6) * iteration / (epoch_size * 5)
143+
warmup_epoch = -1
144+
if epoch <= warmup_epoch:
145+
lr = 1e-6 + (initial_lr-1e-6) * iteration / (epoch_size * warmup_epoch)
137146
else:
138-
lr = args.lr * (gamma ** (step_index))
147+
lr = initial_lr * (gamma ** (step_index))
139148
for param_group in optimizer.param_groups:
140149
param_group['lr'] = lr
141150
return lr
142-
151+
143152
if __name__ == '__main__':
144153
train()

0 commit comments

Comments
 (0)