Beispiel #1
0
def average(a, axis=None, weights=None, returned=False):  # pylint: disable=missing-docstring
    if axis is not None and not isinstance(axis, six.integer_types):
        # TODO(wangpeng): Support tuple of ints as `axis`
        raise ValueError('`axis` must be an integer. Tuple of ints is not '
                         'supported yet. Got type: %s' % type(axis))
    a = array_ops.array(a)
    if weights is None:  # Treat all weights as 1
        if not np.issubdtype(a.dtype, np.inexact):
            a = a.astype(
                utils.result_type(a.dtype, dtypes.default_float_type()))
        avg = tf.reduce_mean(a.data, axis=axis)
        if returned:
            if axis is None:
                weights_sum = tf.size(a.data)
            else:
                weights_sum = tf.shape(a.data)[axis]
            weights_sum = tf.cast(weights_sum, a.data.dtype)
    else:
        if np.issubdtype(a.dtype, np.inexact):
            out_dtype = utils.result_type(a.dtype, weights)
        else:
            out_dtype = utils.result_type(a.dtype, weights,
                                          dtypes.default_float_type())
        a = array_ops.array(a, out_dtype).data
        weights = array_ops.array(weights, out_dtype).data

        def rank_equal_case():
            tf.debugging.Assert(
                tf.reduce_all(tf.shape(a) == tf.shape(weights)),
                [tf.shape(a), tf.shape(weights)])
            weights_sum = tf.reduce_sum(weights, axis=axis)
            avg = tf.reduce_sum(a * weights, axis=axis) / weights_sum
            return avg, weights_sum

        if axis is None:
            avg, weights_sum = rank_equal_case()
        else:

            def rank_not_equal_case():
                tf.debugging.Assert(tf.rank(weights) == 1, [tf.rank(weights)])
                weights_sum = tf.reduce_sum(weights)
                axes = tf.convert_to_tensor([[axis], [0]])
                avg = tf.tensordot(a, weights, axes) / weights_sum
                return avg, weights_sum

            # We condition on rank rather than shape equality, because if we do the
            # latter, when the shapes are partially unknown but the ranks are known
            # and different, utils.cond will run shape checking on the true branch,
            # which will raise a shape-checking error.
            avg, weights_sum = utils.cond(
                tf.rank(a) == tf.rank(weights), rank_equal_case,
                rank_not_equal_case)

    avg = array_ops.array(avg)
    if returned:
        weights_sum = array_ops.broadcast_to(weights_sum, tf.shape(avg.data))
        return avg, weights_sum
    return avg
Beispiel #2
0
 def f(x1, x2):
     if x1.dtype == tf.bool:
         assert x2.dtype == tf.bool
         float_ = dtypes.default_float_type()
         x1 = tf.cast(x1, float_)
         x2 = tf.cast(x2, float_)
     return tf.math.truediv(x1, x2)
Beispiel #3
0
def heaviside(x1, x2):
  def f(x1, x2):
    return tf.where(x1 < 0, tf.constant(0, dtype=x2.dtype),
                    tf.where(x1 > 0, tf.constant(1, dtype=x2.dtype), x2))
  y = _bin_op(f, x1, x2)
  if not np.issubdtype(y.dtype, np.inexact):
    y = y.astype(dtypes.default_float_type())
  return y
Beispiel #4
0
def _reduce(tf_fn, a, axis=None, dtype=None, keepdims=None,
            promote_int=_TO_INT64, tf_bool_fn=None, preserve_bool=False):
  """A general reduction function.

  Args:
    tf_fn: the TF reduction function.
    a: the array to be reduced.
    axis: (optional) the axis along which to do the reduction. If None, all
      dimensions are reduced.
    dtype: (optional) the dtype of the result.
    keepdims: (optional) whether to keep the reduced dimension(s).
    promote_int: how to promote integer and bool inputs. There are three
      choices: (1) _TO_INT64: always promote them to int64 or uint64; (2)
      _TO_FLOAT: always promote them to a float type (determined by
      dtypes.default_float_type); (3) None: don't promote.
    tf_bool_fn: (optional) the TF reduction function for bool inputs. It
      will only be used if `dtype` is explicitly set to `np.bool_` or if `a`'s
      dtype is `np.bool_` and `preserve_bool` is True.
    preserve_bool: a flag to control whether to use `tf_bool_fn` if `a`'s dtype
      is `np.bool_` (some reductions such as np.sum convert bools to
      integers, while others such as np.max preserve bools.

  Returns:
    An ndarray.
  """
  if dtype:
    dtype = utils.result_type(dtype)
  if keepdims is None:
    keepdims = False
  a = array_creation.asarray(a, dtype=dtype)
  if ((dtype == np.bool_ or preserve_bool and a.dtype == np.bool_)
      and tf_bool_fn is not None):
    return utils.tensor_to_ndarray(
        tf_bool_fn(input_tensor=a.data, axis=axis, keepdims=keepdims))
  if dtype is None:
    dtype = a.dtype
    if np.issubdtype(dtype, np.integer) or dtype == np.bool_:
      if promote_int == _TO_INT64:
        # If a is an integer/bool type and whose bit width is less than 64,
        # numpy up-casts it to 64-bit.
        if dtype == np.bool_:
          is_signed = True
          width = 8  # We can use any number here that is less than 64
        else:
          is_signed = np.issubdtype(dtype, np.signedinteger)
          width = np.iinfo(dtype).bits
        if width < 64:
          if is_signed:
            dtype = np.int64
          else:
            dtype = np.uint64
          a = a.astype(dtype)
      elif promote_int == _TO_FLOAT:
        a = a.astype(dtypes.default_float_type())

  return utils.tensor_to_ndarray(
      tf_fn(input_tensor=a.data, axis=axis, keepdims=keepdims))
