Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion edward/inferences/bigan_inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def __init__(self, latent_vars, data, discriminator):
# call grandparent's method; avoid parent (GANInference)
super(GANInference, self).__init__(latent_vars, data)

def build_loss_and_gradients(self, var_list):
def _build_loss_and_gradients(self, var_list):
x_true = list(six.itervalues(self.data))[0]
x_fake = list(six.iterkeys(self.data))[0]

Expand Down
41 changes: 23 additions & 18 deletions edward/inferences/gan_inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,14 @@ def __init__(self, data, discriminator):
if not callable(discriminator):
raise TypeError("discriminator must be a callable function.")

self.discriminator = discriminator
self._discriminator = discriminator
super(GANInference, self).__init__(None, data)

@property
def discriminator(self):
"""Discriminator used to discriminate samples from the model."""
return self._discriminator

def initialize(self, optimizer=None, optimizer_d=None,
global_step=None, global_step_d=None, var_list=None,
*args, **kwargs):
Expand Down Expand Up @@ -92,25 +97,25 @@ def initialize(self, optimizer=None, optimizer_d=None,
# call grandparent's method; avoid parent (VariationalInference)
super(VariationalInference, self).initialize(*args, **kwargs)

self.loss, grads_and_vars, self.loss_d, grads_and_vars_d = \
self.build_loss_and_gradients(var_list)
self._loss, grads_and_vars, self._loss_d, grads_and_vars_d = \
self._build_loss_and_gradients(var_list)

optimizer, global_step = _build_optimizer(optimizer, global_step)
optimizer_d, global_step_d = _build_optimizer(optimizer_d, global_step_d)

self.train = optimizer.apply_gradients(grads_and_vars,
self._train = optimizer.apply_gradients(grads_and_vars,
global_step=global_step)
self.train_d = optimizer_d.apply_gradients(grads_and_vars_d,
self._train_d = optimizer_d.apply_gradients(grads_and_vars_d,
global_step=global_step_d)

if self.logging:
if self._logging:
tf.summary.scalar("loss", self.loss,
collections=[self._summary_key])
tf.summary.scalar("loss/discriminative", self.loss_d,
collections=[self._summary_key])
self.summarize = tf.summary.merge_all(key=self._summary_key)
self._summarize = tf.summary.merge_all(key=self._summary_key)

def build_loss_and_gradients(self, var_list):
def _build_loss_and_gradients(self, var_list):
x_true = list(six.itervalues(self.data))[0]
x_fake = list(six.iterkeys(self.data))[0]
with tf.variable_scope("Disc"):
Expand All @@ -119,7 +124,7 @@ def build_loss_and_gradients(self, var_list):
with tf.variable_scope("Disc", reuse=True):
d_fake = self.discriminator(x_fake)

if self.logging:
if self._logging:
tf.summary.histogram("discriminator_outputs",
tf.concat([d_true, d_fake], axis=0),
collections=[self._summary_key])
Expand Down Expand Up @@ -176,26 +181,26 @@ def update(self, feed_dict=None, variables=None):
sess = get_session()
if variables is None:
_, _, t, loss, loss_d = sess.run(
[self.train, self.train_d, self.increment_t, self.loss, self.loss_d],
[self._train, self._train_d, self._increment_t, self._loss, self._loss_d],
feed_dict)
elif variables == "Gen":
_, t, loss = sess.run(
[self.train, self.increment_t, self.loss], feed_dict)
[self._train, self._increment_t, self._loss], feed_dict)
loss_d = 0.0
elif variables == "Disc":
_, t, loss_d = sess.run(
[self.train_d, self.increment_t, self.loss_d], feed_dict)
[self._train_d, self._increment_t, self._loss_d], feed_dict)
loss = 0.0
else:
raise NotImplementedError("variables must be None, 'Gen', or 'Disc'.")

if self.debug:
sess.run(self.op_check, feed_dict)
if self._debug:
sess.run(self._op_check, feed_dict)

if self.logging and self.n_print != 0:
if self._logging and self.n_print != 0:
if t == 1 or t % self.n_print == 0:
summary = sess.run(self.summarize, feed_dict)
self.train_writer.add_summary(summary, t)
summary = sess.run(self._summarize, feed_dict)
self._train_writer.add_summary(summary, t)

return {'t': t, 'loss': loss, 'loss_d': loss_d}

Expand All @@ -205,7 +210,7 @@ def print_progress(self, info_dict):
if self.n_print != 0:
t = info_dict['t']
if t == 1 or t % self.n_print == 0:
self.progbar.update(t, {'Gen Loss': info_dict['loss'],
self._progbar.update(t, {'Gen Loss': info_dict['loss'],
'Disc Loss': info_dict['loss_d']})


Expand Down
57 changes: 30 additions & 27 deletions edward/inferences/gibbs.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,15 @@ def __init__(self, latent_vars, proposal_vars=None, data=None):
else:
check_latent_vars(proposal_vars)

self.proposal_vars = proposal_vars
self._proposal_vars = proposal_vars
super(Gibbs, self).__init__(latent_vars, data)

@property
def proposal_vars(self):
"""Proposal variable dictionary binding model latent variables to
their proposal distribution."""
return self._proposal_vars

def initialize(self, scan_order='random', *args, **kwargs):
"""Initialize inference algorithm. It initializes hyperparameters
and builds ops for the algorithm's computation graph.
Expand All @@ -62,8 +68,8 @@ def initialize(self, scan_order='random', *args, **kwargs):
`RandomVariable`s (this defines a blocked Gibbs sampler). If
'random', will use a random order at each update.
"""
self.scan_order = scan_order
self.feed_dict = {}
self._scan_order = scan_order
self._feed_dict = {}
kwargs['auto_transform'] = False
return super(Gibbs, self).initialize(*args, **kwargs)

Expand All @@ -81,73 +87,70 @@ def update(self, feed_dict=None):
acceptance rate of samples since (and including) this iteration.
"""
sess = get_session()
if not self.feed_dict:
if not self._feed_dict:
# Initialize feed for all conditionals to be the draws at step 0.
samples = OrderedDict(self.latent_vars)
inits = sess.run([qz.params[0] for qz in six.itervalues(samples)])
for z, init in zip(six.iterkeys(samples), inits):
self.feed_dict[z] = init
self._feed_dict[z] = init

for key, value in six.iteritems(self.data):
if isinstance(key, tf.Tensor) and "Placeholder" in key.op.type:
self.feed_dict[key] = value
self._feed_dict[key] = value
elif isinstance(key, RandomVariable) and \
isinstance(value, (tf.Tensor, tf.Variable)):
self.feed_dict[key] = sess.run(value)
self._feed_dict[key] = sess.run(value)

if feed_dict is None:
feed_dict = {}

feed_dict.update(self.feed_dict)
feed_dict.update(self._feed_dict)

# Determine scan order.
if self.scan_order == 'random':
if self._scan_order == 'random':
scan_order = list(six.iterkeys(self.latent_vars))
random.shuffle(scan_order)
else: # list
scan_order = self.scan_order
scan_order = self._scan_order

# Fetch samples by iterating over complete conditional draws.
for z in scan_order:
if isinstance(z, RandomVariable):
draw = sess.run(self.proposal_vars[z], feed_dict)
feed_dict[z] = draw
self.feed_dict[z] = draw
self._feed_dict[z] = draw
else: # list
draws = sess.run([self.proposal_vars[zz] for zz in z], feed_dict)
for zz, draw in zip(z, draws):
feed_dict[zz] = draw
self.feed_dict[zz] = draw
self._feed_dict[zz] = draw

# Assign the samples to the Empirical random variables.
_, accept_rate = sess.run([self.train, self.n_accept_over_t], feed_dict)
t = sess.run(self.increment_t)
_, accept_rate = sess.run([self._train, self._n_accept_over_t], feed_dict)
t = sess.run(self._increment_t)

if self.debug:
sess.run(self.op_check, feed_dict)
if self._debug:
sess.run(self._op_check, feed_dict)

if self.logging and self.n_print != 0:
if self._logging and self.n_print != 0:
if t == 1 or t % self.n_print == 0:
summary = sess.run(self.summarize, feed_dict)
self.train_writer.add_summary(summary, t)
summary = sess.run(self._summarize, feed_dict)
self._train_writer.add_summary(summary, t)

return {'t': t, 'accept_rate': accept_rate}

def build_update(self):
"""
#### Notes

The updates assume each Empirical random variable is directly
parameterized by `tf.Variable`s.
def _build_update(self):
"""Note the updates assume each Empirical random variable is
directly parameterized by `tf.Variable`s.
"""
# Update Empirical random variables according to the complete
# conditionals. We will feed the conditionals when calling `update()`.
assign_ops = []
for z, qz in six.iteritems(self.latent_vars):
variable = qz.get_variables()[0]
assign_ops.append(
tf.scatter_update(variable, self.t, self.proposal_vars[z]))
tf.scatter_update(variable, self._t, self.proposal_vars[z]))

# Increment n_accept (if accepted).
assign_ops.append(self.n_accept.assign_add(1))
assign_ops.append(self._n_accept.assign_add(1))
return tf.group(*assign_ops)
30 changes: 14 additions & 16 deletions edward/inferences/hmc.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ class HMC(MonteCarlo):
"""Hamiltonian Monte Carlo, also known as hybrid Monte Carlo
[@duane1987hybrid; @neal2011mcmc].

The algorithm simulates Hamiltonian dynamics using a numerical
integrator. It corrects for the integrator's discretization error
using an acceptance ratio.

#### Notes

In conditional inference, we infer $z$ in $p(z, \\beta
Expand Down Expand Up @@ -57,23 +61,17 @@ def initialize(self, step_size=0.25, n_steps=2, *args, **kwargs):
n_steps: int, optional.
Number of steps of numerical integrator.
"""
self.step_size = step_size
self.n_steps = n_steps
self._step_size = step_size
self._n_steps = n_steps
# store global scope for log joint calculations
self._scope = tf.get_default_graph().unique_name("inference") + '/'
return super(HMC, self).initialize(*args, **kwargs)

def build_update(self):
"""Simulate Hamiltonian dynamics using a numerical integrator.
Correct for the integrator's discretization error using an
acceptance ratio.

#### Notes

The updates assume each Empirical random variable is directly
parameterized by `tf.Variable`s.
def _build_update(self):
"""Note the updates assume each Empirical random variable is
directly parameterized by `tf.Variable`s.
"""
old_sample = {z: tf.gather(qz.params, tf.maximum(self.t - 1, 0))
old_sample = {z: tf.gather(qz.params, tf.maximum(self._t - 1, 0))
for z, qz in six.iteritems(self.latent_vars)}
old_sample = OrderedDict(old_sample)

Expand All @@ -87,8 +85,8 @@ def build_update(self):

# Simulate Hamiltonian dynamics.
new_sample, new_r_sample = leapfrog(old_sample, old_r_sample,
self.step_size, self._log_joint,
self.n_steps)
self._step_size, self._log_joint,
self._n_steps)

# Calculate acceptance ratio.
ratio = tf.reduce_sum([0.5 * tf.reduce_sum(tf.square(r))
Expand Down Expand Up @@ -121,10 +119,10 @@ def build_update(self):
# If z is an automatically unconstrained distribution,
# transform samples back to original (constrained) space.
qz_sample = z.bijector.inverse(qz_sample)
assign_ops.append(tf.scatter_update(variable, self.t, qz_sample))
assign_ops.append(tf.scatter_update(variable, self._t, qz_sample))

# Increment n_accept (if accepted).
assign_ops.append(self.n_accept.assign_add(tf.where(accept, 1, 0)))
assign_ops.append(self._n_accept.assign_add(tf.where(accept, 1, 0)))
return tf.group(*assign_ops)

def _log_joint(self, z_sample):
Expand Down
Loading