Esempio n. 1
0
def convert_color_space(images, from_space, to_space, name=None):
    """Converts one or more images from RGB to Grayscale.
    (A mirror to tf.image rgb_to_grayscale, rgb_to_hsv, grayscale_to_rgb, and hsv_to_rgb)

    Outputs a tensor of the same `DType` and rank as `images`.

    Possible conversions:
        * rgb_to_grayscale: The size of the last dimension of the output is 1,
            containing the Grayscale value of the pixels.
        * grayscale_to_rgb: The size of the last dimension of the output is 3,
            containing the RGB value of the pixels.
        * hsv_to_rgb: The output is only well defined if the value in `images` are in `[0,1]`.
        * rgb_to_hsv: The output is only well defined if the value in `images` are in `[0,1]`.
            `output[..., 0]` contains hue, `output[..., 1]` contains saturation, and
            `output[..., 2]` contains value. All HSV values are in `[0,1]`. A hue of 0
            corresponds to pure red, hue 1/3 is pure green, and 2/3 is pure blue.
        * grayscale_to_hsv: grayscale_to_rgb then rgb_to_hsv
        * hsv_to_grayscale: hsv_to_rgb then rgb_to_grayscale.

    Args:
        images: 4-D Tensor of shape `[batch, height, width, channels]`
        from_space: The color to convert from.
        to_space: The color space to convert to.
        name: A name for the operation (optional).

    Returns:
        The converted image(s).
    """
    color_spaces = ('rgb', 'grayscale', 'hsv')
    if from_space not in color_spaces:
        raise ValueError('`from_space` should be one of the values `{}`, '
                         'received instead `{}`'.format(color_spaces, from_space))
    if to_space not in color_spaces:
        raise ValueError('`to_space` should be one of the values `{}`, '
                         'received instead `{}`'.format(color_spaces, to_space))

    if from_space == 'rgb':
        if to_space == 'grayscale':
            return tf.image.rgb_to_grayscale(images=images, name=name)
        if to_space =='hsv':
            return tf.image.rgb_to_hsv(images=images, name=name)

    if from_space == 'grayscale':
        if to_space == 'rgb':
            return tf.image.grayscale_to_rgb(images=images, name=name)
        if to_space == 'hsv':
            with get_name_scope(name, 'grayscale_to_hsv', [images]):
                _images = tf.image.grayscale_to_rgb(images=images)
                return tf.image.rgb_to_hsv(images=_images)

    if from_space == 'hsv':
        if to_space == 'rgb':
            return tf.image.hsv_to_rgb(images=images, name=name)
        if to_space == 'grayscale':
            with get_name_scope(name, 'hsv_to_grayscale', [images]):
                _images = tf.image.hsv_to_rgb(images=images)
                return tf.image.rgb_to_grayscale(images=_images)
Esempio n. 2
0
def convert_color_space(images, from_space, to_space, name=None):
    """Converts one or more images from RGB to Grayscale.
    (A mirror to tf.image rgb_to_grayscale, rgb_to_hsv, grayscale_to_rgb, and hsv_to_rgb)

    Outputs a tensor of the same `DType` and rank as `images`.

    Possible conversions:
        * rgb_to_grayscale: The size of the last dimension of the output is 1,
            containing the Grayscale value of the pixels.
        * grayscale_to_rgb: The size of the last dimension of the output is 3,
            containing the RGB value of the pixels.
        * hsv_to_rgb: The output is only well defined if the value in `images` are in `[0,1]`.
        * rgb_to_hsv: The output is only well defined if the value in `images` are in `[0,1]`.
            `output[..., 0]` contains hue, `output[..., 1]` contains saturation, and
            `output[..., 2]` contains value. All HSV values are in `[0,1]`. A hue of 0
            corresponds to pure red, hue 1/3 is pure green, and 2/3 is pure blue.
        * grayscale_to_hsv: grayscale_to_rgb then rgb_to_hsv
        * hsv_to_grayscale: hsv_to_rgb then rgb_to_grayscale.

    Args:
        images: 4-D Tensor of shape `[batch, height, width, channels]`
        from_space: The color to convert from.
        to_space: The color space to convert to.
        name: A name for the operation (optional).

    Returns:
        The converted image(s).
    """
    color_spaces = ('rgb', 'grayscale', 'hsv')
    if from_space not in color_spaces:
        raise ValueError('`from_space` should be one of the values `{}`, '
                         'received instead `{}`'.format(color_spaces, from_space))
    if to_space not in color_spaces:
        raise ValueError('`to_space` should be one of the values `{}`, '
                         'received instead `{}`'.format(color_spaces, to_space))

    if from_space == 'rgb':
        if to_space == 'grayscale':
            return tf.image.rgb_to_grayscale(images=images, name=name)
        if to_space =='hsv':
            return tf.image.rgb_to_hsv(images=images, name=name)

    if from_space == 'grayscale':
        if to_space == 'rgb':
            return tf.image.grayscale_to_rgb(images=images, name=name)
        if to_space == 'hsv':
            with get_name_scope(name, 'grayscale_to_hsv', [images]):
                _images = tf.image.grayscale_to_rgb(images=images)
                return tf.image.rgb_to_hsv(images=_images)

    if from_space == 'hsv':
        if to_space == 'rgb':
            return tf.image.hsv_to_rgb(images=images, name=name)
        if to_space == 'grayscale':
            with get_name_scope(name, 'hsv_to_grayscale', [images]):
                _images = tf.image.hsv_to_rgb(images=images)
                return tf.image.rgb_to_grayscale(images=_images)
