doanh25032004's picture
Upload folder using huggingface_hub
872b0a0 verified
Raw
History Blame Contribute Delete
18.2 kB
import os
import re
import numpy as np
from multiprocessing import Process
#from matplotlib.pyplot import plot, show
import tensorflow as tf
from tensorflow.python.client import timeline
import tensorflow.contrib.slim as slim
from . import util
from ..ops import forward_warp
from .image_warp import image_warp
from .unsupervised import unsupervised_loss
from .supervised import supervised_loss
from .losses import occlusion, DISOCC_THRESH, create_outgoing_mask
from .flow_util import flow_error_avg, flow_to_color, flow_error_image, outlier_pct
from ..gui import display
from .util import summarized_placeholder
from .input import resize_input, resize_output_crop, resize_output, resize_output_flow
def restore_networks(sess, params, ckpt, ckpt_path=None):
finetune = params.get('finetune', [])
train_all = params.get('train_all', None)
spec = params.get('flownet', 'S')
flownet_num = len(spec)
net_names = ['flownet_c'] + ['stack_{}_flownet'.format(i+1) for i in range(flownet_num - 1)]
assert len(finetune) <= flownet_num
# Save all trained networks, restore all networks which are kept fixed
if train_all:
restore_external_nets = finetune if ckpt is None else []
variables_to_save = slim.get_variables_to_restore(include=net_names)
else:
restore_external_nets = finetune if ckpt is None else finetune[:flownet_num - 1]
variables_to_save = slim.get_variables_to_restore(include=[net_names[-1]])
saver = tf.train.Saver(variables_to_save, max_to_keep=1000)
sess.run(tf.global_variables_initializer())
if ckpt is not None:
# continue training
saver.restore(sess, ckpt.model_checkpoint_path)
saver.recover_last_checkpoints(ckpt.all_model_checkpoint_paths)
for i, ckpt in enumerate(restore_external_nets):
print('-- restore', net_names[i], ckpt.model_checkpoint_path)
try:
nets_to_restore = [net_names[i]]
variables_to_restore = slim.get_variables_to_restore(
include=nets_to_restore)
restorer = tf.train.Saver(variables_to_restore)
restorer.restore(sess, ckpt.model_checkpoint_path)
except:
# load partial network (missing final 2 upconvolutions)
nets_to_restore = [net_names[i]]
variables_to_restore = slim.get_variables_to_restore(
include=nets_to_restore)
variables_to_restore = [v for v in variables_to_restore
if not 'full_res' in v.name]
restorer = tf.train.Saver(variables_to_restore)
restorer.restore(sess, ckpt.model_checkpoint_path)
return saver
def _add_loss_summaries():
losses = tf.get_collection('losses')
for l in losses:
tensor_name = re.sub('tower_[0-9]*/', '', l.op.name)
tf.summary.scalar(tensor_name, l)
def _add_param_summaries():
params = tf.get_collection('params')
for p in params:
tensor_name = re.sub('tower_[0-9]*/', '', p.op.name)
tf.summary.scalar(tensor_name, p)
def _add_image_summaries():
images = tf.get_collection('train_images')
for im in images:
tensor_name = re.sub('tower_[0-9]*/', '', im.op.name)
tf.summary.image(tensor_name, im)
def _eval_plot(results, image_names, title):
import matplotlib.pyplot as plt
display(results, image_names, title)
class Trainer():
def __init__(self, train_batch_fn, eval_batch_fn, params,
train_summaries_dir, eval_summaries_dir, ckpt_dir,
normalization, debug=False, experiment="", interactive_plot=False,
supervised=False, devices=None):
self.train_summaries_dir = train_summaries_dir
self.eval_summaries_dir = eval_summaries_dir
self.ckpt_dir = ckpt_dir
self.params = params
self.debug = debug
self.train_batch_fn = train_batch_fn
self.eval_batch_fn = eval_batch_fn
self.normalization = normalization
self.experiment = experiment
self.interactive_plot = interactive_plot
self.plot_proc = None
self.supervised = supervised
self.loss_fn = supervised_loss if supervised else unsupervised_loss
self.devices = devices or '/gpu:0'
self.shared_device = devices[0] if len(devices) == 1 else '/cpu:0'
def run(self, min_iter, max_iter):
"""Train (at most) from min_iter + 1 to max_iter.
If checkpoints are found in ckpt_dir,
they must be have a global_step within [min_iter, max_iter]. In this case,
training is continued from global_step + 1 until max_iter is reached.
"""
save_interval = self.params['save_interval']
ckpt = tf.train.get_checkpoint_state(self.ckpt_dir)
if ckpt is not None:
ckpt_path = ckpt.model_checkpoint_path
global_step = int(ckpt_path.split('/')[-1].split('-')[-1])
assert global_step >= min_iter, 'training stage not reached'
start_iter = global_step + 1
if start_iter > max_iter:
print('-- train: max_iter reached')
return
else:
start_iter = min_iter + 1
print('-- training from i = {} to {}'.format(start_iter, max_iter))
assert (max_iter - start_iter + 1) % save_interval == 0
for i in range(start_iter, max_iter + 1, save_interval):
self.train(i, i + save_interval - 1, i - (min_iter + 1))
self.eval(1)
if self.plot_proc:
self.plot_proc.join()
def get_train_and_loss_ops(self, batch, learning_rate, global_step):
if self.params['flownet'] == 'resnet':
opt = tf.train.MomentumOptimizer(learning_rate, 0.9)
else:
opt = tf.train.AdamOptimizer(beta1=0.9, beta2=0.999,
learning_rate=learning_rate)
def _add_summaries():
_add_loss_summaries()
_add_param_summaries()
if self.debug:
_add_image_summaries()
if len(self.devices) == 1:
loss_ = self.loss_fn(batch, self.params, self.normalization)
train_op = opt.minimize(loss_)
_add_summaries()
else:
tower_grads = []
with tf.variable_scope(tf.get_variable_scope()):
for i, devid in enumerate(self.devices):
with tf.device(devid):
with tf.name_scope('tower_{}'.format(i)) as scope:
loss_ = self.loss_fn(batch, self.params, self.normalization)
_add_summaries()
# Reuse variables for the next tower.
tf.get_variable_scope().reuse_variables()
# Retain the summaries from the final tower.
tower_summaries = tf.get_collection(tf.GraphKeys.SUMMARIES,
scope)
grads = opt.compute_gradients(loss_)
tower_grads.append(grads)
grads = average_gradients(tower_grads)
apply_gradient_op = opt.apply_gradients(grads)
train_op = apply_gradient_op
return train_op, loss_
def train(self, start_iter, max_iter, iter_offset):
ckpt = tf.train.get_checkpoint_state(self.ckpt_dir)
with tf.Graph().as_default(), tf.device(self.shared_device):
batch = self.train_batch_fn(iter_offset)
with tf.name_scope('params') as scope:
learning_rate_ = util.summarized_placeholder('learning_rate', 'train')
summaries = tf.get_collection(tf.GraphKeys.SUMMARIES, scope)
global_step_ = tf.placeholder(tf.int32, name="global_step")
train_op, loss_ = self.get_train_and_loss_ops(batch, learning_rate_, global_step_)
summaries = tf.get_collection(tf.GraphKeys.SUMMARIES)
summary_ = tf.summary.merge(summaries)
sess_config = tf.ConfigProto(allow_soft_placement=True)
with tf.Session(config=sess_config) as sess:
if self.debug:
summary_writer = tf.summary.FileWriter(self.train_summaries_dir,
sess.graph)
run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
run_metadata = tf.RunMetadata()
else:
summary_writer = tf.summary.FileWriter(self.train_summaries_dir)
run_options = None
run_metadata = None
saver = restore_networks(sess, self.params, ckpt)
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
for local_i, i in enumerate(range(start_iter, max_iter + 1)):
#if INTERACTIVE_PLOT:
# plt.title = "{} ({})".format(self.experiment, i)
decay_iters = local_i + iter_offset
if 'manual_decay_lrs' in self.params \
and 'manual_decay_iters' in self.params:
decay_index = 0
iter_counter = 0
for decay_i, manual_decay_iter in enumerate(self.params['manual_decay_iters']):
iter_counter += manual_decay_iter
if decay_iters <= iter_counter:
decay_index = decay_i
break
learning_rate = self.params['manual_decay_lrs'][decay_index]
else:
decay_interval = self.params['decay_interval']
decay_after = self.params.get('decay_after', 0)
if decay_iters >= decay_after:
decay_minimum = decay_after / decay_interval
decay = (decay_iters // decay_interval) - decay_minimum
learning_rate = self.params['learning_rate'] / (2 ** decay)
else:
learning_rate = self.params['learning_rate']
feed_dict = {learning_rate_: learning_rate, global_step_: i}
_, loss = sess.run(
[train_op, loss_],
feed_dict=feed_dict,
options=run_options,
run_metadata=run_metadata)
if i == 1 or i % self.params['display_interval'] == 0:
summary = sess.run(summary_, feed_dict=feed_dict)
summary_writer.add_summary(summary, i)
print("-- train: i = {}, loss = {}".format(i, loss))
save_path = os.path.join(self.ckpt_dir, 'model.ckpt')
saver.save(sess, save_path, global_step=max_iter)
summary_writer.close()
coord.request_stop()
coord.join(threads)
def eval(self, num):
assert num == 1 # TODO enable num > 1
with tf.Graph().as_default():
inputs = self.eval_batch_fn()
im1, im2, input_shape = inputs[:3]
truths = inputs[3:]
height, width, _ = tf.unstack(tf.squeeze(input_shape), num=3, axis=0)
im1 = resize_input(im1, height, width, 384, 1280)
im2 = resize_input(im2, height, width, 384, 1280)
_, flow, flow_bw = unsupervised_loss(
(im1, im2),
params=self.params,
normalization=self.normalization,
augment=False, return_flow=True)
im1 = resize_output(im1, height, width, 3)
im2 = resize_output(im2, height, width, 3)
flow = resize_output_flow(flow, height, width, 2)
flow_bw = resize_output_flow(flow_bw, height, width, 2)
variables_to_restore = tf.all_variables()
images_ = [image_warp(im1, flow) / 255,
flow_to_color(flow),
1 - (1 - occlusion(flow, flow_bw)[0]) * create_outgoing_mask(flow) ,
forward_warp(flow_bw) < DISOCC_THRESH]
image_names = ['warped image', 'flow', 'occ', 'reverse disocc']
values_ = []
averages_ = []
truth_tuples = []
if len(truths) == 4:
flow_occ, mask_occ, flow_noc, mask_noc = truths
flow_occ = resize_output_crop(flow_occ, height, width, 2)
flow_noc = resize_output_crop(flow_noc, height, width, 2)
mask_occ = resize_output_crop(mask_occ, height, width, 1)
mask_noc = resize_output_crop(mask_noc, height, width, 1)
truth_tuples.append(('occluded', flow_occ, mask_occ))
truth_tuples.append(('non-occluded', flow_noc, mask_noc))
images_ += [flow_error_image(flow, flow_occ, mask_occ, mask_noc)]
image_names += ['flow error']
else:
raise NotImplementedError()
truth_tuples.append(('flow', truths[0], truths[1]))
for name, gt_flow, mask in truth_tuples:
error_ = flow_error_avg(gt_flow, flow, mask)
error_avg_ = summarized_placeholder('AEE/' + name, key='eval_avg')
outliers_ = outlier_pct(gt_flow, flow, mask)
outliers_avg = summarized_placeholder('outliers/' + name,
key='eval_avg')
values_.extend([error_, outliers_])
averages_.extend([error_avg_, outliers_avg])
losses = tf.get_collection('losses')
for l in losses:
values_.append(l)
tensor_name = re.sub('tower_[0-9]*/', '', l.op.name)
loss_avg_ = summarized_placeholder(tensor_name, key='eval_avg')
averages_.append(loss_avg_)
ckpt = tf.train.get_checkpoint_state(self.ckpt_dir)
assert ckpt is not None, "No checkpoints to evaluate"
# Correct path for ckpts from different machine
# ckpt_path = self.ckpt_dir + "/" + os.path.basename(ckpt.model_checkpoint_path)
ckpt_path = ckpt.model_checkpoint_path
with tf.Session() as sess:
summary_writer = tf.summary.FileWriter(self.eval_summaries_dir)
saver = tf.train.Saver(variables_to_restore)
sess.run(tf.global_variables_initializer())
sess.run(tf.local_variables_initializer())
restore_networks(sess, self.params, ckpt)
global_step = ckpt_path.split('/')[-1].split('-')[-1]
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess,
coord=coord)
averages = np.zeros(len(averages_))
num_iters = 0
image_lists = []
try:
while not coord.should_stop():
results = sess.run(values_ + images_)
values = results[:len(averages_)]
images = results[len(averages_):]
image_lists.append(images)
averages += values
num_iters += 1
except tf.errors.OutOfRangeError:
pass
averages /= num_iters
feed = {k: v for (k, v) in zip(averages_, averages)}
summary_ = tf.summary.merge_all('eval_avg')
summary = sess.run(summary_, feed_dict=feed)
summary_writer.add_summary(summary, global_step)
print("-- eval: i = {}".format(global_step))
coord.request_stop()
coord.join(threads)
summary_writer.close()
if self.interactive_plot:
if self.plot_proc:
self.plot_proc.terminate()
self.plot_proc = Process(target=_eval_plot,
args=([image_lists], image_names,
"{} (i={})".format(self.experiment,
global_step)))
self.plot_proc.start()
def average_gradients(tower_grads):
"""Calculate the average gradient for each shared variable across all towers.
Note that this function provides a synchronization point across all towers.
Args:
tower_grads: List of lists of (gradient, variable) tuples. The outer list
is over individual gradients. The inner list is over the gradient
calculation for each tower.
Returns:
List of pairs of (gradient, variable) where the gradient has been averaged
across all towers.
"""
average_grads = []
for grad_and_vars in zip(*tower_grads):
# Note that each grad_and_vars looks like the following:
# ((grad0_gpu0, var0_gpu0), ... , (grad0_gpuN, var0_gpuN))
grads = []
for g, _ in grad_and_vars:
if g is not None:
# Add 0 dimension to the gradients to represent the tower.
expanded_g = tf.expand_dims(g, 0)
# Append on a 'tower' dimension which we will average over below.
grads.append(expanded_g)
if grads != []:
# Average over the 'tower' dimension.
grad = tf.concat(grads, 0)
grad = tf.reduce_mean(grad, 0)
# Keep in mind that the Variables are redundant because they are shared
# across towers. So .. we will just return the first tower's pointer to
# the Variable.
v = grad_and_vars[0][1]
grad_and_var = (grad, v)
average_grads.append(grad_and_var)
return average_grads