-
Notifications
You must be signed in to change notification settings - Fork 1
/
trainer.py
119 lines (100 loc) · 3.8 KB
/
trainer.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
118
119
# encoding: utf-8
"""
@author: zhoumi
@contact: [email protected]
"""
import math
import time
import numpy as np
class AverageMeter(object):
def __init__(self):
self.n = 0
self.sum = 0.0
self.var = 0.0
self.val = 0.0
self.mean = np.nan
self.std = np.nan
def update(self, value, n=1):
self.val = value
self.sum += value
self.var += value * value
self.n += n
if self.n == 0:
self.mean, self.std = np.nan, np.nan
elif self.n == 1:
self.mean, self.std = self.sum, np.inf
else:
self.mean = self.sum / self.n
self.std = math.sqrt(
(self.var - self.n * self.mean * self.mean) / (self.n - 1.0))
def value(self):
return self.mean, self.std
def reset(self):
self.n = 0
self.sum = 0.0
self.var = 0.0
self.val = 0.0
self.mean = np.nan
self.std = np.nan
class cls_tripletTrainer:
def __init__(self, opt, model, optimzier, criterion, summary_writer):
self.opt = opt
self.model = model
self.optimizer= optimzier
self.criterion = criterion
self.summary_writer = summary_writer
def train(self, epoch, data_loader):
self.model.train()
batch_time = AverageMeter()
data_time = AverageMeter()
losses = AverageMeter()
start = time.time()
for i, inputs in enumerate(data_loader):
data_time.update(time.time() - start)
# model optimizer
self._parse_data(inputs)
self._forward()
self.optimizer.zero_grad()
self._backward()
self.optimizer.step()
batch_time.update(time.time() - start)
losses.update(self.loss.item())
# tensorboard
global_step = epoch * len(data_loader) + i
self.summary_writer.add_scalar('loss', self.loss.item(), global_step)
self.summary_writer.add_scalar('lr', self.optimizer.param_groups[0]['lr'], global_step)
start = time.time()
if (i + 1) % self.opt.print_freq == 0:
print('Epoch: [{}][{}/{}]\t'
'Batch Time {:.3f} ({:.3f})\t'
'Data Time {:.3f} ({:.3f})\t'
'Loss {:.3f} ({:.3f})\t'
.format(epoch, i + 1, len(data_loader),
batch_time.val, batch_time.mean,
data_time.val, data_time.mean,
losses.val, losses.mean))
param_group = self.optimizer.param_groups
print('Epoch: [{}]\tEpoch Time {:.3f} s\tLoss {:.3f}\t'
'Lr {:.2e}'
.format(epoch, batch_time.sum, losses.mean, param_group[0]['lr']))
print()
def _parse_data(self, inputs):
imgs, pids, _ = inputs
self.data = imgs.cuda()
self.target = pids.cuda()
def _forward(self):
score, feat = self.model(self.data)
if 'pcb' == self.opt.model_name:
loss = 0
for i in range(self.opt.num_parts):
loss += self.criterion(score[i], feat, self.target)
self.loss = loss / self.opt.num_parts
elif 'MGN' == self.opt.model_name or 'StackPCBv2' == self.opt.model_name\
or 'drop_block' == self.opt.model_name or 'StackPCB' == self.opt.model_name:
tri_loss = [self.criterion(score[0], f, self.target, weight_s = 0) for f in feat]
soft_loss = [self.criterion(s, feat[0], self.target, weight_t = 0) for s in score]
self.loss = sum(tri_loss) / len(feat) + sum(soft_loss) / len(score)
else:
self.loss = self.criterion(score, feat, self.target)
def _backward(self):
self.loss.backward()