Esempio n. 3
0
def normal(shape=None, mean=0.0, stddev=0.02, dtype=tf.float32, seed=None, name='Normal'):
    """Normal.

    Initialization with random values from a normal distribution.

    Args:
        shape: List of `int`. A shape to initialize a Tensor (optional).
        mean: Same as `dtype`. The mean of the truncated normal distribution.
        stddev: Same as `dtype`. The standard deviation of the truncated
            normal distribution.
        dtype: The tensor data type.
        seed: `int`. Used to create a random seed for the distribution.
        scope: scope to add the op to.
        name: name of the op.

    Returns:
        The Initializer, or an initialized `Tensor` if shape is specified.

    """
    if shape:
        return tf.random_normal(
            shape, mean=mean, stddev=stddev, seed=seed, dtype=dtype, name=name)
    else:
        with get_name_scope(name):
            return tf.random_normal_initializer(
                mean=mean, stddev=stddev, seed=seed, dtype=dtype)
Esempio n. 4
0
 def inner_regularizer(x):
     with get_name_scope(name, [x]) as _name:
         regularizer_tensors = [
             l1_regularizer(scale_l1)(x),
             l2_regularizer(scale_l2)(x)
         ]
         tf_math_ops.add_n(regularizer_tensors, name=_name)
Esempio n. 5
0
def truncated_normal(shape=None, mean=0.0, stddev=0.02, dtype=tf.float32, seed=None,
                     name='TruncatedNormal'):
    """Truncated Normal.

    Initialization with random values from a normal truncated distribution.

    The generated values follow a normal distribution with specified mean and
    standard deviation, except that values whose magnitude is more than 2 standard
    deviations from the mean are dropped and re-picked.

    Args:
        shape: List of `int`. A shape to initialize a Tensor (optional).
        mean: Same as `dtype`. The mean of the truncated normal distribution.
        stddev: Same as `dtype`. The standard deviation of the truncated
            normal distribution.
        dtype: The tensor data type.
        seed: `int`. Used to create a random seed for the distribution.
        name: name of the op.

    Returns:
        The Initializer, or an initialized `Tensor` if shape is specified.

    """
    if shape:
        return tf.truncated_normal(
            shape=shape, mean=mean, stddev=stddev, seed=seed, dtype=dtype, name=name)
    else:
        with get_name_scope(name):
            return tf.truncated_normal_initializer(
                mean=mean, stddev=stddev, seed=seed, dtype=dtype)
Esempio n. 6
0
def xavier(uniform=True, seed=None, dtype=tf.float32, name='Xavier'):
    """Xavier.

    Returns an initializer performing "Xavier" initialization for weights.

    This initializer is designed to keep the scale of the gradients roughly the
    same in all layers. In uniform distribution this ends up being the range:
    `x = sqrt(6. / (in + out)); [-x, x]` and for normal distribution a standard
    deviation of `sqrt(3. / (in + out))` is used.

    Args:
        uniform: Whether to use uniform or normal distributed random
            initialization.
        seed: A Python integer. Used to create random seeds. See
            `set_random_seed` for behavior.
        dtype: The data type. Only floating point types are supported.
        name: name of the op.

    Returns:
        An initializer for a weight matrix.

    References:
        Understanding the difficulty of training deep feedforward neural
        networks. International conference on artificial intelligence and
        statistics. Xavier Glorot and Yoshua Bengio (2010).

    Links:
        [http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf]
        (http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf)
    """
    with get_name_scope(name):
        return tflayers.xavier_initializer(uniform=uniform, seed=seed, dtype=dtype)
Esempio n. 7
0
def uniform(shape=None, minval=0, maxval=None, dtype=tf.float32, seed=None, name='Uniform'):
    """Uniform.

    Initialization with random values from a uniform distribution.

    The generated values follow a uniform distribution in the range
    `[minval, maxval)`. The lower bound `minval` is included in the range,
    while the upper bound `maxval` is excluded.

    For floats, the default range is `[0, 1)`.  For ints, at least `maxval`
    must be specified explicitly.

    In the integer case, the random integers are slightly biased unless
    `maxval - minval` is an exact power of two.  The bias is small for values of
    `maxval - minval` significantly smaller than the range of the output (either
    `2**32` or `2**64`).

    Args:
        shape: List of `int`. A shape to initialize a Tensor (optional).
        dtype: The tensor data type. Only float are supported.
        seed: `int`. Used to create a random seed for the distribution.
        name: name of the op.

    Returns:
        The Initializer, or an initialized `Tensor` if shape is specified.

    """
    if shape:
        return tf.random_uniform(
            shape=shape, minval=minval, maxval=maxval, seed=seed, dtype=dtype, name=name)
    else:
        with get_name_scope(name):
            return tf.random_uniform_initializer(
                minval=minval, maxval=maxval, seed=seed, dtype=dtype)
Esempio n. 8
0
def variance_scaling(factor=2.0, mode='FAN_IN', uniform=False, seed=None, dtype=tf.float32,
                     name='Xavier'):
    """Variance Scaling.

    Returns an initializer that generates tensors without scaling variance.

    When initializing a deep network, it is in principle advantageous to keep
    the scale of the input variance constant, so it does not explode or diminish
    by reaching the final layer. This initializer use the following formula:

    ```
    if mode='FAN_IN': # Count only number of input connections.
      n = fan_in
    elif mode='FAN_OUT': # Count only number of output connections.
      n = fan_out
    elif mode='FAN_AVG': # Average number of inputs and output connections.
      n = (fan_in + fan_out)/2.0

      truncated_normal(shape, 0.0, stddev=sqrt(factor / n))
    ```

    To get http://arxiv.org/pdf/1502.01852v1.pdf use (Default):
    - factor=2.0 mode='FAN_IN' uniform=False

    To get http://arxiv.org/abs/1408.5093 use:
    - factor=1.0 mode='FAN_IN' uniform=True

    To get http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf use:
    - factor=1.0 mode='FAN_AVG' uniform=True.

    To get xavier_initializer use either:
    - factor=1.0 mode='FAN_AVG' uniform=True.
    - factor=1.0 mode='FAN_AVG' uniform=False.

    Args:
        factor: Float.  A multiplicative factor.
        mode: String.  'FAN_IN', 'FAN_OUT', 'FAN_AVG'.
        uniform: Whether to use uniform or normal distributed random
            initialization.
        seed: A Python integer. Used to create random seeds. See
            `set_random_seed` for behavior.
        dtype: The data type. Only floating point types are supported.
        name: name of the op.

    Returns:
        An initializer that generates tensors with unit variance.

    Raises:
        ValueError: if `dtype` is not a floating point type.
        TypeError: if `mode` is not in ['FAN_IN', 'FAN_OUT', 'FAN_AVG'].
    """
    with get_name_scope(name):
        return tflayers.variance_scaling_initializer(
            factor=factor, mode=mode, uniform=uniform, seed=seed, dtype=dtype)
