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)
Exemple #2
0
    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:]
Exemple #3
0
    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
Exemple #4
0
    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
Exemple #5
0
    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
Exemple #7
0
    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)
Exemple #9
0
    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]