Beispiel #5
0
def convert_to_tensor(value, dtype=None):
  # A safer version of `tf.convert_to_tensor` to work around b/149876037.
  # TODO(wangpeng): Remove this function once the bug is fixed.
  if (dtype is None and isinstance(value, six.integer_types)
      and value >= 2 ** 63):
    dtype = tf.uint64
  elif (dtype is None and isinstance(value, float)):
    dtype = dtypes.default_float_type()
  return tf.convert_to_tensor(value, dtype=dtype)
Beispiel #6
0
 def f(x1, x2):
     if x1.dtype == tf.bool:
         assert x2.dtype == tf.bool
         float_ = dtypes.default_float_type()
         x1 = tf.cast(x1, float_)
         x2 = tf.cast(x2, float_)
     if not dtypes.is_allow_float64():
         # tf.math.truediv in Python3 produces float64 when both inputs are int32
         # or int64. We want to avoid that when is_allow_float64() is False.
         x1, x2 = _avoid_float64(x1, x2)
     return tf.math.truediv(x1, x2)
Beispiel #7
0
def around(a, decimals=0):  # pylint: disable=missing-docstring
    a = asarray(a)
    dtype = a.dtype
    factor = math.pow(10, decimals)
    # Use float as the working dtype instead of a.dtype, because a.dtype can be
    # integer and `decimals` can be negative.
    float_dtype = dtypes.default_float_type()
    a = a.astype(float_dtype).data
    factor = tf.cast(factor, float_dtype)
    a = tf.multiply(a, factor)
    a = tf.round(a)
    a = tf.math.divide(a, factor)
    return utils.tensor_to_ndarray(a).astype(dtype)
Beispiel #8
0
def around(a, decimals=0):  # pylint: disable=missing-docstring
  a = asarray(a)
  dtype = a.dtype
  factor = math.pow(10, decimals)
  if np.issubdtype(dtype, np.inexact):
    factor = tf.cast(factor, dtype)
  else:
    # Use float as the working dtype when a.dtype is exact (e.g. integer),
    # because `decimals` can be negative.
    float_dtype = dtypes.default_float_type()
    a = a.astype(float_dtype).data
    factor = tf.cast(factor, float_dtype)
  a = tf.multiply(a, factor)
  a = tf.round(a)
  a = tf.math.divide(a, factor)
  return utils.tensor_to_ndarray(a).astype(dtype)
Beispiel #9
0
def _scalar(x, tf_fn):
    """Computes the tf_fn(x) for each element in `x`.

  Args:
    x: array_like. Could be an ndarray, a Tensor or any object that can
      be converted to a Tensor using `tf.convert_to_tensor`.
    tf_fn: function that takes a single Tensor argument.

  Returns:
    An ndarray with the same shape as `x`. The default output dtype is
    determined by `dtypes.default_float_type`, unless x is an ndarray with a
    floating point type, in which case the output type is same as x.dtype.
  """
    x = array_creation.asarray(x)
    if x.dtype not in (np.float16, np.float32, np.float64):
        x = x.astype(dtypes.default_float_type())
    return utils.tensor_to_ndarray(tf_fn(x.data))
Beispiel #10
0
def _scalar(tf_fn, x, promote_to_float=False):
    """Computes the tf_fn(x) for each element in `x`.

  Args:
    tf_fn: function that takes a single Tensor argument.
    x: array_like. Could be an ndarray, a Tensor or any object that can
      be converted to a Tensor using `tf.convert_to_tensor`.
    promote_to_float: whether to cast the argument to a float dtype
      (`dtypes.default_float_type`) if it is not already.

  Returns:
    An ndarray with the same shape as `x`. The default output dtype is
    determined by `dtypes.default_float_type`, unless x is an ndarray with a
    floating point type, in which case the output type is same as x.dtype.
  """
    x = array_creation.asarray(x)
    if promote_to_float and not np.issubdtype(x.dtype, np.floating):
        x = x.astype(dtypes.default_float_type())
    return utils.tensor_to_ndarray(tf_fn(x.data))
Beispiel #11
0
def tri(N, M=None, k=0, dtype=None):  # pylint: disable=invalid-name,missing-docstring
  M = M if M is not None else N
  if dtype is not None:
    dtype = utils.result_type(dtype)
  else:
    dtype = dtypes.default_float_type()

  if k < 0:
    lower = -k - 1
    if lower > N:
      r = tf.zeros([N, M], dtype)
    else:
      # Keep as tf bool, since we create an upper triangular matrix and invert
      # it.
      o = tf.ones([N, M], dtype=tf.bool)
      r = tf.cast(tf.math.logical_not(tf.linalg.band_part(o, lower, -1)), dtype)
  else:
    o = tf.ones([N, M], dtype)
    if k > M:
      r = o
    else:
      r = tf.linalg.band_part(o, -1, k)
  return utils.tensor_to_ndarray(r)