Esempio n. 9
0
def uniform_scaling(shape=None,
                    factor=1.0,
                    dtype=tf.float32,
                    seed=None,
                    name='UniformScaling'):
    """Uniform Scaling.

    Initialization with random values from uniform distribution without scaling
    variance.

    When initializing a deep network, it is in principle advantageous to keep
    the scale of the input variance constant, so it does not explode or diminish
    by reaching the final layer. If the input is `x` and the operation `x * W`,
    and we want to initialize `W` uniformly at random, we need to pick `W` from

      [-sqrt(3) / sqrt(dim), sqrt(3) / sqrt(dim)]

    to keep the scale intact, where `dim = W.shape[0]` (the size of the input).
    A similar calculation for convolutional networks gives an analogous result
    with `dim` equal to the product of the first 3 dimensions.  When
    nonlinearities are present, we need to multiply this by a constant `factor`.
    See [Sussillo et al., 2014](https://arxiv.org/abs/1412.6558)
    ([pdf](http://arxiv.org/pdf/1412.6558.pdf)) for deeper motivation, experiments
    and the calculation of constants. In section 2.3 there, the constants were
    numerically computed: for a linear layer it's 1.0, relu: ~1.43, tanh: ~1.15.

    Args:
        shape: List of `int`. A shape to initialize a Tensor (optional).
        factor: `float`. A multiplicative factor by which the values will be
            scaled.
        dtype: The tensor data type. Only float are supported.
        seed: `int`. Used to create a random seed for the distribution.
        name: name of the op.

    Returns:
        The Initializer, or an initialized `Tensor` if shape is specified.

    """
    if shape:
        input_size = 1.0
        for dim in shape[:-1]:
            input_size *= float(dim)
        max_val = math.sqrt(3 / input_size) * factor
        return tf.random_ops.random_uniform(shape=shape,
                                            minval=-max_val,
                                            maxval=max_val,
                                            dtype=dtype,
                                            seed=seed,
                                            name=name)
    else:
        with get_name_scope(name):
            return tf.uniform_unit_scaling_initializer(seed=seed, dtype=dtype)
Esempio n. 10
0
    def _prelu(x, name):
        with get_name_scope(name):
            if channel_shared:
                w_shape = (1,)
            else:
                w_shape = get_shape(x)[-1:]

            w_init = getters.get_initializer(weights_init)
            alphas = variable(shape=w_shape, initializer=w_init, restore=restore, name="alphas")

            x = tf.nn.relu(features=x) + tf.multiply(x=alphas, y=(x - tf.abs(x))) * 0.5
            x.alphas = alphas
            return x
Esempio n. 11
0
    def _prelu(x, name):
        with get_name_scope(name):
            if channel_shared:
                w_shape = (1,)
            else:
                w_shape = get_shape(x)[-1:]

            W_init = getters.get_initializer(weights_init)
            alphas = variable(shape=w_shape, initializer=W_init, restore=restore, name="alphas")

            x = tf.nn.relu(features=x) + tf.multiply(x=alphas, y=(x - tf.abs(x))) * 0.5
            x.alphas = alphas
            return x
Esempio n. 12
0
    def _build_loss(self, results, features, labels, loss_config, **kwargs):
        losses, loss = getters.get_loss(loss_config.module, results, features, **loss_config.params)

        with get_name_scope('latent_loss'):
            z_mean = kwargs['z_mean']
            z_log_sigma = kwargs['z_log_sigma']

            latent_losses = -0.5 * tf.reduce_sum(
                1 + z_log_sigma - tf.square(z_mean) - tf.exp(z_log_sigma))
            latent_loss = tf.losses.compute_weighted_loss(latent_losses)

        losses += latent_losses
        loss += latent_loss
        return losses, loss
Esempio n. 13
0
    def loss(y_true, y_pred):
        """
        Args:
            y_pred: `Tensor` of `float` type. Predicted values.
            y_true: `Tensor` of `float` type. Targets (labels).

        Returns:
            `Float`. The calculated loss.
        """
        loss_collection = tf.GraphKeys.LOSSES if collect else None
        with get_name_scope(scope, name, (y_true, y_pred, weights)) as scope_:
            y_true, y_pred = check_loss_data(y_true, y_pred, logits)
            losses = fct(y_true, y_pred)
            weighted_loss = tf.losses.compute_weighted_loss(losses, weights, scope_, loss_collection)
        return losses, weighted_loss
Esempio n. 14
0
    def metric(y_pred, y_true):
        """
        Args:
            y_pred: `Tensor`
            y_true: `Tensor`

        Returns:
            `Float`. The calculated metric.
        """
        check_metric_data(y_pred, y_true)
        with get_name_scope(name, scope):
            x = fct(y_pred, y_true)
            if collect:
                track(x, tf.GraphKeys.METRICS)
            return x
Esempio n. 15
0
    def metric(y_pred, y_true):
        """
        Args:
            y_pred: `Tensor`
            y_true: `Tensor`

        Returns:
            `Float`. The calculated metric.
        """
        check_metric_data(y_pred, y_true)
        with get_name_scope(name, scope):
            x = fct(y_pred, y_true)
            if collect:
                track(x, tf.GraphKeys.METRICS)
            return x
Esempio n. 16
0
    def loss(y_true, y_pred):
        """
        Args:
            y_pred: `Tensor` of `float` type. Predicted values.
            y_true: `Tensor` of `float` type. Targets (labels).

        Returns:
            `Float`. The calculated loss.
        """
        loss_collection = tf.GraphKeys.LOSSES if collect else None
        with get_name_scope(scope, name, (y_true, y_pred, weights)) as scope_:
            y_true, y_pred = check_loss_data(y_true, y_pred, logits)
            losses = fct(y_true, y_pred)
            weighted_loss = tf.losses.compute_weighted_loss(losses, weights, scope_, loss_collection)
        return losses, weighted_loss
