def get_output_for(self, input, **kwargs):
input_shape = tf.shape(input)
n_batches = input_shape[0]
n_steps = input_shape[1]
input = tf.reshape(input, tf.pack([n_batches, n_steps, -1]))
if 'recurrent_state' in kwargs and self in kwargs['recurrent_state']:
h0s = kwargs['recurrent_state'][self]
else:
h0s = tf.tile(
tf.reshape(self.h0, (1, self.num_units)),
(n_batches, 1)
)
# flatten extra dimensions
shuffled_input = tf.transpose(input, (1, 0, 2))
hs = tf.scan(
self.step,
elems=shuffled_input,
initializer=h0s
)
shuffled_hs = tf.transpose(hs, (1, 0, 2))
if 'recurrent_state_output' in kwargs:
kwargs['recurrent_state_output'][self] = shuffled_hs
return shuffled_hs
python类scan()的实例源码
def get_output_for(self, input, **kwargs):
input_shape = tf.shape(input)
n_batches = input_shape[0]
n_steps = input_shape[1]
input = tf.reshape(input, tf.pack([n_batches, n_steps, -1]))
c0s = tf.tile(
tf.reshape(self.c0, (1, self.num_units)),
(n_batches, 1)
)
h0s = self.nonlinearity(c0s)
# flatten extra dimensions
shuffled_input = tf.transpose(input, (1, 0, 2))
hcs = tf.scan(
self.step,
elems=shuffled_input,
initializer=tf.concat(axis=1, values=[h0s, c0s])
)
shuffled_hcs = tf.transpose(hcs, (1, 0, 2))
shuffled_hs = shuffled_hcs[:, :, :self.num_units]
shuffled_cs = shuffled_hcs[:, :, self.num_units:]
return shuffled_hs
def ctc_label_dense_to_sparse(labels, label_lengths, batch_size):
# The second dimension of labels must be equal to the longest label length in the batch
correct_shape_assert = tf.assert_equal(tf.shape(labels)[1], tf.reduce_max(label_lengths))
with tf.control_dependencies([correct_shape_assert]):
labels = tf.identity(labels)
label_shape = tf.shape(labels)
num_batches_tns = tf.stack([label_shape[0]])
max_num_labels_tns = tf.stack([label_shape[1]])
def range_less_than(previous_state, current_input):
return tf.expand_dims(tf.range(label_shape[1]), 0) < current_input
init = tf.cast(tf.fill(max_num_labels_tns, 0), tf.bool)
init = tf.expand_dims(init, 0)
dense_mask = tf.scan(range_less_than, label_lengths, initializer=init, parallel_iterations=1)
dense_mask = dense_mask[:, 0, :]
label_array = tf.reshape(tf.tile(tf.range(0, label_shape[1]), num_batches_tns),
label_shape)
label_ind = tf.boolean_mask(label_array, dense_mask)
batch_array = tf.transpose(tf.reshape(tf.tile(tf.range(0, label_shape[0]), max_num_labels_tns), tf.reverse(label_shape, [0])))
batch_ind = tf.boolean_mask(batch_array, dense_mask)
indices = tf.transpose(tf.reshape(tf.concat([batch_ind, label_ind], 0), [2, -1]))
shape = [batch_size, tf.reduce_max(label_lengths)]
vals_sparse = gather_nd(labels, indices, shape)
return tf.SparseTensor(tf.to_int64(indices), vals_sparse, tf.to_int64(label_shape))
# Validate and normalize transcriptions. Returns a cleaned version of the label
# or None if it's invalid.
def ctc_label_dense_to_sparse(labels, label_lengths, batch_size):
# The second dimension of labels must be equal to the longest label length in the batch
correct_shape_assert = tf.assert_equal(tf.shape(labels)[1], tf.reduce_max(label_lengths))
with tf.control_dependencies([correct_shape_assert]):
labels = tf.identity(labels)
label_shape = tf.shape(labels)
num_batches_tns = tf.stack([label_shape[0]])
max_num_labels_tns = tf.stack([label_shape[1]])
def range_less_than(previous_state, current_input):
return tf.expand_dims(tf.range(label_shape[1]), 0) < current_input
init = tf.cast(tf.fill(max_num_labels_tns, 0), tf.bool)
init = tf.expand_dims(init, 0)
dense_mask = tf.scan(range_less_than, label_lengths, initializer=init, parallel_iterations=1)
dense_mask = dense_mask[:, 0, :]
label_array = tf.reshape(tf.tile(tf.range(0, label_shape[1]), num_batches_tns),
label_shape)
label_ind = tf.boolean_mask(label_array, dense_mask)
batch_array = tf.transpose(tf.reshape(tf.tile(tf.range(0, label_shape[0]), max_num_labels_tns), tf.reverse(label_shape, [0])))
batch_ind = tf.boolean_mask(batch_array, dense_mask)
indices = tf.transpose(tf.reshape(tf.concat([batch_ind, label_ind], 0), [2, -1]))
shape = [batch_size, tf.reduce_max(label_lengths)]
vals_sparse = gather_nd(labels, indices, shape)
return tf.SparseTensor(tf.to_int64(indices), vals_sparse, tf.to_int64(label_shape))
# Validate and normalize transcriptions. Returns a cleaned version of the label
# or None if it's invalid.
def __init__(self, energy_fn, prior, std=1.0,
inter_op_parallelism_threads=1, intra_op_parallelism_threads=1):
self.energy_fn = energy_fn
self.prior = prior
self.z = self.energy_fn.z
def fn(z, x):
z_ = z + tf.random_normal(tf.shape(self.z), 0.0, std)
accept = metropolis_hastings_accept(
energy_prev=energy_fn(z),
energy_next=energy_fn(z_)
)
return tf.where(accept, z_, z)
self.steps = tf.placeholder(tf.int32, [])
elems = tf.zeros([self.steps])
self.z_ = tf.scan(
fn, elems, self.z, back_prop=False
)
self.sess = tf.Session(
config=tf.ConfigProto(
inter_op_parallelism_threads=inter_op_parallelism_threads,
intra_op_parallelism_threads=intra_op_parallelism_threads
)
)
self.sess.run(tf.global_variables_initializer())
def __call__(self, inputs, steps, nice_steps=1):
def nice_proposal(zv, x):
"""
Nice Proposal (without Metropolis-Hastings).
`z` is the input state.
`v` is created as a dummy variable to allow output of v_, for debugging purposes.
:param zv:
:param x:
:return: next state `z_`, and the corresponding auxiliary variable `v_' (without MH).
"""
z, v = zv
z_, v_ = self.network([z, v], is_backward=(x < 0.5)) #(tf.random_uniform([]) < 0.5))
return z_, v_
def fn(zv, x):
"""
Transition with Metropolis-Hastings.
`z` is the input state.
`v` is created as a dummy variable to allow output of v_, for debugging purposes.
:param zv: [z, v]. It is written in this form merely to appeal to Python 3.
:param x: variable only for specifying the number of steps
:return: next state `z_`, and the corresponding auxiliary variable `v_`.
"""
z, v = zv
v = tf.random_normal(shape=tf.stack([tf.shape(z)[0], self.network.v_dim]))
# z_, v_ = self.network([z, v], is_backward=(tf.random_uniform([]) < 0.5))
z_, v_ = tf.scan(nice_proposal, x * tf.random_uniform([]), (z, v), back_prop=False)
z_, v_ = z_[-1], v_[-1]
ep = hamiltonian(z, v, self.energy_fn)
en = hamiltonian(z_, v_, self.energy_fn)
accept = metropolis_hastings_accept(energy_prev=ep, energy_next=en)
z_ = tf.where(accept, z_, z)
return z_, v_
elems = tf.ones([steps, nice_steps])
return tf.scan(fn, elems, inputs, back_prop=False)
def segment_sample_select(probs, segment_ids):
num_segments = tf.reduce_max(segment_ids) + 1
sampled = tf.random_uniform([num_segments])
def scan_fn(acc, x):
p, i = x[0], x[1]
prev_v = tf.gather(acc[0], i)
new_probs = acc[0] + tf.one_hot(i, num_segments, p)
select = tf.logical_and(tf.less(prev_v, 0.0), tf.greater_equal(prev_v + p, 0.0))
return new_probs, select
_, selection = tf.scan(scan_fn, (probs, segment_ids), initializer=(-sampled, False))
return selection
def get_output_for(self, input, **kwargs):
input_shape = tf.shape(input)
n_batches = input_shape[0]
state = tf.tile(
tf.reshape(self.h0, (1, self.num_units)),
(n_batches, 1)
)
state.set_shape((None, self.num_units))
if self.horizon is not None:
outputs = []
for idx in range(self.horizon):
output, state = self.gru(input[:, idx, :], state, scope=self.scope) # self.name)
outputs.append(tf.expand_dims(output, 1))
outputs = tf.concat(1, outputs)
return outputs
else:
n_steps = input_shape[1]
input = tf.reshape(input, tf.pack([n_batches, n_steps, -1]))
# flatten extra dimensions
shuffled_input = tf.transpose(input, (1, 0, 2))
shuffled_input.set_shape((None, None, self.input_shape[-1]))
hs = tf.scan(
self.step,
elems=shuffled_input,
initializer=state
)
shuffled_hs = tf.transpose(hs, (1, 0, 2))
return shuffled_hs
def get_output_for(self, input, **kwargs):
input_shape = tf.shape(input)
n_batches = input_shape[0]
n_steps = input_shape[1]
input = tf.reshape(input, tf.pack([n_batches, n_steps, -1]))
h0s = tf.tile(
tf.reshape(self.h0, (1, self.num_units)),
(n_batches, 1)
)
c0s = tf.tile(
tf.reshape(self.c0, (1, self.num_units)),
(n_batches, 1)
)
# flatten extra dimensions
shuffled_input = tf.transpose(input, (1, 0, 2))
hcs = tf.scan(
self.step,
elems=shuffled_input,
initializer=tf.concat(1, [h0s, c0s])
)
shuffled_hcs = tf.transpose(hcs, (1, 0, 2))
shuffled_hs = shuffled_hcs[:, :, :self.num_units]
shuffled_cs = shuffled_hcs[:, :, self.num_units:]
if 'recurrent_state_output' in kwargs:
kwargs['recurrent_state_output'][self] = shuffled_hcs
return shuffled_hs
def get_output_for(self, input, **kwargs):
input_shape = tf.shape(input)
n_batches = input_shape[0]
h0s = tf.tile(
tf.reshape(self.h0, (1, self.num_units)),
(n_batches, 1)
)
h0s.set_shape((None, self.num_units))
c0s = tf.tile(
tf.reshape(self.c0, (1, self.num_units)),
(n_batches, 1)
)
c0s.set_shape((None, self.num_units))
state = (c0s, h0s)
if self.horizon is not None:
outputs = []
for idx in range(self.horizon):
output, state = self.lstm(input[:, idx, :], state, scope=self.scope) # self.name)
outputs.append(tf.expand_dims(output, 1))
outputs = tf.concat(1, outputs)
return outputs
else:
n_steps = input_shape[1]
input = tf.reshape(input, tf.pack([n_batches, n_steps, -1]))
# flatten extra dimensions
shuffled_input = tf.transpose(input, (1, 0, 2))
shuffled_input.set_shape((None, None, self.input_shape[-1]))
hcs = tf.scan(
self.step,
elems=shuffled_input,
initializer=tf.concat(1, [h0s, c0s]),
)
shuffled_hcs = tf.transpose(hcs, (1, 0, 2))
shuffled_hs = shuffled_hcs[:, :, :self.num_units]
shuffled_cs = shuffled_hcs[:, :, self.num_units:]
return shuffled_hs
def get_output_for(self, input, **kwargs):
input_shape = tf.shape(input)
n_batches = input_shape[0]
state = tf.tile(
tf.reshape(self.h0, (1, self.num_units)),
(n_batches, 1)
)
state.set_shape((None, self.num_units))
if self.horizon is not None:
outputs = []
for idx in range(self.horizon):
output, state = self.gru(input[:, idx, :], state, scope=self.scope) # self.name)
outputs.append(tf.expand_dims(output, 1))
outputs = tf.concat(axis=1, values=outputs)
return outputs
else:
n_steps = input_shape[1]
input = tf.reshape(input, tf.stack([n_batches, n_steps, -1]))
# flatten extra dimensions
shuffled_input = tf.transpose(input, (1, 0, 2))
shuffled_input.set_shape((None, None, self.input_shape[-1]))
hs = tf.scan(
self.step,
elems=shuffled_input,
initializer=state
)
shuffled_hs = tf.transpose(hs, (1, 0, 2))
return shuffled_hs
def get_output_for(self, input, **kwargs):
input_shape = tf.shape(input)
n_batches = input_shape[0]
n_steps = input_shape[1]
input = tf.reshape(input, tf.stack([n_batches, n_steps, -1]))
h0s = tf.tile(
tf.reshape(self.h0, (1, self.num_units)),
(n_batches, 1)
)
c0s = tf.tile(
tf.reshape(self.c0, (1, self.num_units)),
(n_batches, 1)
)
# flatten extra dimensions
shuffled_input = tf.transpose(input, (1, 0, 2))
hcs = tf.scan(
self.step,
elems=shuffled_input,
initializer=tf.concat(axis=1, values=[h0s, c0s])
)
shuffled_hcs = tf.transpose(hcs, (1, 0, 2))
shuffled_hs = shuffled_hcs[:, :, :self.num_units]
shuffled_cs = shuffled_hcs[:, :, self.num_units:]
if 'recurrent_state_output' in kwargs:
kwargs['recurrent_state_output'][self] = shuffled_hcs
return shuffled_hs
def get_output_for(self, input, **kwargs):
input_shape = tf.shape(input)
n_batches = input_shape[0]
h0s = tf.tile(
tf.reshape(self.h0, (1, self.num_units)),
(n_batches, 1)
)
h0s.set_shape((None, self.num_units))
c0s = tf.tile(
tf.reshape(self.c0, (1, self.num_units)),
(n_batches, 1)
)
c0s.set_shape((None, self.num_units))
state = (c0s, h0s)
if self.horizon is not None:
outputs = []
for idx in range(self.horizon):
output, state = self.lstm(input[:, idx, :], state, scope=self.scope) # self.name)
outputs.append(tf.expand_dims(output, 1))
outputs = tf.concat(axis=1, values=outputs)
return outputs
else:
n_steps = input_shape[1]
input = tf.reshape(input, tf.stack([n_batches, n_steps, -1]))
# flatten extra dimensions
shuffled_input = tf.transpose(input, (1, 0, 2))
shuffled_input.set_shape((None, None, self.input_shape[-1]))
hcs = tf.scan(
self.step,
elems=shuffled_input,
initializer=tf.concat(axis=1, values=[h0s, c0s]),
)
shuffled_hcs = tf.transpose(hcs, (1, 0, 2))
shuffled_hs = shuffled_hcs[:, :, :self.num_units]
shuffled_cs = shuffled_hcs[:, :, self.num_units:]
return shuffled_hs
def cummax(x, reverse=False, name=None):
"""Compute the cumulative maximum of the tensor `x` along `axis`. This
operation is similar to the more classic `cumsum`. Only support 1D Tensor
for now.
Args:
x: A `Tensor`. Must be one of the following types: `float32`, `float64`,
`int64`, `int32`, `uint8`, `uint16`, `int16`, `int8`, `complex64`,
`complex128`, `qint8`, `quint8`, `qint32`, `half`.
axis: A `Tensor` of type `int32` (default: 0).
reverse: A `bool` (default: False).
name: A name for the operation (optional).
Returns:
A `Tensor`. Has the same type as `x`.
"""
with ops.name_scope(name, "Cummax", [x]) as name:
x = ops.convert_to_tensor(x, name="x")
# Not very optimal: should directly integrate reverse into tf.scan.
if reverse:
x = tf.reverse(x, axis=[0])
# 'Accumlating' maximum: ensure it is always increasing.
cmax = tf.scan(lambda a, y: tf.maximum(a, y), x,
initializer=None, parallel_iterations=1,
back_prop=False, swap_memory=False)
if reverse:
cmax = tf.reverse(cmax, axis=[0])
return cmax
def tf_discount_rewards(self, tf_r): # tf_r ~ [game_steps,1]
discount_f = lambda a, v: a * self._gamma + v;
tf_r_reverse = tf.scan(discount_f, tf.reverse(tf_r, [True, False]))
tf_discounted_r = tf.reverse(tf_r_reverse, [True, False])
return tf_discounted_r
def output(self):
"""Iterate through hidden states to get outputs for all"""
input_shape = tf.shape(self._input_B_T_Di)
input = tf.reshape(self._input_B_T_Di, tf.pack([input_shape[0], input_shape[1], -1]))
h0s = tf.tile(tf.reshape(self.h0, (1, self._hidden_units)), (input_shape[0], 1))
# Flatten extra dimension
shuffled_input = tf.transpose(input, (1, 0, 2))
hs = tf.scan(self.step, elems=shuffled_input, initializer=h0s)
shuffled_hs = tf.transpose(hs, (1, 0, 2))
return shuffled_hs
def cummax(x, reverse=False, name=None):
"""Compute the cumulative maximum of the tensor `x` along `axis`. This
operation is similar to the more classic `cumsum`. Only support 1D Tensor
for now.
Args:
x: A `Tensor`. Must be one of the following types: `float32`, `float64`,
`int64`, `int32`, `uint8`, `uint16`, `int16`, `int8`, `complex64`,
`complex128`, `qint8`, `quint8`, `qint32`, `half`.
axis: A `Tensor` of type `int32` (default: 0).
reverse: A `bool` (default: False).
name: A name for the operation (optional).
Returns:
A `Tensor`. Has the same type as `x`.
"""
with ops.name_scope(name, "Cummax", [x]) as name:
x = ops.convert_to_tensor(x, name="x")
# Not very optimal: should directly integrate reverse into tf.scan.
if reverse:
x = tf.reverse(x, axis=[0])
# 'Accumlating' maximum: ensure it is always increasing.
cmax = tf.scan(lambda a, y: tf.maximum(a, y), x,
initializer=None, parallel_iterations=1,
back_prop=False, swap_memory=False)
if reverse:
cmax = tf.reverse(cmax, axis=[0])
return cmax
def compute_detections_greedy(seg_preds, boxes_preds, num_outputs,
seg_threshold=0.2,
sigma=5e-3, step=0.2, num_iters=20,
dist_threshold=20.0):
mask_flat = tf.reshape(seg_preds[:,:,1], [-1])
boxes_flat = tf.reshape(boxes_preds, [-1, 4])
# TODO: also collect (y,x) coordinates
idxs = tf.where(mask_flat > seg_threshold)[:,0]
boxes = tf.gather(boxes_flat, idxs)
boxes, confidence = refine_boxes(boxes, num_iters, step, sigma)
num_boxes = tf.shape(boxes)[0]
dists = tf.nn.relu(nnutil.pairwise_distance(boxes / sigma))
weights = tf.exp(-dists)
def _next_detection(prev, i):
_, _, presence = prev
confidence_curr = tf.reduce_sum(weights * presence, [1], True)
idx = tf.to_int32(tf.argmax(confidence_curr, 0)[0])
mask = tf.to_float(tf.gather(dists, idx) > dist_threshold)[:,tf.newaxis]
presence = presence * mask
confidence = tf.gather(confidence_curr, idx)[0]
return idx, confidence, presence
idxs, confidence, presences = tf.scan(_next_detection,
tf.range(0, num_outputs),
initializer=(0,
0.0,
tf.ones([num_boxes,1])))
return tf.gather(boxes, idxs), confidence
def tf_discounted_cumulative_reward(self, terminal, reward, discount, final_reward=0.0):
"""
Creates the TensorFlow operations for calculating the discounted cumulative rewards
for a given sequence of rewards.
Args:
terminal: Terminal boolean tensor.
reward: Reward tensor.
discount: Discount factor.
final_reward: Last reward value in the sequence.
Returns:
Discounted cumulative reward tensor.
"""
# TODO: n-step cumulative reward (particularly for envs without terminal)
def cumulate(cumulative, reward_and_terminal):
rew, term = reward_and_terminal
return tf.where(
condition=term,
x=rew,
y=(rew + cumulative * discount)
)
# Reverse since reward cumulation is calculated right-to-left, but tf.scan only works left-to-right
reward = tf.reverse(tensor=reward, axis=(0,))
terminal = tf.reverse(tensor=terminal, axis=(0,))
reward = tf.scan(fn=cumulate, elems=(reward, terminal), initializer=final_reward)
return tf.reverse(tensor=reward, axis=(0,))
def get_output_for(self, input, **kwargs):
input_shape = tf.shape(input)
n_batches = input_shape[0]
state = tf.tile(
tf.reshape(self.h0, (1, self.num_units)),
(n_batches, 1)
)
state.set_shape((None, self.num_units))
if self.horizon is not None:
outputs = []
for idx in range(self.horizon):
output, state = self.gru(
input[:, idx, :], state, scope=self.scope) # self.name)
outputs.append(tf.expand_dims(output, 1))
outputs = tf.concat(1, outputs)
return outputs
else:
n_steps = input_shape[1]
input = tf.reshape(input, tf.pack([n_batches, n_steps, -1]))
# flatten extra dimensions
shuffled_input = tf.transpose(input, (1, 0, 2))
shuffled_input.set_shape((None, None, self.input_shape[-1]))
hs = tf.scan(
self.step,
elems=shuffled_input,
initializer=state
)
shuffled_hs = tf.transpose(hs, (1, 0, 2))
return shuffled_hs