def dot(a, b): """The dot product of two arrays. See numpy.dot for more details. This relies on `tf.tensordot` which does not support types int64 and float64. So arrays of those types are "unsafely" cast to int32 and float32. Args: a: array_like. Could be an ndarray, a Tensor or any object that can be converted to a Tensor using `tf.convert_to_tensor`. b: array_like. Could be an ndarray, a Tensor or any object that can be converted to a Tensor using `tf.convert_to_tensor`. Returns: An ndarray. """ a, b = array_creation.promote_args_types(a, b) if utils.isscalar(a) or utils.isscalar(b): a = utils.tensor_to_ndarray(tf.expand_dims(a.data, -1)) b = utils.tensor_to_ndarray(tf.expand_dims(b.data, -1)) a_axis = b_axis = -1 else: a_axis = -1 # TODO(agarwal): handle ndim being None when in graph mode. b_axis = -2 if b.ndim > 1 else -1 # TODO(srbs): When the shape of the output is a scalar e.g. when performing # a dot-product of two vectors, numpy returns a scalar object and not an # instance of ndarray. # tensordot/MatMul does not support int64 and float64 so we manually cast to # the compatible types. The conversion may be unsafe. # TODO(srbs): Figure out why MatMul does not support larger types. output_type = None if a.dtype == np.int64: logging.warning("Unsafe cast to int32.") a = utils.tensor_to_ndarray(tf.cast(a.data, tf.int32)) b = utils.tensor_to_ndarray(tf.cast(b.data, tf.int32)) output_type = tf.int64 elif a.dtype == np.float64: logging.warning("Unsafe cast to float32.") a = utils.tensor_to_ndarray(tf.cast(a.data, tf.float32)) b = utils.tensor_to_ndarray(tf.cast(b.data, tf.float32)) output_type = tf.float64 result_t = tf.tensordot(a.data, b.data, [[a_axis], [b_axis]]) if output_type: result_t = tf.cast(result_t, output_type) return utils.tensor_to_ndarray(result_t)
def randn(*args): """Returns samples from a normal distribution. Uses `tf.random_normal`. Args: *args: The shape of the output array. Returns: An ndarray with shape `args` and dtype `float64`. """ # TODO(wangpeng): Use new stateful RNG if utils.isscalar(args): args = (args, ) return utils.tensor_to_ndarray( tf.random.normal(args, dtype=DEFAULT_RANDN_DTYPE))
def argmax(a, axis=None): """Returns the indices of the maximum values along an array axis. Args: a: array_like. Could be an ndarray, a Tensor or any object that can be converted to a Tensor using `tf.convert_to_tensor`. axis: Optional. The axis along which to compute argmax. If None, index of the max element in the flattened array is returned. Returns: An ndarray with the same shape as `a` with `axis` removed if not None. If `axis` is None, a scalar array is returned. """ a = array_creation.asarray(a) if axis is None or utils.isscalar(a): # When axis is None or the array is a scalar, numpy flattens the array. a_t = tf.reshape(a.data, [-1]) else: a_t = a.data return utils.tensor_to_ndarray(tf.argmax(input=a_t, axis=axis))
def full(shape, fill_value, dtype=None): # pylint: disable=redefined-outer-name """Returns an array with given shape and dtype filled with `fill_value`. Args: shape: A valid shape object. Could be a native python object or an object of type ndarray, numpy.ndarray or tf.TensorShape. fill_value: array_like. Could be an ndarray, a Tensor or any object that can be converted to a Tensor using `tf.convert_to_tensor`. dtype: Optional, defaults to dtype of the `fill_value`. The type of the resulting ndarray. Could be a python type, a NumPy type or a TensorFlow `DType`. Returns: An ndarray. Raises: ValueError: if `fill_value` can not be broadcast to shape `shape`. """ fill_value = asarray(fill_value, dtype=dtype) if utils.isscalar(shape): shape = tf.reshape(shape, [1]) return arrays_lib.tensor_to_ndarray(tf.broadcast_to(fill_value.data, shape))