Esempio n. 17
0
def zeros(shape=None, dtype=tf.float32, name='zeros'):
    """Zeros.

    Initialize a tensor with all elements set to zero.

    Args:
        shape: List of `int`. A shape to initialize a Tensor (optional).
        dtype: The tensor data type.
        name: name of the op.

    Returns:
        The Initializer, or an initialized `Tensor` if a shape is specified.
    """
    if shape:
        return tf.zeros(shape=shape, dtype=dtype, name=name)
    else:
        with get_name_scope(name):
            return tf.constant_initializer(value=0, dtype=dtype)
Esempio n. 18
0
def uniform_scaling(shape=None, factor=1.0, dtype=tf.float32, seed=None, name='UniformScaling'):
    """Uniform Scaling.

    Initialization with random values from uniform distribution without scaling
    variance.

    When initializing a deep network, it is in principle advantageous to keep
    the scale of the input variance constant, so it does not explode or diminish
    by reaching the final layer. If the input is `x` and the operation `x * W`,
    and we want to initialize `W` uniformly at random, we need to pick `W` from

      [-sqrt(3) / sqrt(dim), sqrt(3) / sqrt(dim)]

    to keep the scale intact, where `dim = W.shape[0]` (the size of the input).
    A similar calculation for convolutional networks gives an analogous result
    with `dim` equal to the product of the first 3 dimensions.  When
    nonlinearities are present, we need to multiply this by a constant `factor`.
    See [Sussillo et al., 2014](https://arxiv.org/abs/1412.6558)
    ([pdf](http://arxiv.org/pdf/1412.6558.pdf)) for deeper motivation, experiments
    and the calculation of constants. In section 2.3 there, the constants were
    numerically computed: for a linear layer it's 1.0, relu: ~1.43, tanh: ~1.15.

    Args:
        shape: List of `int`. A shape to initialize a Tensor (optional).
        factor: `float`. A multiplicative factor by which the values will be
            scaled.
        dtype: The tensor data type. Only float are supported.
        seed: `int`. Used to create a random seed for the distribution.
        name: name of the op.

    Returns:
        The Initializer, or an initialized `Tensor` if shape is specified.

    """
    if shape:
        input_size = 1.0
        for dim in shape[:-1]:
          input_size *= float(dim)
        max_val = math.sqrt(3 / input_size) * factor
        return tf.random_ops.random_uniform(
            shape=shape, minval=-max_val, maxval=max_val, dtype=dtype, seed=seed, name=name)
    else:
        with get_name_scope(name):
            return tf.uniform_unit_scaling_initializer(seed=seed, dtype=dtype)
Esempio n. 19
0
 def _linear(x, name):
     with get_name_scope(name=name):
         return x
Esempio n. 20
0
def exponential_decay(exploration_rate, timestep, decay_steps, decay_rate, staircase=False,
                      name=None):
    """Applies exponential decay to the exploration rate.

    When training a model, it is often recommended to lower the exploration rate as
    the training progresses.  This function applies an exponential decay function
    to a provided initial exploration rate.  It requires a `timestep` value to
    compute the decayed exploration rate.  You can just pass a TensorFlow variable
    that you increment at each training step.
    
    The function returns the decayed exploration rate.  It is computed as:

    ```python
    >>> decayed_exploration_rate = exploration_rate * decay_rate ^ (timestep / decay_steps)
    ```

    If the argument `staircase` is `True`, then `timestep / decay_steps` is an
    integer division and the decayed exploration rate follows a staircase function.

    Example: decay every 100000 steps with a base of 0.96:

    ```python
    >>> timestep = tf.Variable(0, trainable=False)
    >>> starter_exploration_rate = 0.1
    >>> exploration_rate = tf.train.exponential_decay(starter_exploration_rate, timestep,
    ...                                               100000, 0.96, staircase=True)
    >>> # Passing timestep to minimize() will increment it at each step.
    >>> learning_step = (
    ... tf.train.GradientDescentOptimizer(exploration_rate)
    ...   .minimize(...my loss..., timestep=timestep)
    ... )
    ```

    Args:
        exploration_rate: A scalar `float32` or `float64` `Tensor` or a Python number.  
            The initial exploration rate.
        timestep: A scalar `int32` or `int64` `Tensor` or a Python number.
            Global step to use for the decay computation.  Must not be negative.
        decay_steps: A scalar `int32` or `int64` `Tensor` or a Python number.
            Must be positive.  See the decay computation above.
        decay_rate: A Python number.  The decay rate.
        staircase: Boolean.  If `True` decay the exploration rate at discrete intervals.
        name: String.  Optional name of the operation.  Defaults to 'ExplorationExponentialDecay'.

    Returns:
        A scalar `Tensor` of the same type as `exploration_rate`. The decayed exploration rate.

    Raises:
        ValueError: if `timestep` is not supplied.
    """
    if timestep is None:
        raise ValueError("timestep is required for exponential_decay.")
    with get_name_scope(name=name, scope="ExponentialDecay",
                        values=[exploration_rate, timestep, decay_steps, decay_rate]) as name:
        exploration_rate = ops.convert_to_tensor(exploration_rate, name="exploration_rate")
        dtype = exploration_rate.dtype
        timestep = math_ops.cast(timestep, dtype)
        decay_steps = math_ops.cast(decay_steps, dtype)
        decay_rate = math_ops.cast(decay_rate, dtype)
        p = timestep / decay_steps
        if staircase:
            p = math_ops.floor(p)
        return math_ops.multiply(exploration_rate, math_ops.pow(decay_rate, p), name=name)
Esempio n. 21
0
 def inner_regularizer(x):
     with get_name_scope(name, [x]) as _name:
         regularizer_tensors = [l1_regularizer(scale_l1)(x),
                                l2_regularizer(scale_l2)(x)]
         tf_math_ops.add_n(regularizer_tensors, name=_name)
