NCTCMumbai's picture
Upload 2571 files
0b8359d
raw
history blame
18.7 kB
# Copyright 2016 The TensorFlow Authors All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Various losses for training navigation agents.
Defines various loss functions for navigation agents,
compute_losses_multi_or.
"""
import os, numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.contrib import slim
from tensorflow.contrib.slim import arg_scope
from tensorflow.contrib.slim.nets import resnet_v2
from tensorflow.python.training import moving_averages
import logging
from src import utils
import src.file_utils as fu
from tfcode import tf_utils
def compute_losses_multi_or(logits, actions_one_hot, weights=None,
num_actions=-1, data_loss_wt=1., reg_loss_wt=1.,
ewma_decay=0.99, reg_loss_op=None):
assert(num_actions > 0), 'num_actions must be specified and must be > 0.'
with tf.name_scope('loss'):
if weights is None:
weight = tf.ones_like(actions_one_hot, dtype=tf.float32, name='weight')
actions_one_hot = tf.cast(tf.reshape(actions_one_hot, [-1, num_actions],
're_actions_one_hot'), tf.float32)
weights = tf.reduce_sum(tf.reshape(weights, [-1, num_actions], 're_weight'),
reduction_indices=1)
total = tf.reduce_sum(weights)
action_prob = tf.nn.softmax(logits)
action_prob = tf.reduce_sum(tf.multiply(action_prob, actions_one_hot),
reduction_indices=1)
example_loss = -tf.log(tf.maximum(tf.constant(1e-4), action_prob))
data_loss_op = tf.reduce_sum(example_loss * weights) / total
if reg_loss_op is None:
if reg_loss_wt > 0:
reg_loss_op = tf.add_n(tf.losses.get_regularization_losses())
else:
reg_loss_op = tf.constant(0.)
if reg_loss_wt > 0:
total_loss_op = data_loss_wt*data_loss_op + reg_loss_wt*reg_loss_op
else:
total_loss_op = data_loss_wt*data_loss_op
is_correct = tf.cast(tf.greater(action_prob, 0.5, name='pred_class'), tf.float32)
acc_op = tf.reduce_sum(is_correct*weights) / total
ewma_acc_op = moving_averages.weighted_moving_average(
acc_op, ewma_decay, weight=total, name='ewma_acc')
acc_ops = [ewma_acc_op]
return reg_loss_op, data_loss_op, total_loss_op, acc_ops
def get_repr_from_image(images_reshaped, modalities, data_augment, encoder,
freeze_conv, wt_decay, is_training):
# Pass image through lots of convolutional layers, to obtain pool5
if modalities == ['rgb']:
with tf.name_scope('pre_rgb'):
x = (images_reshaped + 128.) / 255. # Convert to brightness between 0 and 1.
if data_augment.relight and is_training:
x = tf_utils.distort_image(x, fast_mode=data_augment.relight_fast)
x = (x-0.5)*2.0
scope_name = encoder
elif modalities == ['depth']:
with tf.name_scope('pre_d'):
d_image = images_reshaped
x = 2*(d_image[...,0] - 80.0)/100.0
y = d_image[...,1]
d_image = tf.concat([tf.expand_dims(x, -1), tf.expand_dims(y, -1)], 3)
x = d_image
scope_name = 'd_'+encoder
resnet_is_training = is_training and (not freeze_conv)
with slim.arg_scope(resnet_v2.resnet_utils.resnet_arg_scope(resnet_is_training)):
fn = getattr(tf_utils, encoder)
x, end_points = fn(x, num_classes=None, global_pool=False,
output_stride=None, reuse=None,
scope=scope_name)
vars_ = slim.get_variables_to_restore()
conv_feat = x
return conv_feat, vars_
def default_train_step_kwargs(m, obj, logdir, rng_seed, is_chief, num_steps,
iters, train_display_interval,
dagger_sample_bn_false):
train_step_kwargs = {}
train_step_kwargs['obj'] = obj
train_step_kwargs['m'] = m
# rng_data has 2 independent rngs, one for sampling episodes and one for
# sampling perturbs (so that we can make results reproducible.
train_step_kwargs['rng_data'] = [np.random.RandomState(rng_seed),
np.random.RandomState(rng_seed)]
train_step_kwargs['rng_action'] = np.random.RandomState(rng_seed)
if is_chief:
train_step_kwargs['writer'] = tf.summary.FileWriter(logdir) #, m.tf_graph)
else:
train_step_kwargs['writer'] = None
train_step_kwargs['iters'] = iters
train_step_kwargs['train_display_interval'] = train_display_interval
train_step_kwargs['num_steps'] = num_steps
train_step_kwargs['logdir'] = logdir
train_step_kwargs['dagger_sample_bn_false'] = dagger_sample_bn_false
return train_step_kwargs
# Utilities for visualizing and analysing validation output.
def save_d_at_t(outputs, global_step, output_dir, metric_summary, N):
"""Save distance to goal at all time steps.
Args:
outputs : [gt_dist_to_goal].
global_step : number of iterations.
output_dir : output directory.
metric_summary : to append scalars to summary.
N : number of outputs to process.
"""
d_at_t = np.concatenate(map(lambda x: x[0][:,:,0]*1, outputs), axis=0)
fig, axes = utils.subplot(plt, (1,1), (5,5))
axes.plot(np.arange(d_at_t.shape[1]), np.mean(d_at_t, axis=0), 'r.')
axes.set_xlabel('time step')
axes.set_ylabel('dist to next goal')
axes.grid('on')
file_name = os.path.join(output_dir, 'dist_at_t_{:d}.png'.format(global_step))
with fu.fopen(file_name, 'w') as f:
fig.savefig(f, bbox_inches='tight', transparent=True, pad_inches=0)
file_name = os.path.join(output_dir, 'dist_at_t_{:d}.pkl'.format(global_step))
utils.save_variables(file_name, [d_at_t], ['d_at_t'], overwrite=True)
plt.close(fig)
return None
def save_all(outputs, global_step, output_dir, metric_summary, N):
"""Save numerous statistics.
Args:
outputs : [locs, goal_loc, gt_dist_to_goal, node_ids, perturbs]
global_step : number of iterations.
output_dir : output directory.
metric_summary : to append scalars to summary.
N : number of outputs to process.
"""
all_locs = np.concatenate(map(lambda x: x[0], outputs), axis=0)
all_goal_locs = np.concatenate(map(lambda x: x[1], outputs), axis=0)
all_d_at_t = np.concatenate(map(lambda x: x[2][:,:,0]*1, outputs), axis=0)
all_node_ids = np.concatenate(map(lambda x: x[3], outputs), axis=0)
all_perturbs = np.concatenate(map(lambda x: x[4], outputs), axis=0)
file_name = os.path.join(output_dir, 'all_locs_at_t_{:d}.pkl'.format(global_step))
vars = [all_locs, all_goal_locs, all_d_at_t, all_node_ids, all_perturbs]
var_names = ['all_locs', 'all_goal_locs', 'all_d_at_t', 'all_node_ids', 'all_perturbs']
utils.save_variables(file_name, vars, var_names, overwrite=True)
return None
def eval_ap(outputs, global_step, output_dir, metric_summary, N, num_classes=4):
"""Processes the collected outputs to compute AP for action prediction.
Args:
outputs : [logits, labels]
global_step : global_step.
output_dir : where to store results.
metric_summary : summary object to add summaries to.
N : number of outputs to process.
num_classes : number of classes to compute AP over, and to reshape tensors.
"""
if N >= 0:
outputs = outputs[:N]
logits = np.concatenate(map(lambda x: x[0], outputs), axis=0).reshape((-1, num_classes))
labels = np.concatenate(map(lambda x: x[1], outputs), axis=0).reshape((-1, num_classes))
aps = []
for i in range(logits.shape[1]):
ap, rec, prec = utils.calc_pr(labels[:,i], logits[:,i])
ap = ap[0]
tf_utils.add_value_to_summary(metric_summary, 'aps/ap_{:d}: '.format(i), ap)
aps.append(ap)
return aps
def eval_dist(outputs, global_step, output_dir, metric_summary, N):
"""Processes the collected outputs during validation to
1. Plot the distance over time curve.
2. Compute mean and median distances.
3. Plots histogram of end distances.
Args:
outputs : [locs, goal_loc, gt_dist_to_goal].
global_step : global_step.
output_dir : where to store results.
metric_summary : summary object to add summaries to.
N : number of outputs to process.
"""
SUCCESS_THRESH = 3
if N >= 0:
outputs = outputs[:N]
# Plot distance at time t.
d_at_t = []
for i in range(len(outputs)):
locs, goal_loc, gt_dist_to_goal = outputs[i]
d_at_t.append(gt_dist_to_goal[:,:,0]*1)
# Plot the distance.
fig, axes = utils.subplot(plt, (1,1), (5,5))
d_at_t = np.concatenate(d_at_t, axis=0)
axes.plot(np.arange(d_at_t.shape[1]), np.mean(d_at_t, axis=0), 'r.')
axes.set_xlabel('time step')
axes.set_ylabel('dist to next goal')
axes.grid('on')
file_name = os.path.join(output_dir, 'dist_at_t_{:d}.png'.format(global_step))
with fu.fopen(file_name, 'w') as f:
fig.savefig(f, bbox_inches='tight', transparent=True, pad_inches=0)
file_name = os.path.join(output_dir, 'dist_at_t_{:d}.pkl'.format(global_step))
utils.save_variables(file_name, [d_at_t], ['d_at_t'], overwrite=True)
plt.close(fig)
# Plot the trajectories and the init_distance and final distance.
d_inits = []
d_ends = []
for i in range(len(outputs)):
locs, goal_loc, gt_dist_to_goal = outputs[i]
d_inits.append(gt_dist_to_goal[:,0,0]*1)
d_ends.append(gt_dist_to_goal[:,-1,0]*1)
# Plot the distance.
fig, axes = utils.subplot(plt, (1,1), (5,5))
d_inits = np.concatenate(d_inits, axis=0)
d_ends = np.concatenate(d_ends, axis=0)
axes.plot(d_inits+np.random.rand(*(d_inits.shape))-0.5,
d_ends+np.random.rand(*(d_ends.shape))-0.5, '.', mec='red', mew=1.0)
axes.set_xlabel('init dist'); axes.set_ylabel('final dist');
axes.grid('on'); axes.axis('equal');
title_str = 'mean: {:0.1f}, 50: {:0.1f}, 75: {:0.2f}, s: {:0.1f}'
title_str = title_str.format(
np.mean(d_ends), np.median(d_ends), np.percentile(d_ends, q=75),
100*(np.mean(d_ends <= SUCCESS_THRESH)))
axes.set_title(title_str)
file_name = os.path.join(output_dir, 'dist_{:d}.png'.format(global_step))
with fu.fopen(file_name, 'w') as f:
fig.savefig(f, bbox_inches='tight', transparent=True, pad_inches=0)
file_name = os.path.join(output_dir, 'dist_{:d}.pkl'.format(global_step))
utils.save_variables(file_name, [d_inits, d_ends], ['d_inits', 'd_ends'],
overwrite=True)
plt.close(fig)
# Plot the histogram of the end_distance.
with plt.style.context('seaborn-white'):
d_ends_ = np.sort(d_ends)
d_inits_ = np.sort(d_inits)
leg = [];
fig, ax = utils.subplot(plt, (1,1), (5,5))
ax.grid('on')
ax.set_xlabel('Distance from goal'); ax.xaxis.label.set_fontsize(16);
ax.set_ylabel('Fraction of data'); ax.yaxis.label.set_fontsize(16);
ax.plot(d_ends_, np.arange(d_ends_.size)*1./d_ends_.size, 'r')
ax.plot(d_inits_, np.arange(d_inits_.size)*1./d_inits_.size, 'k')
leg.append('Final'); leg.append('Init');
ax.legend(leg, fontsize='x-large');
ax.set_axis_on()
title_str = 'mean: {:0.1f}, 50: {:0.1f}, 75: {:0.2f}, s: {:0.1f}'
title_str = title_str.format(
np.mean(d_ends), np.median(d_ends), np.percentile(d_ends, q=75),
100*(np.mean(d_ends <= SUCCESS_THRESH)))
ax.set_title(title_str)
file_name = os.path.join(output_dir, 'dist_hist_{:d}.png'.format(global_step))
with fu.fopen(file_name, 'w') as f:
fig.savefig(f, bbox_inches='tight', transparent=True, pad_inches=0)
# Log distance metrics.
tf_utils.add_value_to_summary(metric_summary, 'dists/success_init: ',
100*(np.mean(d_inits <= SUCCESS_THRESH)))
tf_utils.add_value_to_summary(metric_summary, 'dists/success_end: ',
100*(np.mean(d_ends <= SUCCESS_THRESH)))
tf_utils.add_value_to_summary(metric_summary, 'dists/dist_init (75): ',
np.percentile(d_inits, q=75))
tf_utils.add_value_to_summary(metric_summary, 'dists/dist_end (75): ',
np.percentile(d_ends, q=75))
tf_utils.add_value_to_summary(metric_summary, 'dists/dist_init (median): ',
np.median(d_inits))
tf_utils.add_value_to_summary(metric_summary, 'dists/dist_end (median): ',
np.median(d_ends))
tf_utils.add_value_to_summary(metric_summary, 'dists/dist_init (mean): ',
np.mean(d_inits))
tf_utils.add_value_to_summary(metric_summary, 'dists/dist_end (mean): ',
np.mean(d_ends))
return np.median(d_inits), np.median(d_ends), np.mean(d_inits), np.mean(d_ends), \
np.percentile(d_inits, q=75), np.percentile(d_ends, q=75), \
100*(np.mean(d_inits) <= SUCCESS_THRESH), 100*(np.mean(d_ends) <= SUCCESS_THRESH)
def plot_trajectories(outputs, global_step, output_dir, metric_summary, N):
"""Processes the collected outputs during validation to plot the trajectories
in the top view.
Args:
outputs : [locs, orig_maps, goal_loc].
global_step : global_step.
output_dir : where to store results.
metric_summary : summary object to add summaries to.
N : number of outputs to process.
"""
if N >= 0:
outputs = outputs[:N]
N = len(outputs)
plt.set_cmap('gray')
fig, axes = utils.subplot(plt, (N, outputs[0][1].shape[0]), (5,5))
axes = axes.ravel()[::-1].tolist()
for i in range(N):
locs, orig_maps, goal_loc = outputs[i]
is_semantic = np.isnan(goal_loc[0,0,1])
for j in range(orig_maps.shape[0]):
ax = axes.pop();
ax.plot(locs[j,0,0], locs[j,0,1], 'ys')
# Plot one by one, so that they come in different colors.
for k in range(goal_loc.shape[1]):
if not is_semantic:
ax.plot(goal_loc[j,k,0], goal_loc[j,k,1], 's')
if False:
ax.plot(locs[j,:,0], locs[j,:,1], 'r.', ms=3)
ax.imshow(orig_maps[j,0,:,:,0], origin='lower')
ax.set_axis_off();
else:
ax.scatter(locs[j,:,0], locs[j,:,1], c=np.arange(locs.shape[1]),
cmap='jet', s=10, lw=0)
ax.imshow(orig_maps[j,0,:,:,0], origin='lower', vmin=-1.0, vmax=2.0)
if not is_semantic:
xymin = np.minimum(np.min(goal_loc[j,:,:], axis=0), np.min(locs[j,:,:], axis=0))
xymax = np.maximum(np.max(goal_loc[j,:,:], axis=0), np.max(locs[j,:,:], axis=0))
else:
xymin = np.min(locs[j,:,:], axis=0)
xymax = np.max(locs[j,:,:], axis=0)
xy1 = (xymax+xymin)/2. - np.maximum(np.max(xymax-xymin), 12)
xy2 = (xymax+xymin)/2. + np.maximum(np.max(xymax-xymin), 12)
ax.set_xlim([xy1[0], xy2[0]])
ax.set_ylim([xy1[1], xy2[1]])
ax.set_axis_off()
file_name = os.path.join(output_dir, 'trajectory_{:d}.png'.format(global_step))
with fu.fopen(file_name, 'w') as f:
fig.savefig(f, bbox_inches='tight', transparent=True, pad_inches=0)
plt.close(fig)
return None
def add_default_summaries(mode, arop_full_summary_iters, summarize_ops,
summarize_names, to_aggregate, action_prob_op,
input_tensors, scope_name):
assert(mode == 'train' or mode == 'val' or mode == 'test'), \
'add_default_summaries mode is neither train or val or test.'
s_ops = tf_utils.get_default_summary_ops()
if mode == 'train':
s_ops.summary_ops, s_ops.print_summary_ops, additional_return_ops, \
arop_summary_iters, arop_eval_fns = tf_utils.simple_summaries(
summarize_ops, summarize_names, mode, to_aggregate=False,
scope_name=scope_name)
s_ops.additional_return_ops += additional_return_ops
s_ops.arop_summary_iters += arop_summary_iters
s_ops.arop_eval_fns += arop_eval_fns
elif mode == 'val':
s_ops.summary_ops, s_ops.print_summary_ops, additional_return_ops, \
arop_summary_iters, arop_eval_fns = tf_utils.simple_summaries(
summarize_ops, summarize_names, mode, to_aggregate=to_aggregate,
scope_name=scope_name)
s_ops.additional_return_ops += additional_return_ops
s_ops.arop_summary_iters += arop_summary_iters
s_ops.arop_eval_fns += arop_eval_fns
elif mode == 'test':
s_ops.summary_ops, s_ops.print_summary_ops, additional_return_ops, \
arop_summary_iters, arop_eval_fns = tf_utils.simple_summaries(
[], [], mode, to_aggregate=[], scope_name=scope_name)
s_ops.additional_return_ops += additional_return_ops
s_ops.arop_summary_iters += arop_summary_iters
s_ops.arop_eval_fns += arop_eval_fns
if mode == 'val':
arop = s_ops.additional_return_ops
arop += [[action_prob_op, input_tensors['train']['action']]]
arop += [[input_tensors['step']['loc_on_map'],
input_tensors['common']['goal_loc'],
input_tensors['step']['gt_dist_to_goal']]]
arop += [[input_tensors['step']['loc_on_map'],
input_tensors['common']['orig_maps'],
input_tensors['common']['goal_loc']]]
s_ops.arop_summary_iters += [-1, arop_full_summary_iters,
arop_full_summary_iters]
s_ops.arop_eval_fns += [eval_ap, eval_dist, plot_trajectories]
elif mode == 'test':
arop = s_ops.additional_return_ops
arop += [[input_tensors['step']['loc_on_map'],
input_tensors['common']['goal_loc'],
input_tensors['step']['gt_dist_to_goal']]]
arop += [[input_tensors['step']['gt_dist_to_goal']]]
arop += [[input_tensors['step']['loc_on_map'],
input_tensors['common']['goal_loc'],
input_tensors['step']['gt_dist_to_goal'],
input_tensors['step']['node_ids'],
input_tensors['step']['perturbs']]]
arop += [[input_tensors['step']['loc_on_map'],
input_tensors['common']['orig_maps'],
input_tensors['common']['goal_loc']]]
s_ops.arop_summary_iters += [-1, -1, -1, arop_full_summary_iters]
s_ops.arop_eval_fns += [eval_dist, save_d_at_t, save_all,
plot_trajectories]
return s_ops