-
Notifications
You must be signed in to change notification settings - Fork 4
/
train_joint.py
117 lines (90 loc) · 4.6 KB
/
train_joint.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# Adapted from references/detection/engine.py for joint training of obj and part
import math
import sys
import time
import torch
import torchvision.models.detection
from references.detection.coco_eval import CocoEvaluator
from references.detection.utils import MetricLogger, SmoothedValue, reduce_dict, warmup_lr_scheduler
from utils import convert_to_coco_api_obj_part
def train_one_epoch(model, optimizer, data_loader, device, epoch, print_freq=1000):
"""
Train model (JointDetector) for 1 epoch from data in data_loader (images, obj_targets, part_targets)
"""
model.train()
metric_logger = MetricLogger(delimiter=" ")
metric_logger.add_meter('lr', SmoothedValue(window_size=1, fmt='{value:.6f}'))
header = 'Epoch: [{}]'.format(epoch)
lr_scheduler = None
if epoch == 0:
warmup_factor = 1. / 1000
warmup_iters = min(1000, len(data_loader) - 1)
lr_scheduler = warmup_lr_scheduler(optimizer, warmup_iters, warmup_factor)
for images, obj_targets, part_targets in metric_logger.log_every(data_loader, print_freq, header, device):
images = list(image.to(device) for image in images)
obj_targets = [{k: v.to(device) for k, v in t.items()} for t in obj_targets]
part_targets = [{k: v.to(device) for k, v in t.items()} for t in part_targets]
loss_dict = model(images, obj_targets, part_targets)
losses = sum(loss for loss in loss_dict.values())
# reduce losses over all GPUs for logging purposes
loss_dict_reduced = reduce_dict(loss_dict)
losses_reduced = sum(loss for loss in loss_dict_reduced.values())
loss_value = losses_reduced.item()
if not math.isfinite(loss_value):
print('Loss is {}, stopping training'.format(loss_value))
print(loss_dict_reduced)
sys.exit(1)
optimizer.zero_grad()
losses.backward()
optimizer.step()
if lr_scheduler is not None:
lr_scheduler.step()
metric_logger.update(loss=losses_reduced, **loss_dict_reduced)
metric_logger.update(lr=optimizer.param_groups[0]["lr"])
return metric_logger
@torch.no_grad()
def evaluate(model, data_loader, device, print_freq=1000, header='Test:'):
"""
Evaluate model (JointDetector) from data in data_loader (images, obj_targets, part_targets)
Return {obj/part}_coco_evaluator, {obj/part}_stats
"""
n_threads = torch.get_num_threads()
# FIXME remove this and make paste_masks_in_image run on the GPU
torch.set_num_threads(1)
cpu_device = torch.device('cpu')
model.eval()
metric_logger = MetricLogger(delimiter=' ')
obj_coco, part_coco = convert_to_coco_api_obj_part(data_loader.dataset)
iou_types = ['bbox']
obj_coco_evaluator = CocoEvaluator(obj_coco, iou_types)
part_coco_evaluator = CocoEvaluator(part_coco, iou_types)
for images, obj_targets, part_targets in metric_logger.log_every(data_loader, print_freq, header, device):
images = list(image.to(device) for image in images)
obj_targets = [{k: v.to(device) for k, v in t.items()} for t in obj_targets]
part_targets = [{k: v.to(device) for k, v in t.items()} for t in part_targets]
torch.cuda.synchronize()
model_time = time.time()
obj_detections, part_detections = model(images)
obj_detections = [{k: v.to(cpu_device) for k, v in t.items()} for t in obj_detections]
part_detections = [{k: v.to(cpu_device) for k, v in t.items()} for t in part_detections]
model_time = time.time() - model_time
obj_res = {target['image_id'].item(): output for target, output in zip(obj_targets, obj_detections)}
part_res = {target['image_id'].item(): output for target, output in zip(part_targets, part_detections)}
evaluator_time = time.time()
obj_coco_evaluator.update(obj_res)
part_coco_evaluator.update(part_res)
evaluator_time = time.time() - evaluator_time
metric_logger.update(model_time=model_time, evaluator_time=evaluator_time)
# gather the stats from all processes
metric_logger.synchronize_between_processes()
# accumulate predictions from all images
print('\nObject Detection Results:')
obj_coco_evaluator.synchronize_between_processes()
obj_coco_evaluator.accumulate()
obj_stats = obj_coco_evaluator.summarize()
print('\nPart Detection Results:')
part_coco_evaluator.synchronize_between_processes()
part_coco_evaluator.accumulate()
part_stats = part_coco_evaluator.summarize()
torch.set_num_threads(n_threads)
return obj_coco_evaluator, part_coco_evaluator, obj_stats, part_stats