Esempio n. 22
0
def piecewise_constant(x, boundaries, values, name=None):
    """Piecewise constant from boundaries and interval values.

    Example: use a exploration rate that's 1.0 for the first 100000 steps, 0.5 for steps
    100001 to 110000, and 0.1 for any additional steps.

    ```python
    timestep = tf.Variable(0, trainable=False)
    boundaries = [100000, 110000]
    values = [1.0, 0.5, 0.1]
    exploration_rate = tf.train.piecewise_constant(timestep, boundaries, values)

    # Later, whenever we perform an optimization step, we increment timestep.
    ```

    Args:
        x: A 0-D scalar `Tensor`. Must be one of the following types: `float32`,
            `float64`, `uint8`, `int8`, `int16`, `int32`, `int64`.
        boundaries: A list of `Tensor`s or `int`s or `float`s with strictly
            increasing entries, and with all elements having the same type as `x`.
        values: A list of `Tensor`s or float`s or `int`s that specifies the values
            for the intervals defined by `boundaries`. It should have one more element
            than `boundaries`, and all elements should have the same type.
        name: A string. Optional name of the operation. Defaults to 'PiecewiseConstant'.

    Returns:
        A 0-D Tensor. Its value is `values[0]` when `x <= boundaries[0]`,
            `values[1]` when `x > boundaries[0]` and `x <= boundaries[1]`, ...,
            and values[-1] when `x > boundaries[-1]`.

    Raises:
        ValueError: if types of `x` and `buondaries` do not match, or types of all
        `values` do not match.
    """
    with get_name_scope(name=name, scope="PiecewiseConstant",
                        values=[x, boundaries, values, name]) as name:
        x = ops.convert_to_tensor(x)
        # Avoid explicit conversion to x's dtype. This could result in faulty
        # comparisons, for example if floats are converted to integers.
        boundaries = ops.convert_n_to_tensor(boundaries)
        for b in boundaries:
            if b.dtype != x.dtype:
                raise ValueError(
                    "Boundaries (%s) must have the same dtype as x (%s)." % (
                        b.dtype, x.dtype))
        values = ops.convert_n_to_tensor(values)
        for v in values[1:]:
            if v.dtype != values[0].dtype:
                raise ValueError(
                    "Values must have elements all with the same dtype (%s vs %s)." % (
                        values[0].dtype, v.dtype))

        pred_fn_pairs = {}
        pred_fn_pairs[x <= boundaries[0]] = lambda: values[0]
        pred_fn_pairs[x > boundaries[-1]] = lambda: values[-1]
        for low, high, v in zip(boundaries[:-1], boundaries[1:], values[1:-1]):
            # Need to bind v here; can do this with lambda v=v: ...
            pred = (x > low) & (x <= high)
            pred_fn_pairs[pred] = lambda v=v: v

        # The default isn't needed here because our conditions are mutually
        # exclusive and exhaustive, but tf.case requires it.
        default = lambda: values[0]
        return control_flow_ops.case(pred_fn_pairs, default, exclusive=True)
Esempio n. 23
0
 def _leak_relu(x, name):
     with get_name_scope(name):
         x = tf.nn.relu(features=x)
         m_x = tf.nn.relu(features=-x)
         x -= alpha * m_x
         return x
Esempio n. 24
0
def polynomial_decay(exploration_rate,
                     timestep,
                     decay_steps,
                     end_exploration_rate=0.0001,
                     power=1.0,
                     cycle=False,
                     name=None):
    """Applies a polynomial decay to the exploration rate.

    It is commonly observed that a monotonically decreasing exploration rate, whose
    degree of change is carefully chosen, results in a better performing model.
    This function applies a polynomial decay function to a provided initial
    `exploration_rate` to reach an `end_exploration_rate` in the given `decay_steps`.

    It requires a `timestep` value to compute the decayed exploration rate.  You
    can just pass a TensorFlow variable that you increment at each training step.

    The function returns the decayed exploration rate.  It is computed as:

    ```python
    >>> timestep = min(timestep, decay_steps)
    >>> decayed_exploration_rate = (exploration_rate - end_exploration_rate) *
    ...                            (1 - timestep / decay_steps) ^ (power) + end_exploration_rate
    ```

    If `cycle` is True then a multiple of `decay_steps` is used, the first one
    that is bigger than `timesteps`.

    ```python
    >>> decay_steps = decay_steps * ceil(timestep / decay_steps)
    >>> decayed_exploration_rate = (exploration_rate - end_exploration_rate) *
    ...                            (1 - timestep / decay_steps) ^ (power) +
    ...                            end_exploration_rate

    ```

    Example: decay from 0.1 to 0.01 in 10000 steps using sqrt (i.e. power=0.5):

    ```python
    >>> timestep = tf.Variable(0, trainable=False)
    >>> starter_exploration_rate = 0.1
    >>> end_exploration_rate = 0.01
    >>> decay_steps = 10000
    >>> exploration_rate = tf.train.polynomial_decay(starter_exploration_rate, timestep,
    ...                                              decay_steps, end_exploration_rate, power=0.5)
    >>> # Passing timestep to minimize() will increment it at each step.
    >>> learning_step = (
    ...     tf.train.GradientDescentOptimizer(exploration_rate)
    ...     .minimize(...my loss..., timestep=timestep)
    ... )
    ```

    Args:
        exploration_rate: A scalar `float32` or `float64` `Tensor` or a
            Python number.  The initial exploration rate.
        timestep: A scalar `int32` or `int64` `Tensor` or a Python number.
            Global step to use for the decay computation.  Must not be negative.
        decay_steps: A scalar `int32` or `int64` `Tensor` or a Python number.
            Must be positive.  See the decay computation above.
        end_exploration_rate: A scalar `float32` or `float64` `Tensor` or a
            Python number.  The minimal end exploration rate.
        power: A scalar `float32` or `float64` `Tensor` or a
            Python number.  The power of the polynomial. Defaults to linear, 1.0.
        cycle: A boolean, whether or not it should cycle beyond decay_steps.
        name: String.  Optional name of the operation. Defaults to
            'PolynomialDecay'.

    Returns:
        A scalar `Tensor` of the same type as `exploration_rate`.  The decayed exploration rate.

    Raises:
        ValueError: if `timestep` is not supplied.
    """
    if timestep is None:
        raise ValueError("timestep is required for polynomial_decay.")
    with get_name_scope(name=name,
                        scope="PolynomialDecay",
                        values=[
                            exploration_rate, timestep, decay_steps,
                            end_exploration_rate, power
                        ]) as name:
        exploration_rate = ops.convert_to_tensor(exploration_rate,
                                                 name="exploration_rate")
        dtype = exploration_rate.dtype
        timestep = math_ops.cast(timestep, dtype)
        decay_steps = math_ops.cast(decay_steps, dtype)
        end_exploration_rate = math_ops.cast(end_exploration_rate, dtype)
        power = math_ops.cast(power, dtype)
        if cycle:
            # Find the first multiple of decay_steps that is bigger than timestep.
            decay_steps = math_ops.multiply(
                decay_steps, math_ops.ceil(timestep / decay_steps))
        else:
            # Make sure that the timestep used is not bigger than decay_steps.
            timestep = math_ops.minimum(timestep, decay_steps)

        p = math_ops.div(timestep, decay_steps)
        return math_ops.add(math_ops.multiply(
            exploration_rate - end_exploration_rate,
            math_ops.pow(1 - p, power)),
                            end_exploration_rate,
                            name=name)
