|
a |
|
b/darkflow/net/yolov2/train.py |
|
|
1 |
import tf_slim as slim |
|
|
2 |
import pickle |
|
|
3 |
import tensorflow as tf |
|
|
4 |
from ..yolo.misc import show |
|
|
5 |
import numpy as np |
|
|
6 |
import os |
|
|
7 |
import math |
|
|
8 |
|
|
|
9 |
tf = tf.compat.v1 |
|
|
10 |
tf.disable_v2_behavior() |
|
|
11 |
|
|
|
12 |
|
|
|
13 |
def expit_tensor(x): |
|
|
14 |
return 1. / (1. + tf.exp(-x)) |
|
|
15 |
|
|
|
16 |
|
|
|
17 |
def loss(self, net_out): |
|
|
18 |
""" |
|
|
19 |
Takes net.out and placeholders value |
|
|
20 |
returned in batch() func above, |
|
|
21 |
to build train_op and loss |
|
|
22 |
""" |
|
|
23 |
# meta |
|
|
24 |
m = self.meta |
|
|
25 |
sprob = float(m['class_scale']) |
|
|
26 |
sconf = float(m['object_scale']) |
|
|
27 |
snoob = float(m['noobject_scale']) |
|
|
28 |
scoor = float(m['coord_scale']) |
|
|
29 |
H, W, _ = m['out_size'] |
|
|
30 |
B, C = m['num'], m['classes'] |
|
|
31 |
HW = H * W # number of grid cells |
|
|
32 |
anchors = m['anchors'] |
|
|
33 |
|
|
|
34 |
print('{} loss hyper-parameters:'.format(m['model'])) |
|
|
35 |
print('\tH = {}'.format(H)) |
|
|
36 |
print('\tW = {}'.format(W)) |
|
|
37 |
print('\tbox = {}'.format(m['num'])) |
|
|
38 |
print('\tclasses = {}'.format(m['classes'])) |
|
|
39 |
print('\tscales = {}'.format([sprob, sconf, snoob, scoor])) |
|
|
40 |
|
|
|
41 |
size1 = [None, HW, B, C] |
|
|
42 |
size2 = [None, HW, B] |
|
|
43 |
|
|
|
44 |
# return the below placeholders |
|
|
45 |
_probs = tf.placeholder(tf.float32, size1) |
|
|
46 |
_confs = tf.placeholder(tf.float32, size2) |
|
|
47 |
_coord = tf.placeholder(tf.float32, size2 + [4]) |
|
|
48 |
# weights term for L2 loss |
|
|
49 |
_proid = tf.placeholder(tf.float32, size1) |
|
|
50 |
# material calculating IOU |
|
|
51 |
_areas = tf.placeholder(tf.float32, size2) |
|
|
52 |
_upleft = tf.placeholder(tf.float32, size2 + [2]) |
|
|
53 |
_botright = tf.placeholder(tf.float32, size2 + [2]) |
|
|
54 |
|
|
|
55 |
self.placeholders = { |
|
|
56 |
'probs': _probs, 'confs': _confs, 'coord': _coord, 'proid': _proid, |
|
|
57 |
'areas': _areas, 'upleft': _upleft, 'botright': _botright |
|
|
58 |
} |
|
|
59 |
|
|
|
60 |
# Extract the coordinate prediction from net.out |
|
|
61 |
net_out_reshape = tf.reshape(net_out, [-1, H, W, B, (4 + 1 + C)]) |
|
|
62 |
coords = net_out_reshape[:, :, :, :, :4] |
|
|
63 |
coords = tf.reshape(coords, [-1, H * W, B, 4]) |
|
|
64 |
adjusted_coords_xy = expit_tensor(coords[:, :, :, 0:2]) |
|
|
65 |
adjusted_coords_wh = tf.sqrt( |
|
|
66 |
tf.exp(coords[:, :, :, 2:4]) * np.reshape(anchors, [1, 1, B, 2]) / np.reshape([W, H], [1, 1, 1, 2])) |
|
|
67 |
coords = tf.concat([adjusted_coords_xy, adjusted_coords_wh], 3) |
|
|
68 |
|
|
|
69 |
adjusted_c = expit_tensor(net_out_reshape[:, :, :, :, 4]) |
|
|
70 |
adjusted_c = tf.reshape(adjusted_c, [-1, H * W, B, 1]) |
|
|
71 |
|
|
|
72 |
adjusted_prob = tf.nn.softmax(net_out_reshape[:, :, :, :, 5:]) |
|
|
73 |
adjusted_prob = tf.reshape(adjusted_prob, [-1, H * W, B, C]) |
|
|
74 |
|
|
|
75 |
adjusted_net_out = tf.concat([adjusted_coords_xy, adjusted_coords_wh, adjusted_c, adjusted_prob], 3) |
|
|
76 |
|
|
|
77 |
wh = tf.pow(coords[:, :, :, 2:4], 2) * np.reshape([W, H], [1, 1, 1, 2]) |
|
|
78 |
area_pred = wh[:, :, :, 0] * wh[:, :, :, 1] |
|
|
79 |
centers = coords[:, :, :, 0:2] |
|
|
80 |
floor = centers - (wh * .5) |
|
|
81 |
ceil = centers + (wh * .5) |
|
|
82 |
|
|
|
83 |
# calculate the intersection areas |
|
|
84 |
intersect_upleft = tf.maximum(floor, _upleft) |
|
|
85 |
intersect_botright = tf.minimum(ceil, _botright) |
|
|
86 |
intersect_wh = intersect_botright - intersect_upleft |
|
|
87 |
intersect_wh = tf.maximum(intersect_wh, 0.0) |
|
|
88 |
intersect = tf.multiply(intersect_wh[:, :, :, 0], intersect_wh[:, :, :, 1]) |
|
|
89 |
|
|
|
90 |
# calculate the best IOU, set 0.0 confidence for worse boxes |
|
|
91 |
iou = tf.truediv(intersect, _areas + area_pred - intersect) |
|
|
92 |
best_box = tf.equal(iou, tf.reduce_max(iou, [2], True)) |
|
|
93 |
best_box = tf.to_float(best_box) |
|
|
94 |
confs = tf.multiply(best_box, _confs) |
|
|
95 |
|
|
|
96 |
# take care of the weight terms |
|
|
97 |
conid = snoob * (1. - confs) + sconf * confs |
|
|
98 |
weight_coo = tf.concat(4 * [tf.expand_dims(confs, -1)], 3) |
|
|
99 |
cooid = scoor * weight_coo |
|
|
100 |
weight_pro = tf.concat(C * [tf.expand_dims(confs, -1)], 3) |
|
|
101 |
proid = sprob * weight_pro |
|
|
102 |
|
|
|
103 |
self.fetch += [_probs, confs, conid, cooid, proid] |
|
|
104 |
true = tf.concat([_coord, tf.expand_dims(confs, 3), _probs], 3) |
|
|
105 |
wght = tf.concat([cooid, tf.expand_dims(conid, 3), proid], 3) |
|
|
106 |
|
|
|
107 |
print('Building {} loss'.format(m['model'])) |
|
|
108 |
loss = tf.pow(adjusted_net_out - true, 2) |
|
|
109 |
loss = tf.multiply(loss, wght) |
|
|
110 |
loss = tf.reshape(loss, [-1, H * W * B * (4 + 1 + C)]) |
|
|
111 |
loss = tf.reduce_sum(loss, 1) |
|
|
112 |
self.loss = .5 * tf.reduce_mean(loss) |
|
|
113 |
tf.summary.scalar('{} loss'.format(m['model']), self.loss) |