def expand_bboxes(xmin, xmax, ymin, ymax, cfg):
"""
Expand the bboxes.
"""
w = xmax - xmin
h = ymax - ymin
w = w * cfg.WIDTH_EXPANSION_FACTOR
h = h * cfg.HEIGHT_EXPANSION_FACTOR
half_w = w / 2.
half_h = h / 2.
xmin = tf.clip_by_value(xmin - half_w, 0, 1)
xmax = tf.clip_by_value(xmax + half_w, 0, 1)
ymin = tf.clip_by_value(ymin - half_h, 0, 1)
ymax = tf.clip_by_value(ymax + half_h, 0, 1)
return tf.tuple([xmin, xmax, ymin, ymax])
python类tuple()的实例源码
def _precision_recall(n_gbboxes, n_detections, scores, tp, fp, scope=None):
"""Compute precision and recall from scores, true positives and false
positives booleans arrays
"""
# Sort by score.
with tf.name_scope(scope, 'prec_rec', [n_gbboxes, scores, tp, fp]):
# Sort detections by score.
scores, idxes = tf.nn.top_k(scores, k=n_detections, sorted=True)
tp = tf.gather(tp, idxes)
fp = tf.gather(fp, idxes)
# Computer recall and precision.
dtype = tf.float64
tp = tf.cumsum(tf.cast(tp, dtype), axis=0)
fp = tf.cumsum(tf.cast(fp, dtype), axis=0)
recall = _safe_div(tp, tf.cast(n_gbboxes, dtype), 'recall')
precision = _safe_div(tp, tp + fp, 'precision')
return tf.tuple([precision, recall])
def _precision_recall(n_gbboxes, n_detections, scores, tp, fp, scope=None):
"""Compute precision and recall from scores, true positives and false
positives booleans arrays
"""
# Sort by score.
with tf.name_scope(scope, 'prec_rec', [n_gbboxes, scores, tp, fp]):
# Sort detections by score.
scores, idxes = tf.nn.top_k(scores, k=n_detections, sorted=True)
tp = tf.gather(tp, idxes)
fp = tf.gather(fp, idxes)
# Computer recall and precision.
dtype = tf.float64
tp = tf.cumsum(tf.cast(tp, dtype), axis=0)
fp = tf.cumsum(tf.cast(fp, dtype), axis=0)
recall = _safe_div(tp, tf.cast(n_gbboxes, dtype), 'recall')
precision = _safe_div(tp, tp + fp, 'precision')
return tf.tuple([precision, recall])
def recompute_grad(fn):
"""Decorator that recomputes the function on the backwards pass.
Args:
fn: a function that takes Tensors (all as positional arguments) and returns
a tuple of Tensors.
Returns:
A wrapped fn that is identical to fn when called, but its activations will
be discarded and recomputed on the backwards pass (i.e. on a call to
tf.gradients).
"""
@functools.wraps(fn)
def wrapped(*args):
return _recompute_grad(fn, args)
return wrapped
def fn_device_dependency(name, device=""):
"""Add control deps for name and device."""
key = name + "_" + device
outs = []
def body():
with tf.control_dependencies(fn_device_dependency_dict()[key]):
yield outs
assert outs
deps = outs
if isinstance(outs[0], list) or isinstance(outs[0], tuple):
assert len(outs) == 1
deps = outs[0]
fn_device_dependency_dict()[key] = deps
if device:
with tf.device(device):
return body()
else:
return body()
def _clip_grad_global_norms(self, tvars, loss, opt, global_norm=8, gate_gradients=1, gradient_noise_scale=None, GATE_GRAPH=2, grad_loss=None, agre_method=None, col_grad_ops=False):
"""Clips the gradients by the given value.
Args:
tvars: trainable variables used for gradint updates
loss: total loss of the network
opt: optimizer
global_norm: the maximum global norm
Returns:
A list of clipped gradient to variable pairs.
"""
var_refs = [v.read_value() for v in tvars]
grads = tf.gradients(loss, var_refs, grad_ys=grad_loss, gate_gradients=(
gate_gradients == 1), aggregation_method=agre_method, colocate_gradients_with_ops=col_grad_ops)
if gradient_noise_scale is not None:
grads = self._add_scaled_noise_to_gradients(
list(zip(grads, tvars)), gradient_noise_scale=gradient_noise_scale)
if gate_gradients == GATE_GRAPH:
grads = tf.tuple(grads)
grads, _ = tf.clip_by_global_norm(grads, global_norm)
grads_and_vars = list(zip(grads, tvars))
return grads_and_vars
def _get_step(self, inputs):
Z, Y, X, theta, lmbd = self.inputs
K, p = self.D.shape
L = self.L
with tf.name_scope("ISTA_iteration"):
self.S = tf.constant(np.eye(K, dtype=np.float32) - self.S0/L,
shape=[K, K], name='S')
self.We = tf.constant(self.D.T/L, shape=[p, K],
dtype=tf.float32, name='We')
hk = tf.matmul(Y, self.S) + tf.matmul(X, self.We)
self.step_FISTA = Zk = soft_thresholding(hk, lmbd/L)
# self.theta_k = tk = (tf.sqrt(theta*theta+4) - theta)*theta/2
self.theta_k = tk = (1 + tf.sqrt(1 + 4*theta*theta))/2
dZ = tf.subtract(Zk, Z)
# self.Yk = Zk + tk*(1/theta-1)*dZ
self.Yk = Zk + (theta-1)/tk*dZ
self.dz = tf.reduce_mean(tf.reduce_sum(
dZ*dZ, reduction_indices=[1]))
step = tf.tuple([Zk, tk, self.Yk])
return step, self.dz
def _precision_recall(n_gbboxes, n_detections, scores, tp, fp, scope=None):
"""Compute precision and recall from scores, true positives and false
positives booleans arrays
"""
# Sort by score.
with tf.name_scope(scope, 'prec_rec', [n_gbboxes, scores, tp, fp]):
# Sort detections by score.
scores, idxes = tf.nn.top_k(scores, k=n_detections, sorted=True)
tp = tf.gather(tp, idxes)
fp = tf.gather(fp, idxes)
# Computer recall and precision.
dtype = tf.float64
tp = tf.cumsum(tf.cast(tp, dtype), axis=0)
fp = tf.cumsum(tf.cast(fp, dtype), axis=0)
recall = _safe_div(tp, tf.cast(n_gbboxes, dtype), 'recall')
precision = _safe_div(tp, tp + fp, 'precision')
return tf.tuple([precision, recall])
def recompute_grad(fn):
"""Decorator that recomputes the function on the backwards pass.
Args:
fn: a function that takes Tensors (all as positional arguments) and returns
a tuple of Tensors.
Returns:
A wrapped fn that is identical to fn when called, but its activations will
be discarded and recomputed on the backwards pass (i.e. on a call to
tf.gradients).
"""
@functools.wraps(fn)
def wrapped(*args):
return _recompute_grad(fn, args)
return wrapped
def birnn(cell, inputs, sequence_length, initial_state_fw=None, initial_state_bw=None, ff_keep_prob=1., recur_keep_prob=1., dtype=tf.float32, scope=None):
""""""
# Forward direction
with tf.variable_scope(scope or 'BiRNN_FW') as fw_scope:
output_fw, output_state_fw = rnn(cell, inputs, sequence_length, initial_state_fw, ff_keep_prob, recur_keep_prob, dtype, scope=fw_scope)
# Backward direction
rev_inputs = tf.reverse_sequence(inputs, sequence_length, 1, 0)
with tf.variable_scope(scope or 'BiRNN_BW') as bw_scope:
output_bw, output_state_bw = rnn(cell, rev_inputs, sequence_length, initial_state_bw, ff_keep_prob, recur_keep_prob, dtype, scope=bw_scope)
output_bw = tf.reverse_sequence(output_bw, sequence_length, 1, 0)
# Concat each of the forward/backward outputs
outputs = tf.concat([output_fw, output_bw], 2)
return outputs, tf.tuple([output_state_fw, output_state_bw])
#===============================================================
def filterOutputBoxes(self, boxes, scores, others=[], preNmsCount=6000, maxOutSize=300, nmsThreshold=0.7):
with tf.name_scope("filter_output_boxes"):
scores = tf.nn.softmax(scores)[:,1]
scores = tf.reshape(scores,[-1])
#Clip boxes to edge
boxes = self.clipBoxesToEdge(boxes)
#Remove empty boxes
boxes, scores = BoxUtils.filterSmallBoxes(boxes, [scores])
scores, boxes = tf.cond(tf.shape(scores)[0] > preNmsCount , lambda: tf.tuple(MultiGather.gatherTopK(scores, preNmsCount, [boxes])), lambda: tf.tuple([scores, boxes]))
#NMS filter
nmsIndices = tf.image.non_max_suppression(boxes, scores, iou_threshold=nmsThreshold, max_output_size=maxOutSize)
nmsIndices = tf.expand_dims(nmsIndices, axis=-1)
return MultiGather.gather([boxes, scores]+others, nmsIndices)
def _precision_recall(n_gbboxes, n_detections, scores, tp, fp, scope=None):
"""Compute precision and recall from scores, true positives and false
positives booleans arrays
"""
# Sort by score.
with tf.name_scope(scope, 'prec_rec', [n_gbboxes, scores, tp, fp]):
# Sort detections by score.
scores, idxes = tf.nn.top_k(scores, k=n_detections, sorted=True)
tp = tf.gather(tp, idxes)
fp = tf.gather(fp, idxes)
# Computer recall and precision.
dtype = tf.float64
tp = tf.cumsum(tf.cast(tp, dtype), axis=0)
fp = tf.cumsum(tf.cast(fp, dtype), axis=0)
recall = _safe_div(tp, tf.cast(n_gbboxes, dtype), 'recall')
precision = _safe_div(tp, tp + fp, 'precision')
return tf.tuple([precision, recall])
def _combine(self, concat, *argv):
if concat:
y = _concat(list(argv), axis=3)
else:
y = tuple(argv)
return y
def _split(self, concat, n_filter, x):
if concat or type(x) != tuple:
x1 = x[:, :, :, :n_filter // 2]
x2 = x[:, :, :, n_filter // 2:]
else:
x1, x2 = x
return x1, x2
def precision_recall(num_gbboxes, num_detections, tp, fp, scores,
dtype=tf.float64, scope=None):
"""Compute precision and recall from scores, true positives and false
positives booleans arrays
"""
# Input dictionaries: dict outputs as streaming metrics.
if isinstance(scores, dict):
d_precision = {}
d_recall = {}
for c in num_gbboxes.keys():
scope = 'precision_recall_%s' % c
p, r = precision_recall(num_gbboxes[c], num_detections[c],
tp[c], fp[c], scores[c],
dtype, scope)
d_precision[c] = p
d_recall[c] = r
return d_precision, d_recall
# Sort by score.
with tf.name_scope(scope, 'precision_recall',
[num_gbboxes, num_detections, tp, fp, scores]):
# Sort detections by score.
scores, idxes = tf.nn.top_k(scores, k=num_detections, sorted=True)
tp = tf.gather(tp, idxes)
fp = tf.gather(fp, idxes)
# Computer recall and precision.
tp = tf.cumsum(tf.cast(tp, dtype), axis=0)
fp = tf.cumsum(tf.cast(fp, dtype), axis=0)
recall = _safe_div(tp, tf.cast(num_gbboxes, dtype), 'recall')
precision = _safe_div(tp, tp + fp, 'precision')
return tf.tuple([precision, recall])
def precision_recall_values(xvals, precision, recall, name=None):
"""Compute values on the precision/recall curve.
Args:
x: Python list of floats;
precision: 1D Tensor decreasing.
recall: 1D Tensor increasing.
Return:
list of precision values.
"""
with ops.name_scope(name, "precision_recall_values",
[precision, recall]) as name:
# Add bounds values to precision and recall.
precision = tf.concat([[0.], precision, [0.]], axis=0)
recall = tf.concat([[0.], recall, [1.]], axis=0)
precision = tfe_math.cummax(precision, reverse=True)
prec_values = []
for x in xvals:
mask = tf.less_equal(recall, x)
val = tf.reduce_min(tf.boolean_mask(precision, mask))
prec_values.append(val)
return tf.tuple(prec_values)
# =========================================================================== #
# TF Extended metrics: old stuff!
# =========================================================================== #
def as_tuple_or_list(obj):
"""
Make sure that `obj` is a tuple or a list and eventually converts it into a list with a single element
:param obj:
:return: A `tuple` or a `list`
"""
return obj if isinstance(obj, (list, tuple)) else [obj]
def assign(self, value_list):
if isinstance(value_list, ZMergedMatrix):
value_list = value_list.components
assert len(value_list) == len(self.components), 'the length of value_list and of z, components must coincide'
value_list = tf.tuple(value_list) # THIS PROBABLY SOLVES THE PROBLEM!
ao1 = [tf.assign(c, v) for c, v in zip(self.components, value_list)]
return tf.group(*ao1)
# noinspection PyUnusedLocal
def _array_to_tuple(inputs, size, shape=None):
""" Convert tf.TensorArray to tf.Tuple. """
with tf.variable_scope('array_to_tuple'):
if shape is None:
output = tf.tuple([inputs.read(i) for i in range(size)])
else:
output = tf.tuple([tf.reshape(inputs.read(i), shape) for i in range(size)])
return output
def stop_gradient_tuple(self, inputs):
""" Stop gradients through tf.tuple. """
for i, _ in enumerate(inputs):
inputs[i] = tf.stop_gradient(inputs[i])
return inputs
def create_bbox_batch(cls, inputs, batch_size=64):
""" Create batch indices for bboxes. """
batch = []
for indices in inputs:
indices = tf.random_shuffle(indices)
start = [0] * 2
size = [tf.minimum(batch_size, tf.shape(indices)[0]), -1]
sample = tf.slice(indices, start, size)
sample.set_shape([None, 1])
batch.append(sample)
batch = tf.tuple(batch)
return batch
def _unstack_tuple(self, inputs, tensor_sizes):
size = len(tensor_sizes)
start_position = tf.constant(0)
output = []
dim = len(inputs.get_shape().as_list())-1
for i in range(size):
output.append(tf.slice(inputs, begin=[start_position, *([0]*dim)], size=[tensor_sizes[i], *([-1]*dim)]))
start_position = start_position + tensor_sizes[i]
return tf.tuple(output)
def unflatten_into_tensors(flatparams_P, output_shapes, name=None):
"""
Unflattens a vector produced by flatcat into a list of tensors of the specified shapes.
"""
with tf.op_scope([flatparams_P], name, 'unflatten_into_tensors') as scope:
outputs = []
curr_pos = 0
for shape in output_shapes:
size = np.prod(shape).astype('int')
flatval = flatparams_P[curr_pos:curr_pos + size]
outputs.append(tf.reshape(flatval, shape))
curr_pos += size
assert curr_pos == flatparams_P.get_shape().num_elements(), "{} != {}".format(
curr_pos, flatparams_P.get_shape().num_elements())
return tf.tuple(outputs, name=scope)
def subsample_feed(feed, frac):
assert isinstance(feed, tuple) and len(feed) >= 1
assert isinstance(frac, float) and 0. < frac <= 1.
l = feed[0].shape[0]
assert all(a.shape[0] == l for a in feed), 'All feed entries must have the same length'
subsamp_inds = np.random.choice(l, size=int(frac * l))
return tuple(a[subsamp_inds, ...] for a in feed)
def precision_recall(num_gbboxes, num_detections, tp, fp, scores,
dtype=tf.float64, scope=None):
"""Compute precision and recall from scores, true positives and false
positives booleans arrays
"""
# Input dictionaries: dict outputs as streaming metrics.
if isinstance(scores, dict):
d_precision = {}
d_recall = {}
for c in num_gbboxes.keys():
scope = 'precision_recall_%s' % c
p, r = precision_recall(num_gbboxes[c], num_detections[c],
tp[c], fp[c], scores[c],
dtype, scope)
d_precision[c] = p
d_recall[c] = r
return d_precision, d_recall
# Sort by score.
with tf.name_scope(scope, 'precision_recall',
[num_gbboxes, num_detections, tp, fp, scores]):
# Sort detections by score.
scores, idxes = tf.nn.top_k(scores, k=num_detections, sorted=True)
tp = tf.gather(tp, idxes)
fp = tf.gather(fp, idxes)
# Computer recall and precision.
tp = tf.cumsum(tf.cast(tp, dtype), axis=0)
fp = tf.cumsum(tf.cast(fp, dtype), axis=0)
recall = _safe_div(tp, tf.cast(num_gbboxes, dtype), 'recall')
precision = _safe_div(tp, tp + fp, 'precision')
return tf.tuple([precision, recall])
def precision_recall_values(xvals, precision, recall, name=None):
"""Compute values on the precision/recall curve.
Args:
x: Python list of floats;
precision: 1D Tensor decreasing.
recall: 1D Tensor increasing.
Return:
list of precision values.
"""
with ops.name_scope(name, "precision_recall_values",
[precision, recall]) as name:
# Add bounds values to precision and recall.
precision = tf.concat([[0.], precision, [0.]], axis=0)
recall = tf.concat([[0.], recall, [1.]], axis=0)
precision = tfe_math.cummax(precision, reverse=True)
prec_values = []
for x in xvals:
mask = tf.less_equal(recall, x)
val = tf.reduce_min(tf.boolean_mask(precision, mask))
prec_values.append(val)
return tf.tuple(prec_values)
# =========================================================================== #
# TF Extended metrics: old stuff!
# =========================================================================== #
def dot_product_attention(q,
k,
v,
bias,
dropout_rate=0.0,
image_shapes=None,
name=None,
make_image_summary=True):
"""dot-product attention.
Args:
q: a Tensor with shape [batch, heads, length_q, depth_k]
k: a Tensor with shape [batch, heads, length_kv, depth_k]
v: a Tensor with shape [batch, heads, length_kv, depth_v]
bias: bias Tensor (see attention_bias())
dropout_rate: a floating point number
image_shapes: optional tuple of integer scalars.
see comments for attention_image_summary()
name: an optional string
make_image_summary: True if you want an image summary.
Returns:
A Tensor.
"""
with tf.variable_scope(
name, default_name="dot_product_attention", values=[q, k, v]):
logits = tf.matmul(q, k, transpose_b=True)
if bias is not None:
logits += bias
weights = tf.nn.softmax(logits, name="attention_weights")
weights = tf.nn.dropout(weights, 1.0 - dropout_rate)
return tf.matmul(weights, v)
def _setup_summaries(self):
with tf.name_scope('summaries'):
self.epoch_loss = tf.placeholder(
tf.float32, shape=[], name="epoch_loss")
# Training summaries
tf.summary.scalar('learning rate', self.learning_rate,
collections=[TRAINING_EPOCH_SUMMARIES])
tf.summary.scalar('training (cross entropy) loss', self.epoch_loss,
collections=[TRAINING_EPOCH_SUMMARIES])
if len(self.inputs.get_shape()) == 4:
summary.summary_image(self.inputs, 'inputs', max_images=10, collections=[
TRAINING_BATCH_SUMMARIES])
for key, val in self.training_end_points.iteritems():
summary.summary_activation(val, name=key, collections=[
TRAINING_BATCH_SUMMARIES])
summary.summary_trainable_params(['scalar', 'histogram', 'norm'], collections=[
TRAINING_BATCH_SUMMARIES])
summary.summary_gradients(self.grads_and_vars, [
'scalar', 'histogram', 'norm'], collections=[TRAINING_BATCH_SUMMARIES])
# Validation summaries
for key, val in self.validation_end_points.iteritems():
summary.summary_activation(val, name=key, collections=[
VALIDATION_BATCH_SUMMARIES])
tf.summary.scalar('validation loss', self.epoch_loss,
collections=[VALIDATION_EPOCH_SUMMARIES])
self.validation_metric_placeholders = []
for metric_name, _ in self.validation_metrics_def:
validation_metric = tf.placeholder(
tf.float32, shape=[], name=metric_name.replace(' ', '_'))
self.validation_metric_placeholders.append(validation_metric)
tf.summary.scalar(metric_name, validation_metric,
collections=[VALIDATION_EPOCH_SUMMARIES])
self.validation_metric_placeholders = tuple(
self.validation_metric_placeholders)
def get_state_variables_for_batch(state_variables, batch_size):
"""Returns a subset of the state variables.
This function takes the state variables returned by get_state_variables() and returns a subset
for an actual forward-propagation run. Specifically, it clips each of the state variables to
the given batch size.
Before this call, each variable's first dimension has length
max_batch_size but when the input has a lower batch size, the LSTM should also only update the
state variables for the used batches.
See get_state_variables() for more info.
Args:
state_variables (tuple[tf.contrib.rnn.LSTMStateTuple]): The LSTM's state variables.
batch_size (tf.Tensor): An 0-dimensional tensor containing the batch size tensor in the
computational graph.
Returns:
tuple[tf.contrib.rnn.LSTMStateTuple]: A new tuple of state variables clipped to the given
batch size.
"""
# Return a tuple of LSTMStateTuples but with only the first batch_size rows for each variable
# in the tuples.
result = []
for state_c, state_h in state_variables:
result.append(tf.contrib.rnn.LSTMStateTuple(state_c[:batch_size], state_h[:batch_size]))
return tuple(result)
def get_state_update_op(state_variables, new_states):
"""Returns an operation to update an LSTM's state variables.
See get_state_variables() for more info.
Args:
state_variables (tuple[tf.contrib.rnn.LSTMStateTuple]): The LSTM's state variables.
new_states (tuple[tf.contrib.rnn.LSTMStateTuple]): The new values for the state variables.
new_states may have state tuples with state sizes < max_batch_size. Then, only the first
rows of the corresponding state variables will be updated.
Returns:
tf.Operation: An operation that updates the LSTM's.
"""
# Add an operation to update the train states with the last state tensors.
update_ops = []
for state_variable, new_state in zip(state_variables, new_states):
# new_state[0] might be smaller than state_variable[0], because state_variable[0]
# contains max_batch_size entries.
# Get the update indices for both states in the tuple
update_indices = (tf.range(0, tf.shape(new_state[0])[0]),
tf.range(0, tf.shape(new_state[1])[0]))
update_ops.extend([
tf.scatter_update(state_variable[0], update_indices[0], new_state[0]),
tf.scatter_update(state_variable[1], update_indices[1], new_state[1])
])
return tf.tuple(update_ops)