Esempio n. 25
0
def exponential_decay(exploration_rate,
                      timestep,
                      decay_steps,
                      decay_rate,
                      staircase=False,
                      name=None):
    """Applies exponential decay to the exploration rate.

    When training a model, it is often recommended to lower the exploration rate as
    the training progresses.  This function applies an exponential decay function
    to a provided initial exploration rate.  It requires a `timestep` value to
    compute the decayed exploration rate.  You can just pass a TensorFlow variable
    that you increment at each training step.
    
    The function returns the decayed exploration rate.  It is computed as:

    ```python
    >>> decayed_exploration_rate = exploration_rate * decay_rate ^ (timestep / decay_steps)
    ```

    If the argument `staircase` is `True`, then `timestep / decay_steps` is an
    integer division and the decayed exploration rate follows a staircase function.

    Example: decay every 100000 steps with a base of 0.96:

    ```python
    >>> timestep = tf.Variable(0, trainable=False)
    >>> starter_exploration_rate = 0.1
    >>> exploration_rate = tf.train.exponential_decay(starter_exploration_rate, timestep,
    ...                                               100000, 0.96, staircase=True)
    >>> # Passing timestep to minimize() will increment it at each step.
    >>> learning_step = (
    ... tf.train.GradientDescentOptimizer(exploration_rate)
    ...   .minimize(...my loss..., timestep=timestep)
    ... )
    ```

    Args:
        exploration_rate: A scalar `float32` or `float64` `Tensor` or a Python number.  
            The initial exploration rate.
        timestep: A scalar `int32` or `int64` `Tensor` or a Python number.
            Global step to use for the decay computation.  Must not be negative.
        decay_steps: A scalar `int32` or `int64` `Tensor` or a Python number.
            Must be positive.  See the decay computation above.
        decay_rate: A Python number.  The decay rate.
        staircase: Boolean.  If `True` decay the exploration rate at discrete intervals.
        name: String.  Optional name of the operation.  Defaults to 'ExplorationExponentialDecay'.

    Returns:
        A scalar `Tensor` of the same type as `exploration_rate`. The decayed exploration rate.

    Raises:
        ValueError: if `timestep` is not supplied.
    """
    if timestep is None:
        raise ValueError("timestep is required for exponential_decay.")
    with get_name_scope(
            name=name,
            scope="ExponentialDecay",
            values=[exploration_rate, timestep, decay_steps,
                    decay_rate]) as name:
        exploration_rate = ops.convert_to_tensor(exploration_rate,
                                                 name="exploration_rate")
        dtype = exploration_rate.dtype
        timestep = math_ops.cast(timestep, dtype)
        decay_steps = math_ops.cast(decay_steps, dtype)
        decay_rate = math_ops.cast(decay_rate, dtype)
        p = timestep / decay_steps
        if staircase:
            p = math_ops.floor(p)
        return math_ops.multiply(exploration_rate,
                                 math_ops.pow(decay_rate, p),
                                 name=name)
