-
Notifications
You must be signed in to change notification settings - Fork 3
/
Network.py
239 lines (216 loc) · 9.7 KB
/
Network.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
import inspect
import tensorflow as tf
import Measures
import NetworkLayers
import NetworkOutputLayers
from Log import log
from Util_Network import TowerSetup
def get_layer_class(layer_class):
if hasattr(NetworkLayers, layer_class):
class_ = getattr(NetworkLayers, layer_class)
elif hasattr(NetworkOutputLayers, layer_class):
class_ = getattr(NetworkOutputLayers, layer_class)
elif hasattr(NetworkRecurrentLayers, layer_class):
class_ = getattr(NetworkRecurrentLayers, layer_class)
else:
assert False, ("Unknown layer class", layer_class)
return class_
class Network(object):
def build_tower(self, network_def, x_image, y_ref, void_label, n_classes, tower_setup, flow=None):
use_dropout = not tower_setup.is_training
gpu_str = "/gpu:" + str(tower_setup.gpu)
if tower_setup.is_main_train_tower:
print >> log.v4, "inputs:", [x_image.get_shape().as_list()]
with tf.device(gpu_str), tf.name_scope("tower_gpu_" + str(tower_setup.gpu)):
output_layer = None
layers = {}
for name, layer_def in network_def.items():
layer_def = layer_def.copy()
layer_class = layer_def["class"]
if layer_class == "GraphSection":
if self.use_partialflow:
if self.current_graph_section is not None:
self.current_graph_section.__exit__(None, None, None)
self.current_graph_section = self.graph_section_manager.new_section()
self.graph_sections.append(self.current_graph_section)
self.current_graph_section.__enter__()
#else:
# print >> log.v1, "warning, GraphSection defined, but use_partialflow is False. Ignoring sections"
continue
del layer_def["class"]
class_ = get_layer_class(layer_class)
spec = inspect.getargspec(class_.__init__)
args = spec[0]
if "from" in layer_def:
inputs = sum([layers[x].outputs for x in layer_def["from"]], [])
del layer_def["from"]
else:
if '_1' in name:
if flow is not None:
inputs = [flow]
else:
raise Exception("Expecting Flow input")
else:
inputs = [x_image]
if "concat" in layer_def:
concat = sum([layers[x].outputs for x in layer_def["concat"]], [])
layer_def["concat"] = concat
if "alternative_labels" in layer_def:
layer_def["targets"] = sum([layers[x].out_labels for x in layer_def["alternative_labels"]])
layer_def["n_classes"] = 2
del layer_def["alternative_labels"]
elif class_.output_layer:
layer_def["targets"] = y_ref
layer_def["n_classes"] = n_classes
if "void_label" in args:
layer_def["void_label"] = void_label
elif "targets" in args:
layer_def["targets"] = y_ref
layer_def["name"] = name
layer_def["inputs"] = inputs
if "dropout" in args and not use_dropout:
layer_def["dropout"] = 0.0
if "tower_setup" in args:
layer_def["tower_setup"] = tower_setup
#check if all args are specified
defaults = spec[3]
if defaults is None:
defaults = []
n_non_default_args = len(args) - len(defaults)
non_default_args = args[1:n_non_default_args] # without self
for arg in non_default_args:
assert arg in layer_def, (name, arg)
layer = class_(**layer_def)
if tower_setup.is_main_train_tower:
print >> log.v4, name, "shape:", [l.get_shape().as_list() for l in layer.outputs]
layers[name] = layer
if class_.output_layer:
assert output_layer is None, "Currently only 1 output layer is supported"
output_layer = layer
assert output_layer is not None, "No output layer in network"
n = tf.shape(y_ref)[0]
assert len(output_layer.outputs) == 1, len(output_layer.outputs)
loss, measures, y_softmax = output_layer.loss, output_layer.measures, output_layer.outputs[0]
regularizers_tower = []
update_ops_tower = []
for l in layers.values():
self.summaries += l.summaries
regularizers_tower += l.regularizers
update_ops_tower += l.update_ops
n_params = sum([l.n_params for l in layers.values()])
return loss, measures, y_softmax, n, n_params, regularizers_tower, update_ops_tower, layers
def build_network(self, config, x_image, y_ref, void_label, n_classes, is_training,
freeze_batchnorm, flow=None):
gpus = config.int_list("gpus")
#only use one gpu for eval
if not is_training:
gpus = gpus[:1]
if self.use_partialflow:
assert len(gpus) == 1, len(gpus) # partialflow does not work with multigpu
network_def = config.dict("network")
batch_size_tower = self.batch_size / len(gpus)
assert batch_size_tower * len(gpus) == self.batch_size, (batch_size_tower, len(gpus), self.batch_size)
loss_summed = measures_accumulated = y_softmax_total = n_total = n_params = None
tower_losses = []
tower_regularizers = []
update_ops = []
tower_setups = []
tower_layers = []
first = True
for idx, gpu in enumerate(gpus):
if len(gpus) == 1:
x_image_tower = x_image
y_ref_tower = y_ref
variable_device = "/gpu:0"
else:
x_image_tower = x_image[idx * batch_size_tower: (idx + 1) * batch_size_tower]
y_ref_tower = y_ref[idx * batch_size_tower: (idx + 1) * batch_size_tower]
variable_device = "/cpu:0"
is_main_train_tower = is_training and first
tower_setup = TowerSetup(dtype=config.dtype, gpu=gpu, is_main_train_tower=is_main_train_tower,
is_training=is_training, freeze_batchnorm=freeze_batchnorm,
variable_device=variable_device, use_update_ops_collection=self.use_partialflow,
batch_size=self.batch_size)
tower_setups.append(tower_setup)
with tf.variable_scope(tf.get_variable_scope(), reuse=True if not first else None):
loss, measures, y_softmax, n, n_params_tower, regularizers, update_ops_tower, layers = self.build_tower(
network_def, x_image_tower, y_ref_tower, void_label, n_classes, tower_setup, flow=flow)
tower_layers.append(layers)
tower_losses.append(loss / tf.cast(n, tower_setup.dtype))
tower_regularizers.append(regularizers)
if first:
loss_summed = loss
measures_accumulated = measures
y_softmax_total = [y_softmax]
n_total = n
update_ops = update_ops_tower
first = False
n_params = n_params_tower
else:
loss_summed += loss
Measures.calc_measures_sum(measures_accumulated, measures)
y_softmax_total.append(y_softmax)
n_total += n
update_ops += update_ops_tower
assert n_params_tower == n_params
if len(gpus) == 1:
y_softmax_total = y_softmax_total[0]
else:
y_softmax_total = tf.concat(axis=0, values=y_softmax_total, name='y_softmax_total')
if self.current_graph_section is not None:
self.current_graph_section.__exit__(None, None, None)
return tower_losses, tower_regularizers, loss_summed, y_softmax_total, measures_accumulated, n_total, n_params, \
update_ops, tower_setups, tower_layers
def __init__(self, config, dataset, global_step, training, do_oneshot, use_partialflow=False, freeze_batchnorm=False,
name=""):
with tf.name_scope(name):
self.use_partialflow = use_partialflow
if use_partialflow:
import partialflow
self.graph_section_manager = partialflow.GraphSectionManager(verbose=False)
self.graph_sections = []
else:
self.graph_section_manager = None
self.current_graph_section = None
if training:
self.batch_size = config.int("batch_size")
self.chunk_size = config.int("chunk_size", -1)
else:
assert freeze_batchnorm
self.chunk_size = config.int("eval_chunk_size", -1)
if self.chunk_size == -1:
self.chunk_size = config.int("chunk_size", -1)
do_multi_sample_testing = config.int("n_test_samples", -1) != -1
if do_multi_sample_testing:
self.batch_size = 1
else:
self.batch_size = config.int("batch_size_eval", -1)
if self.batch_size == -1:
self.batch_size = config.int("batch_size")
n_classes = dataset.num_classes()
if config.bool("adjustable_output_layer", False):
n_classes = None
self.global_step = global_step
inputs_tensors_dict = dataset.create_input_tensors_dict(self.batch_size)
#inputs and labels are not optional
inputs = inputs_tensors_dict["inputs"]
labels = inputs_tensors_dict["labels"]
if "flow" in inputs_tensors_dict.keys():
flows = inputs_tensors_dict["flow"]
else:
flows = None
self.raw_labels = inputs_tensors_dict.get("raw_labels", None)
self.index_imgs = inputs_tensors_dict.get("index_imgs", None)
self.tags = inputs_tensors_dict.get("tags")
void_label = dataset.void_label()
#important: first inputs_and_labels (which creates summaries) and then access summaries
self.summaries = []
self.summaries += dataset.summaries
self.losses, self.regularizers, self.loss_summed, self.y_softmax, self.measures_accumulated, self.n_imgs, \
self.n_params, self.update_ops, self.tower_setups, self.tower_layers = self.build_network(
config, inputs, labels, void_label, n_classes, training, freeze_batchnorm, flow=flows)
def get_output_layer(self):
layers = self.tower_layers[0]
output_layers = [l for l in layers.values() if l.output_layer]
assert len(output_layers) == 1
return output_layers[0]