| # Copyright 2018 The TensorFlow Authors. All Rights Reserved. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # ============================================================================== |
| """Functional tests for unary coefficient-wise operations.""" |
| |
| from __future__ import absolute_import |
| from __future__ import division |
| from __future__ import print_function |
| |
| import math |
| |
| import numpy as np |
| |
| from tensorflow.python.eager import backprop |
| from tensorflow.python.framework import constant_op |
| from tensorflow.python.framework import dtypes as dtypes_lib |
| from tensorflow.python.framework import ops |
| from tensorflow.python.framework import sparse_tensor |
| from tensorflow.python.framework import test_util |
| from tensorflow.python.ops import gen_math_ops |
| from tensorflow.python.ops import gradient_checker |
| from tensorflow.python.ops import gradient_checker_v2 |
| from tensorflow.python.ops import math_ops |
| from tensorflow.python.ops import nn_grad # pylint: disable=unused-import |
| from tensorflow.python.ops import special_math_ops |
| from tensorflow.python.platform import test |
| from tensorflow.python.platform import tf_logging |
| |
| _NEG = lambda x: -x |
| _ABS = abs |
| |
| |
| # TODO(zongheng): it'd be great to factor out this function and various random |
| # SparseTensor gen funcs. |
| def _sparsify(x, thresh=0.5, index_dtype=np.int64): |
| x[x < thresh] = 0 |
| |
| non_zero = np.where(x) |
| x_indices = np.vstack(non_zero).astype(index_dtype).T |
| x_values = x[non_zero] |
| x_shape = x.shape |
| |
| return sparse_tensor.SparseTensor( |
| indices=x_indices, values=x_values, dense_shape=x_shape), x_values |
| |
| |
| def _default_tolerance(dtype): |
| """Returns a sensible default tolerance for comparing results of a given type. |
| |
| Args: |
| dtype: A datatype. |
| """ |
| if dtype == dtypes_lib.bfloat16.as_numpy_dtype: |
| return 5e-3 |
| if dtype == np.float16: |
| return 5e-3 |
| elif dtype in (np.float32, np.complex64): |
| return 1e-3 |
| elif dtype in (np.float64, np.complex128): |
| return 1e-5 |
| else: |
| return None # Fail fast for unexpected types |
| |
| |
| class UnaryOpTest(test.TestCase): |
| |
| def _compareCpu(self, x, np_func, tf_func, grad_rtol=None, grad_atol=None): |
| if grad_rtol is None: |
| grad_rtol = _default_tolerance(x.dtype) |
| if grad_atol is None: |
| grad_atol = _default_tolerance(x.dtype) |
| np_ans = np_func(x) |
| with self.cached_session(use_gpu=False): |
| inx = ops.convert_to_tensor(x) |
| y = tf_func(inx) |
| tf_cpu = self.evaluate(y) |
| self.assertShapeEqual(np_ans, y) |
| if x.dtype == np.float16: |
| self.assertAllClose(np_ans, tf_cpu, rtol=1e-3, atol=1e-3) |
| elif x.dtype == dtypes_lib.bfloat16.as_numpy_dtype: |
| self.assertAllClose(np_ans, tf_cpu, rtol=1e-2, atol=1e-2) |
| else: |
| self.assertAllClose(np_ans, tf_cpu) |
| |
| if x.dtype in (np.complex64, np.complex128) and tf_func == math_ops.sign: |
| return # Return early |
| |
| if x.dtype in (np.float16, dtypes_lib.bfloat16.as_numpy_dtype): |
| s = list(np.shape(x)) |
| jacob_t, _ = gradient_checker.compute_gradient( |
| inx, s, y, s, x_init_value=x) |
| xf = x.astype(np.float) |
| inxf = ops.convert_to_tensor(xf) |
| yf = tf_func(inxf) |
| _, jacob_n = gradient_checker.compute_gradient( |
| inxf, s, yf, s, x_init_value=xf, delta=1e-2) |
| jacob_n = jacob_n.astype(x.dtype) |
| self.assertAllClose(jacob_t, jacob_n, rtol=grad_rtol, atol=grad_atol) |
| elif x.dtype in (np.float32, np.complex64): |
| s = list(np.shape(x)) |
| jacob_t, jacob_n = gradient_checker.compute_gradient( |
| inx, s, y, s, x_init_value=x, delta=1e-3) |
| self.assertAllClose(jacob_t, jacob_n, rtol=grad_rtol, atol=grad_atol) |
| elif x.dtype in (np.float64, np.complex128): |
| s = list(np.shape(x)) |
| jacob_t, jacob_n = gradient_checker.compute_gradient( |
| inx, s, y, s, x_init_value=x, delta=1e-5) |
| self.assertAllClose(jacob_t, jacob_n, rtol=grad_rtol, atol=grad_atol) |
| |
| def _check(self, result_tensor, result_np, input_sp_t, tol): |
| self.assertTrue(isinstance(result_tensor, sparse_tensor.SparseTensor)) |
| self.assertTrue(isinstance(input_sp_t, sparse_tensor.SparseTensor)) |
| self.assertAllEqual(input_sp_t.indices, result_tensor.indices) |
| self.assertAllEqual(input_sp_t.dense_shape, result_tensor.dense_shape) |
| if tol is None: |
| self.assertAllClose(result_np, result_tensor.values) |
| else: |
| self.assertAllClose(result_np, result_tensor.values, rtol=tol, atol=tol) |
| |
| def _compareSparseCpu(self, x, np_func, tf_func, tol): |
| x_sp, x_sp_vals = _sparsify(x) |
| res_np = np_func(x_sp_vals) |
| with test_util.force_cpu(): |
| self._check(tf_func(x_sp), res_np, x_sp, tol) |
| |
| def _compareGpu(self, x, np_func, tf_func): |
| np_ans = np_func(x) |
| with test_util.use_gpu(): |
| result = tf_func(ops.convert_to_tensor(x)) |
| tf_gpu = self.evaluate(result) |
| if x.dtype == np.float16: |
| self.assertAllClose(np_ans, tf_gpu, rtol=1e-3, atol=1e-3) |
| else: |
| self.assertAllClose(np_ans, tf_gpu) |
| # TODO(zhifengc/ke): make gradient checker work on GPU. |
| |
| def _compareSparseGpu(self, x, np_func, tf_func, tol): |
| x_sp, x_sp_vals = _sparsify(x) |
| res_np = np_func(x_sp_vals) |
| with test_util.use_gpu(): |
| self._check(tf_func(x_sp), res_np, x_sp, tol) |
| |
| def _compareBoth(self, x, np_func, tf_func): |
| self._compareCpu(x, np_func, tf_func) |
| self._compareGpu(x, np_func, tf_func) |
| |
| def _compareBothSparse(self, x, np_func, tf_func, tol=None): |
| self._compareSparseCpu(x, np_func, tf_func, tol) |
| self._compareSparseGpu(x, np_func, tf_func, tol) |
| |
| def _inv(self, x): |
| return 1.0 / x |
| |
| def _rsqrt(self, x): |
| return self._inv(np.sqrt(x)) |
| |
| def _sigmoid(self, x): |
| return 1.0 / (1.0 + np.exp(-x)) |
| |
| def _log_sigmoid(self, x): |
| return np.log(self._sigmoid(x)) |
| |
| def _replace_domain_error_with_inf(self, fn): |
| |
| def func(x): |
| try: |
| return fn(x) |
| except ValueError as e: |
| if "domain error" in str(e): |
| return np.inf * np.ones_like(x) |
| else: |
| raise e |
| |
| return func |
| |
| @test_util.run_deprecated_v1 |
| def testFloatBasic(self): |
| x = np.arange(-3, 3).reshape(1, 3, 2).astype(np.float32) |
| w = x - x.min() + 1.02 # all greater than 1 |
| y = (x + .5).astype(np.float32) # no zero |
| z = (x + 15.5).astype(np.float32) # all positive |
| k = np.arange(-0.90, 0.90, 0.25).astype(np.float32) # between -1 and 1 |
| |
| self._compareBoth(x, np.abs, math_ops.abs) |
| self._compareBoth(x, np.abs, _ABS) |
| self._compareBoth(x, np.negative, math_ops.negative) |
| self._compareBoth(x, np.negative, _NEG) |
| self._compareBoth(y, self._inv, math_ops.reciprocal) |
| self._compareBoth(x, np.square, math_ops.square) |
| self._compareBoth(z, np.sqrt, math_ops.sqrt) |
| self._compareBoth(z, self._rsqrt, math_ops.rsqrt) |
| self._compareBoth(x, np.exp, math_ops.exp) |
| self._compareBoth(x, np.expm1, math_ops.expm1) |
| self._compareBoth(z, np.log, math_ops.log) |
| self._compareBoth(z, np.log1p, math_ops.log1p) |
| self._compareBoth(x, np.sinh, math_ops.sinh) |
| self._compareBoth(x, np.cosh, math_ops.cosh) |
| self._compareBoth(x, np.tanh, math_ops.tanh) |
| self._compareBoth(x, np.arcsinh, math_ops.asinh) |
| self._compareBoth(w, np.arccosh, math_ops.acosh) |
| self._compareBoth(k, np.arctanh, math_ops.atanh) |
| self._compareBoth(x, self._sigmoid, math_ops.sigmoid) |
| self._compareBoth(x, self._log_sigmoid, math_ops.log_sigmoid) |
| self._compareBoth(y, np.sign, math_ops.sign) |
| self._compareBoth(x, np.sin, math_ops.sin) |
| self._compareBoth(x, np.cos, math_ops.cos) |
| self._compareBoth(k, np.arcsin, math_ops.asin) |
| self._compareBoth(k, np.arccos, math_ops.acos) |
| self._compareBoth(x, np.arctan, math_ops.atan) |
| self._compareBoth(x, np.tan, math_ops.tan) |
| self._compareBoth( |
| y, np.vectorize(self._replace_domain_error_with_inf(math.lgamma)), |
| math_ops.lgamma) |
| self._compareBoth(x, np.vectorize(math.erf), math_ops.erf) |
| self._compareBoth(x, np.vectorize(math.erfc), math_ops.erfc) |
| try: |
| from scipy import special # pylint: disable=g-import-not-at-top |
| self._compareBoth(x, special.i0e, special_math_ops.bessel_i0e) |
| self._compareBoth(x, special.i1e, special_math_ops.bessel_i1e) |
| except ImportError as e: |
| tf_logging.warn("Cannot test special functions: %s" % str(e)) |
| |
| self._compareBothSparse(x, np.abs, math_ops.abs) |
| self._compareBothSparse(x, np.negative, math_ops.negative) |
| self._compareBothSparse(x, np.square, math_ops.square) |
| self._compareBothSparse(z, np.sqrt, math_ops.sqrt, tol=1e-3) |
| self._compareBothSparse(x, np.tanh, math_ops.tanh) |
| self._compareBothSparse(y, np.sign, math_ops.sign) |
| self._compareBothSparse(x, np.vectorize(math.erf), math_ops.erf) |
| |
| @test_util.run_deprecated_v1 |
| def testFloatTanhEdge(self): |
| x = np.arange(40, 40 + 6).reshape(6).astype(np.float32) |
| self._compareBoth(x, np.tanh, math_ops.tanh) |
| x = np.arange(-40, -40 + 6).reshape(6).astype(np.float32) |
| self._compareBoth(x, np.tanh, math_ops.tanh) |
| |
| @test_util.run_deprecated_v1 |
| def testFloatEmpty(self): |
| x = np.empty((2, 0, 5), dtype=np.float32) |
| self._compareBoth(x, np.abs, math_ops.abs) |
| self._compareBoth(x, np.abs, _ABS) |
| self._compareBoth(x, np.negative, math_ops.negative) |
| self._compareBoth(x, np.negative, _NEG) |
| self._compareBoth(x, self._inv, math_ops.reciprocal) |
| self._compareBoth(x, np.square, math_ops.square) |
| self._compareBoth(x, np.sqrt, math_ops.sqrt) |
| self._compareBoth(x, self._rsqrt, math_ops.rsqrt) |
| self._compareBoth(x, np.exp, math_ops.exp) |
| self._compareBoth(x, np.expm1, math_ops.expm1) |
| self._compareBoth(x, np.log, math_ops.log) |
| self._compareBoth(x, np.log1p, math_ops.log1p) |
| self._compareBoth(x, np.sinh, math_ops.sinh) |
| self._compareBoth(x, np.arcsinh, math_ops.asinh) |
| self._compareBoth(x, np.cosh, math_ops.cosh) |
| self._compareBoth(x, np.tanh, math_ops.tanh) |
| self._compareBoth(x, self._sigmoid, math_ops.sigmoid) |
| self._compareBoth(x, np.sign, math_ops.sign) |
| self._compareBoth(x, np.sin, math_ops.sin) |
| self._compareBoth(x, np.cos, math_ops.cos) |
| # Can't use vectorize below, so just use some arbitrary function |
| self._compareBoth(x, np.sign, math_ops.lgamma) |
| self._compareBoth(x, np.sign, math_ops.erf) |
| self._compareBoth(x, np.sign, math_ops.erfc) |
| self._compareBoth(x, np.tan, math_ops.tan) |
| self._compareBoth(x, np.arcsin, math_ops.asin) |
| self._compareBoth(x, np.arccos, math_ops.acos) |
| self._compareBoth(x, np.arctan, math_ops.atan) |
| try: |
| from scipy import special # pylint: disable=g-import-not-at-top |
| self._compareBoth(x, special.i0e, special_math_ops.bessel_i0e) |
| self._compareBoth(x, special.i1e, special_math_ops.bessel_i1e) |
| except ImportError as e: |
| tf_logging.warn("Cannot test special functions: %s" % str(e)) |
| |
| self._compareBothSparse(x, np.abs, math_ops.abs) |
| self._compareBothSparse(x, np.negative, math_ops.negative) |
| self._compareBothSparse(x, np.square, math_ops.square) |
| self._compareBothSparse(x, np.sqrt, math_ops.sqrt, tol=1e-3) |
| self._compareBothSparse(x, np.tanh, math_ops.tanh) |
| self._compareBothSparse(x, np.sign, math_ops.sign) |
| self._compareBothSparse(x, np.sign, math_ops.erf) |
| |
| @test_util.run_deprecated_v1 |
| def testDoubleBasic(self): |
| x = np.arange(-3, 3).reshape(1, 3, 2).astype(np.float64) |
| w = x - x.min() + 1.02 # all greater than 1 |
| y = (x + .5).astype(np.float64) # no zero |
| z = (x + 15.5).astype(np.float64) # all positive |
| k = np.arange(-0.90, 0.90, |
| 0.35).reshape(1, 3, 2).astype(np.float64) # between -1 and 1 |
| self._compareBoth(x, np.abs, math_ops.abs) |
| self._compareBoth(x, np.abs, _ABS) |
| self._compareBoth(x, np.negative, math_ops.negative) |
| self._compareBoth(x, np.negative, _NEG) |
| self._compareBoth(y, self._inv, math_ops.reciprocal) |
| self._compareBoth(x, np.square, math_ops.square) |
| self._compareBoth(z, np.sqrt, math_ops.sqrt) |
| self._compareBoth(z, self._rsqrt, math_ops.rsqrt) |
| self._compareBoth(x, np.exp, math_ops.exp) |
| self._compareBoth(x, np.expm1, math_ops.expm1) |
| self._compareBoth(z, np.log, math_ops.log) |
| self._compareBoth(z, np.log1p, math_ops.log1p) |
| self._compareBoth(x, np.sinh, math_ops.sinh) |
| self._compareBoth(x, np.cosh, math_ops.cosh) |
| self._compareBoth(x, np.tanh, math_ops.tanh) |
| self._compareBoth(x, np.arcsinh, math_ops.asinh) |
| self._compareBoth(w, np.arccosh, math_ops.acosh) |
| self._compareBoth(k, np.arctanh, math_ops.atanh) |
| self._compareBoth(x, self._sigmoid, math_ops.sigmoid) |
| self._compareBoth(y, np.sign, math_ops.sign) |
| self._compareBoth(x, np.sin, math_ops.sin) |
| self._compareBoth(x, np.cos, math_ops.cos) |
| self._compareBoth( |
| y, np.vectorize(self._replace_domain_error_with_inf(math.lgamma)), |
| math_ops.lgamma) |
| self._compareBoth(x, np.vectorize(math.erf), math_ops.erf) |
| self._compareBoth(x, np.vectorize(math.erfc), math_ops.erfc) |
| self._compareBoth(x, np.arctan, math_ops.atan) |
| self._compareBoth(k, np.arcsin, math_ops.asin) |
| self._compareBoth(k, np.arccos, math_ops.acos) |
| self._compareBoth(k, np.tan, math_ops.tan) |
| try: |
| from scipy import special # pylint: disable=g-import-not-at-top |
| self._compareBoth(x, special.i0e, special_math_ops.bessel_i0e) |
| self._compareBoth(x, special.i1e, special_math_ops.bessel_i1e) |
| except ImportError as e: |
| tf_logging.warn("Cannot test special functions: %s" % str(e)) |
| |
| self._compareBothSparse(x, np.abs, math_ops.abs) |
| self._compareBothSparse(x, np.negative, math_ops.negative) |
| self._compareBothSparse(x, np.square, math_ops.square) |
| self._compareBothSparse(z, np.sqrt, math_ops.sqrt, tol=1e-3) |
| self._compareBothSparse(x, np.tanh, math_ops.tanh) |
| self._compareBothSparse(y, np.sign, math_ops.sign) |
| self._compareBothSparse(x, np.vectorize(math.erf), math_ops.erf) |
| |
| @test_util.run_deprecated_v1 |
| def testHalfBasic(self): |
| x = np.arange(-3, 3).reshape(1, 3, 2).astype(np.float16) |
| y = (x + .5).astype(np.float16) # no zero |
| z = (x + 15.5).astype(np.float16) # all positive |
| self._compareBoth(x, np.abs, math_ops.abs) |
| self._compareBoth(x, np.abs, _ABS) |
| self._compareBoth(x, np.negative, math_ops.negative) |
| self._compareBoth(x, np.negative, _NEG) |
| self._compareBoth(y, self._inv, math_ops.reciprocal) |
| self._compareBoth(x, np.square, math_ops.square) |
| self._compareBoth(z, np.sqrt, math_ops.sqrt) |
| self._compareBoth(z, self._rsqrt, math_ops.rsqrt) |
| self._compareBoth(x, np.exp, math_ops.exp) |
| self._compareBoth(x, np.expm1, math_ops.expm1) |
| self._compareBoth(z, np.log, math_ops.log) |
| self._compareBoth(z, np.log1p, math_ops.log1p) |
| self._compareBoth(x, np.tanh, math_ops.tanh) |
| self._compareBoth(x, self._sigmoid, math_ops.sigmoid) |
| self._compareBoth(y, np.sign, math_ops.sign) |
| self._compareBoth(x, np.sin, math_ops.sin) |
| self._compareBoth(x, np.cos, math_ops.cos) |
| self._compareBoth( |
| y, np.vectorize(self._replace_domain_error_with_inf(math.lgamma)), |
| math_ops.lgamma) |
| self._compareBoth(x, np.vectorize(math.erf), math_ops.erf) |
| self._compareBoth(x, np.vectorize(math.erfc), math_ops.erfc) |
| self._compareBothSparse(x, np.abs, math_ops.abs) |
| self._compareBothSparse(x, np.negative, math_ops.negative) |
| self._compareBothSparse(x, np.square, math_ops.square) |
| self._compareBothSparse(z, np.sqrt, math_ops.sqrt, tol=1e-3) |
| self._compareBothSparse(x, np.tanh, math_ops.tanh) |
| self._compareBothSparse(y, np.sign, math_ops.sign) |
| self._compareBothSparse(x, np.vectorize(math.erf), math_ops.erf, tol=1e-3) |
| |
| @test_util.run_deprecated_v1 |
| def testBFloat16Basic(self): |
| def compute_f32(np_func): |
| """Decorator to compute Numpy function with float32 math.""" |
| def f(x): |
| y = np_func(x.astype(np.float32)) |
| return y.astype(x.dtype) |
| return f |
| |
| bfloat16 = dtypes_lib.bfloat16.as_numpy_dtype |
| x = np.arange(-6, 6, |
| 2).reshape(1, 3, 2).astype(dtypes_lib.bfloat16.as_numpy_dtype) |
| y = (x + .5).astype(bfloat16) # no zero |
| z = (x + 15.5).astype(bfloat16) # all positive |
| self._compareCpu(x, np.abs, math_ops.abs) |
| self._compareCpu(x, np.abs, _ABS) |
| self._compareBoth(x, np.negative, math_ops.negative) |
| self._compareBoth(x, np.negative, _NEG) |
| self._compareCpu(y, compute_f32(self._inv), math_ops.reciprocal) |
| self._compareCpu(x, np.exp, math_ops.exp) |
| self._compareCpu(x, np.expm1, math_ops.expm1) |
| self._compareCpu(z, compute_f32(np.log), math_ops.log) |
| self._compareCpu(z, compute_f32(np.log1p), math_ops.log1p) |
| self._compareCpu(y, np.sign, math_ops.sign) |
| self._compareBoth(x, compute_f32(np.sin), math_ops.sin) |
| self._compareBoth(x, compute_f32(np.cos), math_ops.cos) |
| self._compareBoth(x, compute_f32(np.tan), math_ops.tan) |
| self._compareBoth(x, compute_f32(np.sinh), math_ops.sinh) |
| self._compareBoth(x, compute_f32(np.cosh), math_ops.cosh) |
| self._compareBoth(x, compute_f32(np.tanh), math_ops.tanh) |
| |
| def testInt8Basic(self): |
| x = np.arange(-6, 6, 2).reshape(1, 3, 2).astype(np.int8) |
| self._compareCpu(x, np.abs, math_ops.abs) |
| self._compareCpu(x, np.abs, _ABS) |
| self._compareBoth(x, np.negative, math_ops.negative) |
| self._compareBoth(x, np.negative, _NEG) |
| |
| def testInt16Basic(self): |
| x = np.arange(-6, 6, 2).reshape(1, 3, 2).astype(np.int16) |
| self._compareCpu(x, np.abs, math_ops.abs) |
| self._compareCpu(x, np.abs, _ABS) |
| self._compareBoth(x, np.negative, math_ops.negative) |
| self._compareBoth(x, np.negative, _NEG) |
| |
| def testInt32Basic(self): |
| x = np.arange(-6, 6, 2).reshape(1, 3, 2).astype(np.int32) |
| self._compareCpu(x, np.abs, math_ops.abs) |
| self._compareCpu(x, np.abs, _ABS) |
| self._compareBoth(x, np.negative, math_ops.negative) |
| self._compareBoth(x, np.negative, _NEG) |
| self._compareBoth(x, np.square, math_ops.square) |
| self._compareCpu(x, np.sign, math_ops.sign) |
| |
| self._compareBothSparse(x, np.abs, math_ops.abs) |
| self._compareBothSparse(x, np.negative, math_ops.negative) |
| self._compareBothSparse(x, np.square, math_ops.square) |
| self._compareBothSparse(x, np.sign, math_ops.sign) |
| |
| def testInt64Basic(self): |
| x = np.arange(-6 << 40, 6 << 40, 2 << 40).reshape(1, 3, 2).astype(np.int64) |
| self._compareCpu(x, np.abs, math_ops.abs) |
| self._compareCpu(x, np.abs, _ABS) |
| self._compareCpu(x, np.negative, math_ops.negative) |
| self._compareCpu(x, np.negative, _NEG) |
| self._compareCpu(x, np.sign, math_ops.sign) |
| |
| self._compareBothSparse(x, np.abs, math_ops.abs) |
| self._compareBothSparse(x, np.negative, math_ops.negative) |
| self._compareBothSparse(x, np.sign, math_ops.sign) |
| |
| def testInt64Square(self): |
| x = np.arange(-6 << 20, 6 << 20, 2 << 20).reshape(1, 3, 2).astype(np.int64) |
| self._compareCpu(x, np.square, math_ops.square) |
| self._compareBothSparse(x, np.square, math_ops.square) |
| |
| @test_util.run_deprecated_v1 |
| def testComplex64Basic(self): |
| x = np.complex(1, 1) * np.arange(-3, 3).reshape(1, 3, 2).astype( |
| np.complex64) |
| y = x + np.complex(0.5, 0.5) # no zeros |
| self._compareBoth(x, np.abs, math_ops.abs) |
| self._compareBoth(x, np.abs, _ABS) |
| self._compareBoth(x, np.negative, math_ops.negative) |
| self._compareBoth(x, np.negative, _NEG) |
| self._compareCpu(y, self._inv, math_ops.reciprocal) |
| self._compareCpu(x, np.square, math_ops.square) |
| self._compareCpu(y, np.sqrt, math_ops.sqrt) |
| self._compareCpu(y, self._rsqrt, math_ops.rsqrt) |
| self._compareBoth(x, np.exp, math_ops.exp) |
| self._compareCpu(x, np.expm1, math_ops.expm1) |
| self._compareCpu(y, np.log, math_ops.log) |
| self._compareCpu(y, np.log1p, math_ops.log1p) |
| self._compareCpu(x, np.sinh, math_ops.sinh) |
| self._compareCpu(x, np.cosh, math_ops.cosh) |
| self._compareCpu(x, np.tanh, math_ops.tanh) |
| |
| # Complex64 versions of asinh() and acosh() in libstdc++ only have 6 digits |
| # of precision. |
| # Small gradient values + low precision --> High relative error |
| self._compareCpu(y, np.arcsinh, math_ops.asinh, grad_rtol=1e-2) |
| self._compareCpu(y, np.arccosh, math_ops.acosh, grad_rtol=1e-2) |
| |
| self._compareCpu(y, np.arctanh, math_ops.atanh) |
| self._compareCpu(x, self._sigmoid, math_ops.sigmoid) |
| self._compareCpu(x, np.sin, math_ops.sin) |
| self._compareCpu(x, np.cos, math_ops.cos) |
| |
| self._compareBothSparse(x, np.abs, math_ops.abs) |
| self._compareBothSparse(x, np.negative, math_ops.negative) |
| self._compareBothSparse(x, np.square, math_ops.square) |
| self._compareBothSparse(x, np.sqrt, math_ops.sqrt, 1e-3) |
| self._compareBothSparse(x, np.tanh, math_ops.tanh) |
| |
| # Numpy uses an incorrect definition of sign; use the right one instead. |
| def complex_sign(x): |
| return x / np.abs(x) |
| |
| self._compareBoth(y, complex_sign, math_ops.sign) |
| self._compareBothSparse(y, complex_sign, math_ops.sign) |
| |
| @test_util.run_deprecated_v1 |
| def testComplex128Basic(self): |
| x = np.complex(1, 1) * np.arange(-3, 3).reshape(1, 3, 2).astype( |
| np.complex128) |
| y = x + np.complex(0.5, 0.5) # no zeros |
| self._compareBoth(x, np.abs, math_ops.abs) |
| self._compareBoth(x, np.abs, _ABS) |
| self._compareBoth(x, np.negative, math_ops.negative) |
| self._compareBoth(x, np.negative, _NEG) |
| self._compareCpu(y, self._inv, math_ops.reciprocal) |
| self._compareCpu(x, np.square, math_ops.square) |
| self._compareCpu(y, np.sqrt, math_ops.sqrt) |
| self._compareCpu(y, self._rsqrt, math_ops.rsqrt) |
| self._compareBoth(x, np.exp, math_ops.exp) |
| self._compareCpu(x, np.expm1, math_ops.expm1) |
| self._compareCpu(y, np.log, math_ops.log) |
| self._compareCpu(y, np.log1p, math_ops.log1p) |
| self._compareCpu(x, np.sinh, math_ops.sinh) |
| self._compareCpu(x, np.cosh, math_ops.cosh) |
| self._compareCpu(x, np.tanh, math_ops.tanh) |
| self._compareCpu(y, np.arcsinh, math_ops.asinh) |
| self._compareCpu(y, np.arccosh, math_ops.acosh) |
| self._compareCpu(y, np.arctanh, math_ops.atanh) |
| self._compareCpu(x, self._sigmoid, math_ops.sigmoid) |
| self._compareCpu(x, np.sin, math_ops.sin) |
| self._compareCpu(x, np.cos, math_ops.cos) |
| |
| self._compareBothSparse(x, np.abs, math_ops.abs) |
| self._compareBothSparse(x, np.negative, math_ops.negative) |
| self._compareBothSparse(x, np.square, math_ops.square) |
| self._compareBothSparse(x, np.sqrt, math_ops.sqrt, 1e-3) |
| self._compareBothSparse(x, np.tanh, math_ops.tanh) |
| |
| # Numpy uses an incorrect definition of sign; use the right one instead. |
| def complex_sign(x): |
| return x / np.abs(x) |
| |
| self._compareBoth(y, complex_sign, math_ops.sign) |
| self._compareBothSparse(y, complex_sign, math_ops.sign) |
| |
| @test_util.run_deprecated_v1 |
| def testGradGrad(self): |
| np.random.seed(7) |
| shape = (5,) |
| dtype_tols = [(np.float32, 5e-4), (np.float64, 1e-6), (np.complex64, 5e-4), |
| (np.complex128, 1e-6)] |
| op_range = [ |
| (gen_math_ops.reciprocal_grad, [-2, 2]), |
| (gen_math_ops.rsqrt_grad, [0.1, 3]), |
| (gen_math_ops.sigmoid_grad, [-2, 2]), |
| (gen_math_ops.sqrt_grad, [0.1, 3]), |
| (gen_math_ops.tanh_grad, [-2, 2]), |
| ] |
| |
| def rand(dtype, real_range): |
| x = np.random.uniform( |
| real_range[0], real_range[1], size=shape[0]).astype(dtype) |
| if dtype in (np.complex64, np.complex128): |
| x += 1j * np.random.uniform(-2, 2, size=shape[0]).astype(dtype) |
| return x |
| |
| for op, real_range in op_range: |
| with self.cached_session(): |
| for dtype, tol in dtype_tols: |
| x = constant_op.constant(rand(dtype, real_range)) |
| y = constant_op.constant(rand(dtype, real_range)) |
| z = op(x, y) |
| grads = gradient_checker.compute_gradient( |
| [x, y], [shape, shape], |
| z, |
| shape, |
| x_init_value=[rand(dtype, real_range), |
| rand(dtype, real_range)]) |
| if isinstance(grads, tuple): |
| grads = [grads] |
| for analytical, numerical in grads: |
| self.assertAllClose(analytical, numerical, rtol=tol, atol=tol) |
| |
| @test_util.run_in_graph_and_eager_modes |
| def testComplexAbsGradGrad(self): |
| |
| def f(x): |
| real = math_ops.cos(x) |
| imag = ops.convert_to_tensor(1.) |
| return math_ops.abs(math_ops.complex(real, imag)) |
| |
| def g(x): |
| with backprop.GradientTape() as t: |
| t.watch(x) |
| y = f(x) |
| return t.gradient(y, x) |
| |
| err = gradient_checker_v2.max_error( |
| *gradient_checker_v2.compute_gradient(g, [ops.convert_to_tensor(2.0)])) |
| self.assertLess(err, 1e-3) |
| |
| |
| if __name__ == "__main__": |
| test.main() |