Esempio n. 26
0
def polynomial_decay(exploration_rate, timestep, decay_steps,
                     end_exploration_rate=0.0001, power=1.0,
                     cycle=False, name=None):
    """Applies a polynomial decay to the exploration rate.

    It is commonly observed that a monotonically decreasing exploration rate, whose
    degree of change is carefully chosen, results in a better performing model.
    This function applies a polynomial decay function to a provided initial
    `exploration_rate` to reach an `end_exploration_rate` in the given `decay_steps`.

    It requires a `timestep` value to compute the decayed exploration rate.  You
    can just pass a TensorFlow variable that you increment at each training step.

    The function returns the decayed exploration rate.  It is computed as:

    ```python
    >>> timestep = min(timestep, decay_steps)
    >>> decayed_exploration_rate = (exploration_rate - end_exploration_rate) *
    ...                            (1 - timestep / decay_steps) ^ (power) + end_exploration_rate
    ```

    If `cycle` is True then a multiple of `decay_steps` is used, the first one
    that is bigger than `timesteps`.

    ```python
    >>> decay_steps = decay_steps * ceil(timestep / decay_steps)
    >>> decayed_exploration_rate = (exploration_rate - end_exploration_rate) *
    ...                            (1 - timestep / decay_steps) ^ (power) +
    ...                            end_exploration_rate

    ```

    Example: decay from 0.1 to 0.01 in 10000 steps using sqrt (i.e. power=0.5):

    ```python
    >>> timestep = tf.Variable(0, trainable=False)
    >>> starter_exploration_rate = 0.1
    >>> end_exploration_rate = 0.01
    >>> decay_steps = 10000
    >>> exploration_rate = tf.train.polynomial_decay(starter_exploration_rate, timestep,
    ...                                              decay_steps, end_exploration_rate, power=0.5)
    >>> # Passing timestep to minimize() will increment it at each step.
    >>> learning_step = (
    ...     tf.train.GradientDescentOptimizer(exploration_rate)
    ...     .minimize(...my loss..., timestep=timestep)
    ... )
    ```

    Args:
        exploration_rate: A scalar `float32` or `float64` `Tensor` or a
            Python number.  The initial exploration rate.
        timestep: A scalar `int32` or `int64` `Tensor` or a Python number.
            Global step to use for the decay computation.  Must not be negative.
        decay_steps: A scalar `int32` or `int64` `Tensor` or a Python number.
            Must be positive.  See the decay computation above.
        end_exploration_rate: A scalar `float32` or `float64` `Tensor` or a
            Python number.  The minimal end exploration rate.
        power: A scalar `float32` or `float64` `Tensor` or a
            Python number.  The power of the polynomial. Defaults to linear, 1.0.
        cycle: A boolean, whether or not it should cycle beyond decay_steps.
        name: String.  Optional name of the operation. Defaults to
            'PolynomialDecay'.

    Returns:
        A scalar `Tensor` of the same type as `exploration_rate`.  The decayed exploration rate.

    Raises:
        ValueError: if `timestep` is not supplied.
    """
    if timestep is None:
        raise ValueError("timestep is required for polynomial_decay.")
    with get_name_scope(name=name, scope="PolynomialDecay",
                        values=[exploration_rate, timestep,
                                decay_steps, end_exploration_rate, power]) as name:
        exploration_rate = ops.convert_to_tensor(exploration_rate, name="exploration_rate")
        dtype = exploration_rate.dtype
        timestep = math_ops.cast(timestep, dtype)
        decay_steps = math_ops.cast(decay_steps, dtype)
        end_exploration_rate = math_ops.cast(end_exploration_rate, dtype)
        power = math_ops.cast(power, dtype)
        if cycle:
            # Find the first multiple of decay_steps that is bigger than timestep.
            decay_steps = math_ops.multiply(decay_steps,
                                            math_ops.ceil(timestep / decay_steps))
        else:
            # Make sure that the timestep used is not bigger than decay_steps.
            timestep = math_ops.minimum(timestep, decay_steps)

        p = math_ops.div(timestep, decay_steps)
        return math_ops.add(math_ops.multiply(exploration_rate - end_exploration_rate,
                                              math_ops.pow(1 - p, power)),
                            end_exploration_rate, name=name)
Esempio n. 27
0
 def hard_sigmoid(x):  # pylint: disable=redefined-outer-name
     with get_name_scope(name=name):
         x = clip_ops.clip_by_value(x, clip_value_min=0., clip_value_max=1.)
         return built_activation(x, collect)
Esempio n. 28
0
 def selu(x):  # pylint: disable=redefined-outer-name
     with get_name_scope(name=name):
         alpha = 1.6732632423543772848170429916717
         scale = 1.0507009873554804934193349852946
         x = scale * tf.nn.elu(x, alpha)
         return built_activation(x, collect)
Esempio n. 29
0
 def _leak_relu(x, name):
     with get_name_scope(name):
         x = tf.nn.relu(features=x)
         m_x = tf.nn.relu(features=-x)
         x -= alpha * m_x
         return x
Esempio n. 30
0
 def _linear(x, name):
     with get_name_scope(name=name):
         return x
Esempio n. 31
0
def natural_exp_decay(exploration_rate,
                      timestep,
                      decay_steps,
                      decay_rate,
                      staircase=False,
                      name=None):
    """Applies natural exponential decay to the initial exploration rate.

    When training a model, it is often recommended to lower the exploration rate as
    the training progresses.  This function applies an exponential decay function
    to a provided initial exploration rate.  It requires an `timestep` value to
    compute the decayed exploration rate.  You can just pass a TensorFlow variable
    that you increment at each training step.

    The function returns the decayed exploration rate.  It is computed as:

    ```python
    >>> decayed_exploration_rate = exploration_rate * exp(-decay_rate * timestep)
    ```

    Example: decay exponentially with a base of 0.96:

    ```python
    >>> timestep = tf.Variable(0, trainable=False)
    >>> exploration_rate = 0.1
    >>> k = 0.5
    >>> exploration_rate = tf.train.exponential_time_decay(exploration_rate, timestep, k)

    >>> # Passing timestep to minimize() will increment it at each step.
    >>> learning_step = (
    ...     tf.train.GradientDescentOptimizer(exploration_rate)
    ...     .minimize(...my loss..., timestep=timestep)
    ... )
    ```

    Args:
        exploration_rate: A scalar `float32` or `float64` `Tensor` or a
            Python number.  The initial exploration rate.
        timestep: A Python number.
            Global step to use for the decay computation.  Must not be negative.
        decay_steps: How often to apply decay.
        decay_rate: A Python number.  The decay rate.
        staircase: Whether to apply decay in a discrete staircase,
            as opposed to continuous, fashion.
        name: String.  Optional name of the operation.  Defaults to 'ExponentialTimeDecay'.

    Returns:
        A scalar `Tensor` of the same type as `exploration_rate`.  The decayed exploration rate.

    Raises:
        ValueError: if `timestep` is not supplied.
    """
    if timestep is None:
        raise ValueError("timestep is required for natural_exp_decay.")
    with get_name_scope(name=name,
                        scope="NaturalExpDecay",
                        values=[exploration_rate, timestep,
                                decay_rate]) as name:
        exploration_rate = ops.convert_to_tensor(exploration_rate,
                                                 name="exploration_rate")
        dtype = exploration_rate.dtype
        timestep = math_ops.cast(timestep, dtype)
        decay_steps = math_ops.cast(decay_steps, dtype)
        decay_rate = math_ops.cast(decay_rate, dtype)
        p = timestep / decay_steps
        if staircase:
            p = math_ops.floor(p)
        exponent = math_ops.exp(
            math_ops.multiply(math_ops.negative(decay_rate), p))
        return math_ops.multiply(exploration_rate, exponent, name=name)
