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
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)
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
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))
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)
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)
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)
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)
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))
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))
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)