def test_is_deterministic_shape(self): deterministic_shape = [ (), (1,), (1, 2), [], [1], [1, 2], [np.asarray([1], dtype=np.int)[0]], tf.placeholder(tf.float32, shape=(1, 2)).get_shape(), ] for v in deterministic_shape: self.assertTrue( is_deterministic_shape(v), msg='%r should be a deterministic shape.' % (v,) ) non_deterministic_shape = [ tf.placeholder(tf.int32, shape=(3,)), tf.placeholder(tf.int32, shape=(None,)), [tf.placeholder(tf.int32, shape=()), 1], tf.placeholder(tf.float32, shape=(1, None)).get_shape(), tf.get_variable('shape', shape=(1,), dtype=tf.int32), tf.placeholder(tf.int32), [tf.placeholder(tf.int32), 1, tf.placeholder(tf.int32, ())], ] for v in non_deterministic_shape: self.assertFalse( is_deterministic_shape(v), msg='%r should not be a deterministic shape.' % (v,) ) not_shape_type = [ object(), {}, '', True, 1, 1.0, [True], [[1, 2]], [1.0], tf.placeholder(tf.float32, shape=(1,)), tf.placeholder(tf.int32, shape=()), tf.placeholder(tf.int32, shape=(1, 2)), [tf.placeholder(tf.int32, shape=(1,))], [tf.placeholder(tf.float32, shape=())], tf.placeholder(tf.float32), [tf.placeholder(tf.float32), 1, tf.placeholder(tf.float32, ())], ] for v in not_shape_type: with self.assertRaises(TypeError, msg='%r is not a shape.' % (v,)): is_deterministic_shape(v)
def __init__(self, logits=None, probs=None, dtype=None, group_event_ndims=None, check_numerics=False, name=None, default_name=None): if dtype is None: dtype = tf.int32 else: dtype = tf.as_dtype(dtype) super(OneHotCategorical, self).__init__(logits=logits, probs=probs, group_event_ndims=group_event_ndims, check_numerics=check_numerics, name=name, default_name=default_name) self._dtype = dtype with reopen_variable_scope(self.variable_scope): with tf.name_scope('init'): # derive the value shape of parameters logits_shape = self.logits.get_shape() self._static_value_shape = logits_shape[-1:] if is_deterministic_shape(self._static_value_shape): self._dynamic_value_shape = tf.constant( self._static_value_shape.as_list(), dtype=tf.int32) else: self._dynamic_value_shape = tf.shape(logits)[-1:]
def _sample_n_sparse(self, n, dtype=None): # flatten the logits for feeding into `tf.multinomial`. if self.logits.get_shape().ndims == 2: logits_2d = self.logits else: logits_2d = tf.reshape(self.logits, tf.stack([-1, tf.shape(self.logits)[-1]])) logits_2d.set_shape( tf.TensorShape([None ]).concatenate(self.logits.get_shape()[-1:])) # derive the samples samples = tf.multinomial(logits_2d, n) if dtype is not None: samples = tf.cast(samples, dtype=dtype) # reshape back into the requested shape samples = tf.transpose(samples) if is_deterministic_shape([n]): static_shape = tf.TensorShape([n]) else: static_shape = tf.TensorShape([None]) static_shape = static_shape.concatenate(self.logits.get_shape()[:-1]) dynamic_shape = tf.concat([[n], tf.shape(self.logits)[:-1]], axis=0) samples = tf.reshape(samples, dynamic_shape) samples.set_shape(static_shape) return samples
def _sample_n(self, n): # compute the shape of samples if is_deterministic_shape([n]): static_shape = tf.TensorShape([n]) else: static_shape = tf.TensorShape([None]) static_shape = static_shape.concatenate(self.static_batch_shape) dynamic_shape = tf.concat([[n], self.dynamic_batch_shape], axis=0) # derive the samples samples = self.mean + self.stddev * (tf.random_normal( dynamic_shape, dtype=self.dtype)) samples.set_shape(static_shape) return samples
def _sample_n(self, n): # compute the shape of samples if is_deterministic_shape([n]): static_shape = tf.TensorShape([n]) else: static_shape = tf.TensorShape([None]) static_shape = static_shape.concatenate(self.static_batch_shape) dynamic_shape = tf.concat([[n], self.dynamic_batch_shape], axis=0) # derive the samples uniform_samples = tf.random_uniform(dynamic_shape, minval=0., maxval=1., dtype=self.param_dtype) samples = tf.cast(tf.less(uniform_samples, self.probs), dtype=self.dtype) samples.set_shape(static_shape) return samples
def _sample_n(self, n): ndims = self.p.get_shape().ndims if ndims is not None: rep = tf.stack([n] + [1] * ndims) else: rep = tf.concat( [[n], tf.ones(tf.stack([tf.rank(self.p)]), dtype=tf.int32)], axis=0) ret = tf.tile(tf.expand_dims(self.p, axis=0), rep) if is_deterministic_shape([n]): static_shape = tf.TensorShape([n]) else: static_shape = tf.TensorShape([None]) ret.set_shape( static_shape.concatenate( self.static_batch_shape.concatenate(self.static_value_shape))) return ret
def __init__(self, logits=None, probs=None, dtype=None, group_event_ndims=None, check_numerics=False, name=None, default_name=None): # check the arguments if (logits is None and probs is None) or \ (logits is not None and probs is not None): raise ValueError('One and only one of `logits`, `probs` should ' 'be specified.') if logits is not None: param_dtype = get_preferred_tensor_dtype(logits) else: param_dtype = get_preferred_tensor_dtype(probs) if not param_dtype.is_floating: raise TypeError('Bernoulli distribution parameters must be float ' 'numbers.') if dtype is None: dtype = tf.int32 else: dtype = tf.as_dtype(dtype) super(Bernoulli, self).__init__( group_event_ndims=group_event_ndims, check_numerics=check_numerics, name=name, default_name=default_name, ) with reopen_variable_scope(self.variable_scope): with tf.name_scope('init'): # obtain parameter tensors if logits is not None: logits = tf.convert_to_tensor(logits, dtype=param_dtype, name='logits') probs = tf.nn.sigmoid(logits, 'probs') probs_clipped = probs probs_is_derived = True else: probs = tf.convert_to_tensor(probs, dtype=param_dtype, name='probs') probs_eps = (1e-11 if probs.dtype == tf.float64 else 1e-7) probs_clipped = tf.clip_by_value(probs, probs_eps, 1 - probs_eps) logits = self._check_numerics( tf.subtract(tf.log(probs_clipped), tf.log1p(-probs_clipped), name='logits'), 'logits') probs_is_derived = False # derive the shape and data types of parameters logits_shape = logits.get_shape() self._logits = logits self._static_batch_shape = logits_shape if is_deterministic_shape(logits_shape): self._dynamic_batch_shape = tf.constant( logits_shape.as_list(), dtype=tf.int32) else: self._dynamic_batch_shape = tf.shape(logits) # derive various distribution attributes self._probs = probs self._probs_clipped = probs_clipped self._probs_is_derived = probs_is_derived # set other attributes self._dtype = dtype
def sample(self, shape=(), group_event_ndims=None, name=None): """Get random samples from the distribution. Parameters ---------- shape : tuple[int | tf.Tensor] | tf.Tensor The shape of the samples, as a tuple of integers / 0-d tensors, or a 1-d tensor. group_event_ndims : int | tf.Tensor If specify, override the default `group_event_ndims`. name : str Optional name of this operation. Returns ------- tfsnippet.bayes.StochasticTensor The random samples as `StochasticTensor`. """ from ..stochastic import StochasticTensor with tf.name_scope(name, default_name='sample'): # derive the samples using ``n = prod(shape)`` if is_deterministic_shape(shape): samples = self._sample_n(np.prod(shape, dtype=np.int32)) static_sample_shape = tf.TensorShape(shape) else: if isinstance(shape, (tuple, list)): static_sample_shape = tf.TensorShape( list( map( lambda v: None if is_dynamic_tensor_like(v) else v, shape))) shape = tf.stack(shape, axis=0) else: static_sample_shape = tf.TensorShape(None) samples = self._sample_n(tf.reduce_prod(shape)) # reshape the samples tail_static_shape = samples.get_shape()[1:] tail_dynamic_shape = tf.shape(samples)[1:] with tf.name_scope('reshape'): dynamic_shape = tf.concat([shape, tail_dynamic_shape], axis=0) samples = tf.reshape(samples, dynamic_shape) # special fix: when `sample_shape` is a tensor, it would cause # `static_sample_shape` to carry no information. We thus # re-capture the sample shape by query at the reshaped samples. if tail_static_shape.ndims is not None and \ samples.get_shape().ndims is not None and \ static_sample_shape.ndims is None: tail_ndims = tail_static_shape.ndims if tail_ndims == 0: static_sample_shape = samples.get_shape() else: static_sample_shape = samples.get_shape()[:-tail_ndims] # fix the static shape of samples samples.set_shape( static_sample_shape.concatenate(tail_static_shape)) # determine the dimensions of samples if static_sample_shape.ndims is None: tail_ndims = tail_static_shape.ndims if tail_ndims is None: tail_ndims = tf.size(tail_dynamic_shape) total_ndims = samples.get_shape().ndims if total_ndims is None: total_ndims = tf.size(dynamic_shape) samples_ndims = total_ndims - tail_ndims else: samples_ndims = static_sample_shape.ndims if samples_ndims == 0: samples_ndims = None # construct the stochastic tensor object if group_event_ndims is None: group_event_ndims = self.group_event_ndims return StochasticTensor(self, samples=samples, samples_ndims=samples_ndims, group_event_ndims=group_event_ndims)
def __init__(self, logits=None, probs=None, group_event_ndims=None, check_numerics=False, name=None, default_name=None): # check the arguments if (logits is None and probs is None) or \ (logits is not None and probs is not None): raise ValueError('One and only one of `logits`, `probs` should ' 'be specified.') if logits is not None: param_dtype = get_preferred_tensor_dtype(logits) else: param_dtype = get_preferred_tensor_dtype(probs) if not param_dtype.is_floating: raise TypeError( 'Categorical distribution parameters must be float ' 'numbers.') super(_BaseCategorical, self).__init__(group_event_ndims=group_event_ndims, check_numerics=check_numerics, name=name, default_name=default_name) with reopen_variable_scope(self.variable_scope): with tf.name_scope('init'): # obtain parameter tensors if logits is not None: logits = tf.convert_to_tensor(logits, dtype=param_dtype) probs = tf.nn.softmax(logits, name='probs_given_logits') probs_clipped = probs probs_is_derived = True else: probs = tf.convert_to_tensor(probs, dtype=param_dtype) probs_eps = (1e-11 if probs.dtype == tf.float64 else 1e-7) probs_clipped = tf.clip_by_value(probs, probs_eps, 1 - probs_eps) logits = self._check_numerics( tf.log(probs, name='logits_given_probs'), 'logits') probs_is_derived = False self._logits = logits self._probs = probs self._probs_is_derived = probs_is_derived self._probs_clipped = probs_clipped # derive the shape and data types of parameters logits_shape = logits.get_shape() self._static_batch_shape = logits_shape[:-1] if is_deterministic_shape(self._static_batch_shape): self._dynamic_batch_shape = tf.constant( self._static_batch_shape.as_list(), dtype=tf.int32) else: self._dynamic_batch_shape = tf.shape(logits)[:-1] # infer the number of categories self._n_categories = logits_shape[-1].value if self._n_categories is None: self._n_categories = tf.shape(logits)[-1]