Esempio n. 32
0
def piecewise_constant(x, boundaries, values, name=None):
    """Piecewise constant from boundaries and interval values.

    Example: use a exploration rate that's 1.0 for the first 100000 steps, 0.5 for steps
    100001 to 110000, and 0.1 for any additional steps.

    ```python
    timestep = tf.Variable(0, trainable=False)
    boundaries = [100000, 110000]
    values = [1.0, 0.5, 0.1]
    exploration_rate = tf.train.piecewise_constant(timestep, boundaries, values)

    # Later, whenever we perform an optimization step, we increment timestep.
    ```

    Args:
        x: A 0-D scalar `Tensor`. Must be one of the following types: `float32`,
            `float64`, `uint8`, `int8`, `int16`, `int32`, `int64`.
        boundaries: A list of `Tensor`s or `int`s or `float`s with strictly
            increasing entries, and with all elements having the same type as `x`.
        values: A list of `Tensor`s or float`s or `int`s that specifies the values
            for the intervals defined by `boundaries`. It should have one more element
            than `boundaries`, and all elements should have the same type.
        name: A string. Optional name of the operation. Defaults to 'PiecewiseConstant'.

    Returns:
        A 0-D Tensor. Its value is `values[0]` when `x <= boundaries[0]`,
            `values[1]` when `x > boundaries[0]` and `x <= boundaries[1]`, ...,
            and values[-1] when `x > boundaries[-1]`.

    Raises:
        ValueError: if types of `x` and `buondaries` do not match, or types of all
        `values` do not match.
    """
    with get_name_scope(name=name,
                        scope="PiecewiseConstant",
                        values=[x, boundaries, values, name]) as name:
        x = ops.convert_to_tensor(x)
        # Avoid explicit conversion to x's dtype. This could result in faulty
        # comparisons, for example if floats are converted to integers.
        boundaries = ops.convert_n_to_tensor(boundaries)
        for b in boundaries:
            if b.dtype != x.dtype:
                raise ValueError(
                    "Boundaries (%s) must have the same dtype as x (%s)." %
                    (b.dtype, x.dtype))
        values = ops.convert_n_to_tensor(values)
        for v in values[1:]:
            if v.dtype != values[0].dtype:
                raise ValueError(
                    "Values must have elements all with the same dtype (%s vs %s)."
                    % (values[0].dtype, v.dtype))

        pred_fn_pairs = {}
        pred_fn_pairs[x <= boundaries[0]] = lambda: values[0]
        pred_fn_pairs[x > boundaries[-1]] = lambda: values[-1]
        for low, high, v in zip(boundaries[:-1], boundaries[1:], values[1:-1]):
            # Need to bind v here; can do this with lambda v=v: ...
            pred = (x > low) & (x <= high)
            pred_fn_pairs[pred] = lambda v=v: v

        # The default isn't needed here because our conditions are mutually
        # exclusive and exhaustive, but tf.case requires it.
        default = lambda: values[0]
        return control_flow_ops.case(pred_fn_pairs, default, exclusive=True)
Esempio n. 33
0
def natural_exp_decay(exploration_rate, timestep, decay_steps, decay_rate,
                      staircase=False, name=None):
    """Applies natural exponential decay to the initial exploration rate.

    When training a model, it is often recommended to lower the exploration rate as
    the training progresses.  This function applies an exponential decay function
    to a provided initial exploration rate.  It requires an `timestep` value to
    compute the decayed exploration rate.  You can just pass a TensorFlow variable
    that you increment at each training step.

    The function returns the decayed exploration rate.  It is computed as:

    ```python
    >>> decayed_exploration_rate = exploration_rate * exp(-decay_rate * timestep)
    ```

    Example: decay exponentially with a base of 0.96:

    ```python
    >>> timestep = tf.Variable(0, trainable=False)
    >>> exploration_rate = 0.1
    >>> k = 0.5
    >>> exploration_rate = tf.train.exponential_time_decay(exploration_rate, timestep, k)

    >>> # Passing timestep to minimize() will increment it at each step.
    >>> learning_step = (
    ...     tf.train.GradientDescentOptimizer(exploration_rate)
    ...     .minimize(...my loss..., timestep=timestep)
    ... )
    ```

    Args:
        exploration_rate: A scalar `float32` or `float64` `Tensor` or a
            Python number.  The initial exploration rate.
        timestep: A Python number.
            Global step to use for the decay computation.  Must not be negative.
        decay_steps: How often to apply decay.
        decay_rate: A Python number.  The decay rate.
        staircase: Whether to apply decay in a discrete staircase,
            as opposed to continuous, fashion.
        name: String.  Optional name of the operation.  Defaults to 'ExponentialTimeDecay'.

    Returns:
        A scalar `Tensor` of the same type as `exploration_rate`.  The decayed exploration rate.

    Raises:
        ValueError: if `timestep` is not supplied.
    """
    if timestep is None:
        raise ValueError("timestep is required for natural_exp_decay.")
    with get_name_scope(name=name, scope="NaturalExpDecay",
                        values=[exploration_rate, timestep, decay_rate]) as name:
        exploration_rate = ops.convert_to_tensor(exploration_rate, name="exploration_rate")
        dtype = exploration_rate.dtype
        timestep = math_ops.cast(timestep, dtype)
        decay_steps = math_ops.cast(decay_steps, dtype)
        decay_rate = math_ops.cast(decay_rate, dtype)
        p = timestep / decay_steps
        if staircase:
            p = math_ops.floor(p)
        exponent = math_ops.exp(math_ops.multiply(math_ops.negative(decay_rate), p))
        return math_ops.multiply(exploration_rate, exponent, name=name)