chore: import upstream snapshot with attribution
cffconvert / validate (push) Has been skipped
License Check / license-check (push) Failing after 2s

This commit is contained in:
wehub-resource-sync
2026-07-13 12:14:16 +08:00
commit 8a852e4b4e
36502 changed files with 9277225 additions and 0 deletions
@@ -0,0 +1,318 @@
# Tests of TensorFlow control flow ops written using the Python API.
load("//tensorflow:tensorflow.default.bzl", "cuda_py_strict_test", "tf_py_strict_test")
load("//tensorflow/core/platform:build_config_root.bzl", "tf_additional_xla_deps_py")
package(
# copybara:uncomment default_applicable_licenses = ["//tensorflow:license"],
licenses = ["notice"],
)
cuda_py_strict_test(
name = "cond_v2_test",
size = "medium",
srcs = ["cond_v2_test.py"],
grpc_enabled = True,
deps = [
"//tensorflow/core:protos_all_py",
"//tensorflow/python/compat",
"//tensorflow/python/eager:backprop",
"//tensorflow/python/eager:context",
"//tensorflow/python/eager:def_function",
"//tensorflow/python/eager:remote",
"//tensorflow/python/framework:constant_op",
"//tensorflow/python/framework:dtypes",
"//tensorflow/python/framework:ops",
"//tensorflow/python/framework:tensor_spec",
"//tensorflow/python/framework:test_lib",
"//tensorflow/python/framework:test_ops",
"//tensorflow/python/module",
"//tensorflow/python/ops:array_ops",
"//tensorflow/python/ops:cond",
"//tensorflow/python/ops:cond_v2",
"//tensorflow/python/ops:control_flow_ops",
"//tensorflow/python/ops:data_flow_ops",
"//tensorflow/python/ops:gradients_impl",
"//tensorflow/python/ops:linalg_ops_gen",
"//tensorflow/python/ops:logging_ops",
"//tensorflow/python/ops:math_ops",
"//tensorflow/python/ops:optional_ops_gen",
"//tensorflow/python/ops:resource_variable_ops",
"//tensorflow/python/ops:tensor_array_ops",
"//tensorflow/python/ops:variables",
"//tensorflow/python/ops:while_loop",
"//tensorflow/python/platform:client_testlib",
"//tensorflow/python/saved_model:load",
"//tensorflow/python/saved_model:save",
"//tensorflow/python/training",
"//tensorflow/python/training:saver",
"//tensorflow/python/util:compat",
"@absl_py//absl/testing:parameterized",
] + tf_additional_xla_deps_py(),
)
cuda_py_strict_test(
name = "control_flow_ops_py_test",
size = "medium",
srcs = ["control_flow_ops_py_test.py"],
shard_count = 16,
tags = [
"no_windows", # TODO(b/184424727): Re-enable this.
],
deps = [
"//tensorflow/core:protos_all_py",
"//tensorflow/python:distributed_framework_test_lib",
"//tensorflow/python:tf2",
"//tensorflow/python/client:device_lib",
"//tensorflow/python/client:session",
"//tensorflow/python/data/experimental/ops:cardinality",
"//tensorflow/python/data/ops:dataset_ops",
"//tensorflow/python/eager:context",
"//tensorflow/python/eager:def_function",
"//tensorflow/python/eager:wrap_function",
"//tensorflow/python/framework:constant_op",
"//tensorflow/python/framework:dtypes",
"//tensorflow/python/framework:errors",
"//tensorflow/python/framework:function",
"//tensorflow/python/framework:indexed_slices",
"//tensorflow/python/framework:ops",
"//tensorflow/python/framework:sparse_tensor",
"//tensorflow/python/framework:tensor",
"//tensorflow/python/framework:tensor_shape",
"//tensorflow/python/ops:array_ops",
"//tensorflow/python/ops:array_ops_gen",
"//tensorflow/python/ops:array_ops_stack",
"//tensorflow/python/ops:cond",
"//tensorflow/python/ops:control_flow_assert",
"//tensorflow/python/ops:control_flow_case",
"//tensorflow/python/ops:control_flow_ops",
"//tensorflow/python/ops:control_flow_ops_gen",
"//tensorflow/python/ops:control_flow_switch_case",
"//tensorflow/python/ops:control_flow_util",
"//tensorflow/python/ops:data_flow_ops",
"//tensorflow/python/ops:data_flow_ops_gen",
"//tensorflow/python/ops:functional_ops",
"//tensorflow/python/ops:gradient_checker_v2",
"//tensorflow/python/ops:gradients_impl",
"//tensorflow/python/ops:init_ops",
"//tensorflow/python/ops:linalg_ops",
"//tensorflow/python/ops:logging_ops",
"//tensorflow/python/ops:logging_ops_gen",
"//tensorflow/python/ops:map_fn",
"//tensorflow/python/ops:math_ops",
"//tensorflow/python/ops:nn_grad",
"//tensorflow/python/ops:nn_ops",
"//tensorflow/python/ops:random_ops",
"//tensorflow/python/ops:resource_variable_ops",
"//tensorflow/python/ops:script_ops",
"//tensorflow/python/ops:sparse_ops",
"//tensorflow/python/ops:state_ops",
"//tensorflow/python/ops:state_ops_gen",
"//tensorflow/python/ops:tensor_array_grad",
"//tensorflow/python/ops:tensor_array_ops",
"//tensorflow/python/ops:variable_scope",
"//tensorflow/python/ops:variable_v1",
"//tensorflow/python/ops:variables",
"//tensorflow/python/ops:while_loop",
"//tensorflow/python/ops:while_v2",
"//tensorflow/python/ops/ragged:ragged_factory_ops",
"//tensorflow/python/ops/ragged:ragged_tensor",
"//tensorflow/python/platform:client_testlib",
"//tensorflow/python/training:adam",
"//tensorflow/python/training:gradient_descent",
"//tensorflow/python/util:nest",
"//third_party/py/numpy",
"@absl_py//absl/testing:parameterized",
],
)
tf_py_strict_test(
name = "control_flow_util_test",
size = "small",
srcs = ["control_flow_util_test.py"],
deps = [
"//tensorflow/python/framework:dtypes",
"//tensorflow/python/framework:ops",
"//tensorflow/python/framework:test_lib",
"//tensorflow/python/framework:test_ops",
"//tensorflow/python/ops:array_ops",
"//tensorflow/python/ops:cond",
"//tensorflow/python/ops:control_flow_ops",
"//tensorflow/python/ops:control_flow_ops_gen",
"//tensorflow/python/ops:control_flow_util",
"//tensorflow/python/ops:math_ops",
"//tensorflow/python/ops:while_loop",
"//tensorflow/python/platform:client_testlib",
],
)
tf_py_strict_test(
name = "control_flow_util_v2_test",
size = "small",
srcs = ["control_flow_util_v2_test.py"],
deps = [
"//tensorflow/python/eager:def_function",
"//tensorflow/python/framework:constant_op",
"//tensorflow/python/framework:test_lib",
"//tensorflow/python/ops:cond",
"//tensorflow/python/ops:control_flow_util",
"//tensorflow/python/ops:control_flow_util_v2",
"//tensorflow/python/ops:while_loop",
"//tensorflow/python/platform:client_testlib",
],
)
cuda_py_strict_test(
name = "functional_ops_test",
size = "medium",
srcs = ["functional_ops_test.py"],
grpc_enabled = True,
shard_count = 2,
tags = ["no_windows"],
deps = [
"//tensorflow/core:protos_all_py",
"//tensorflow/python/client:session",
"//tensorflow/python/eager:cancellation",
"//tensorflow/python/eager:context",
"//tensorflow/python/eager:def_function",
"//tensorflow/python/eager:executor",
"//tensorflow/python/framework:config",
"//tensorflow/python/framework:constant_op",
"//tensorflow/python/framework:errors",
"//tensorflow/python/framework:for_generated_wrappers",
"//tensorflow/python/framework:test_lib",
"//tensorflow/python/ops:array_ops",
"//tensorflow/python/ops:collective_ops",
"//tensorflow/python/ops:functional_ops",
"//tensorflow/python/ops:functional_ops_gen",
"//tensorflow/python/ops:gradients_impl",
"//tensorflow/python/ops:init_ops",
"//tensorflow/python/ops:math_ops",
"//tensorflow/python/ops:tensor_array_grad",
"//tensorflow/python/ops:variable_scope",
"//tensorflow/python/ops:variables",
"//tensorflow/python/platform:client_testlib",
"//third_party/py/numpy",
],
)
cuda_py_strict_test(
name = "map_fn_test",
size = "small",
srcs = ["map_fn_test.py"],
grpc_enabled = True,
shard_count = 2,
tags = ["no_windows"],
xla_tags = [
"no_cuda_asan", # times out
],
deps = [
"//tensorflow/python/eager:context",
"//tensorflow/python/eager:def_function",
"//tensorflow/python/framework:constant_op",
"//tensorflow/python/framework:dtypes",
"//tensorflow/python/framework:sparse_tensor",
"//tensorflow/python/framework:test_lib",
"//tensorflow/python/ops:array_ops",
"//tensorflow/python/ops:gradients_impl",
"//tensorflow/python/ops:init_ops",
"//tensorflow/python/ops:map_fn",
"//tensorflow/python/ops:math_ops",
"//tensorflow/python/ops:resource_variable_ops",
"//tensorflow/python/ops:tensor_array_grad",
"//tensorflow/python/ops:variable_scope",
"//tensorflow/python/ops:variables",
"//tensorflow/python/ops/ragged:ragged_factory_ops",
"//tensorflow/python/ops/ragged:ragged_tensor",
"//tensorflow/python/platform:client_testlib",
"//third_party/py/numpy",
],
)
cuda_py_strict_test(
name = "py_func_test",
size = "small",
srcs = ["py_func_test.py"],
grpc_enabled = True,
tags = ["no_windows"],
deps = [
"//tensorflow/python/client:session",
"//tensorflow/python/eager:backprop",
"//tensorflow/python/eager:context",
"//tensorflow/python/eager:def_function",
"//tensorflow/python/framework:constant_op",
"//tensorflow/python/framework:errors",
"//tensorflow/python/framework:for_generated_wrappers",
"//tensorflow/python/framework:test_lib",
"//tensorflow/python/framework:type_spec",
"//tensorflow/python/ops:array_ops",
"//tensorflow/python/ops:batch_ops",
"//tensorflow/python/ops:gradients_impl",
"//tensorflow/python/ops:math_ops",
"//tensorflow/python/ops:resource_variable_ops",
"//tensorflow/python/ops:script_ops",
"//tensorflow/python/ops/ragged:ragged_factory_ops",
"//tensorflow/python/ops/ragged:ragged_tensor",
"//tensorflow/python/platform:client_testlib",
"//third_party/py/numpy",
],
)
cuda_py_strict_test(
name = "scan_ops_test",
size = "medium",
srcs = ["scan_ops_test.py"],
deps = [
"//tensorflow/python/framework:constant_op",
"//tensorflow/python/framework:errors",
"//tensorflow/python/framework:for_generated_wrappers",
"//tensorflow/python/framework:test_lib",
"//tensorflow/python/ops:gradient_checker",
"//tensorflow/python/ops:math_ops",
"//tensorflow/python/platform:client_testlib",
"//third_party/py/numpy",
],
)
cuda_py_strict_test(
name = "while_v2_test",
size = "medium",
srcs = ["while_v2_test.py"],
grpc_enabled = True,
deps = [
"//tensorflow/core:protos_all_py",
"//tensorflow/python/eager:backprop",
"//tensorflow/python/eager:context",
"//tensorflow/python/eager:def_function",
"//tensorflow/python/framework:constant_op",
"//tensorflow/python/framework:dtypes",
"//tensorflow/python/framework:function",
"//tensorflow/python/framework:importer",
"//tensorflow/python/framework:meta_graph",
"//tensorflow/python/framework:ops",
"//tensorflow/python/framework:tensor_shape",
"//tensorflow/python/framework:tensor_spec",
"//tensorflow/python/framework:test_lib",
"//tensorflow/python/grappler:tf_optimizer",
"//tensorflow/python/ops:array_ops",
"//tensorflow/python/ops:array_ops_gen",
"//tensorflow/python/ops:control_flow_util",
"//tensorflow/python/ops:control_flow_util_v2",
"//tensorflow/python/ops:control_flow_v2_toggles",
"//tensorflow/python/ops:custom_gradient",
"//tensorflow/python/ops:gradient_checker_v2",
"//tensorflow/python/ops:gradients_impl",
"//tensorflow/python/ops:list_ops",
"//tensorflow/python/ops:list_ops_gen",
"//tensorflow/python/ops:map_fn",
"//tensorflow/python/ops:math_ops",
"//tensorflow/python/ops:random_ops",
"//tensorflow/python/ops:variables",
"//tensorflow/python/ops:while_loop",
"//tensorflow/python/ops:while_v2",
"//tensorflow/python/ops/ragged:ragged_factory_ops",
"//tensorflow/python/ops/ragged:ragged_tensor",
"//tensorflow/python/platform:client_testlib",
"@absl_py//absl/testing:parameterized",
],
)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,182 @@
# Copyright 2017 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.
# ==============================================================================
"""Tests for tensorflow.python.ops.control_flow_util."""
from tensorflow.python.framework import dtypes
from tensorflow.python.framework import ops
from tensorflow.python.framework import test_ops
from tensorflow.python.framework import test_util
from tensorflow.python.ops import array_ops
from tensorflow.python.ops import cond
from tensorflow.python.ops import control_flow_ops
from tensorflow.python.ops import control_flow_util
from tensorflow.python.ops import gen_control_flow_ops
from tensorflow.python.ops import math_ops
from tensorflow.python.ops import while_loop as while_loop_tf
from tensorflow.python.platform import test
class ControlFlowUtilTest(test.TestCase):
@test_util.run_v1_only("b/120545219")
def testIsSwitch(self):
switch_false, _ = control_flow_ops.switch(1, True)
switch = switch_false.op
self.assertTrue(control_flow_util.IsSwitch(switch))
ref_switch_false, _ = control_flow_ops.ref_switch(test_ops.ref_output(),
True)
ref_switch = ref_switch_false.op
self.assertTrue(control_flow_util.IsSwitch(ref_switch))
self.assertFalse(control_flow_util.IsSwitch(test_ops.int_output().op))
@test_util.run_v1_only("b/120545219")
def testIsLoopEnter(self):
enter = gen_control_flow_ops.enter(1, frame_name="name").op
self.assertTrue(control_flow_util.IsLoopEnter(enter))
self.assertFalse(control_flow_util.IsLoopConstantEnter(enter))
ref_enter = gen_control_flow_ops.ref_enter(test_ops.ref_output(),
frame_name="name").op
self.assertTrue(control_flow_util.IsLoopEnter(ref_enter))
self.assertFalse(control_flow_util.IsLoopConstantEnter(ref_enter))
const_enter = gen_control_flow_ops.enter(1, frame_name="name",
is_constant=True).op
self.assertTrue(control_flow_util.IsLoopEnter(const_enter))
self.assertTrue(control_flow_util.IsLoopConstantEnter(const_enter))
self.assertFalse(control_flow_util.IsLoopEnter(test_ops.int_output().op))
@test_util.run_v1_only("b/120545219")
def testIsLoopExit(self):
exit_op = control_flow_ops.exit(1).op
self.assertTrue(control_flow_util.IsLoopExit(exit_op))
ref_exit = control_flow_ops.exit(test_ops.ref_output()).op
self.assertTrue(control_flow_util.IsLoopExit(ref_exit))
self.assertFalse(control_flow_util.IsLoopExit(test_ops.int_output().op))
def build_test_graph(self) -> ops.Graph:
g = ops.Graph()
with g.as_default():
def while_loop(x):
def b(x):
with ops.name_scope("NestedCond"):
return cond.cond(
math_ops.less(x, 100), lambda: math_ops.add(x, 1),
lambda: math_ops.add(x, 2))
c = lambda x: math_ops.less(x, 10000)
with ops.name_scope("OuterWhile"):
return while_loop_tf.while_loop(c, b, [x])
x = array_ops.placeholder(dtypes.int32)
with ops.name_scope("OuterCond"):
cond.cond(
math_ops.less(x, 1000), lambda: while_loop(x),
lambda: math_ops.add(x, 2))
return g
def testIsCondSwitch(self):
g = self.build_test_graph()
cond_switch = [
"OuterCond/cond/Switch",
"OuterCond/cond/OuterWhile/while/Switch",
"OuterCond/cond/OuterWhile/while/NestedCond/cond/Switch",
"OuterCond/cond/OuterWhile/while/NestedCond/cond/Add/Switch",
"OuterCond/cond/OuterWhile/while/NestedCond/cond/Add_1/Switch",
"OuterCond/cond/Add/Switch",
]
for n in g.get_operations():
if control_flow_util.IsSwitch(n):
self.assertTrue(
control_flow_util.IsCondSwitch(n) != control_flow_util.IsLoopSwitch(
n))
if n.name in cond_switch:
self.assertTrue(control_flow_util.IsSwitch(n))
self.assertTrue(
control_flow_util.IsCondSwitch(n),
msg="Mismatch for {}".format(n.name))
self.assertFalse(
control_flow_util.IsLoopSwitch(n),
msg="Mismatch for {}".format(n.name))
else:
self.assertFalse(
control_flow_util.IsCondSwitch(n),
msg="Mismatch for {}".format(n.name))
def testIsLoopSwitch(self):
g = self.build_test_graph()
loop_switch = ["OuterCond/cond/OuterWhile/while/Switch_1"]
for n in g.get_operations():
if control_flow_util.IsSwitch(n):
self.assertTrue(
control_flow_util.IsCondSwitch(n) != control_flow_util.IsLoopSwitch(
n))
if n.name in loop_switch:
self.assertTrue(control_flow_util.IsSwitch(n))
self.assertFalse(
control_flow_util.IsCondSwitch(n),
msg="Mismatch for {}".format(n.name))
self.assertTrue(
control_flow_util.IsLoopSwitch(n),
msg="Mismatch for {}".format(n.name))
else:
self.assertFalse(
control_flow_util.IsLoopSwitch(n),
msg="Mismatch for {}".format(n.name))
def testIsCondMerge(self):
g = self.build_test_graph()
cond_merges = [
"OuterCond/cond/OuterWhile/while/NestedCond/cond/Merge",
"OuterCond/cond/Merge"
]
for n in g.get_operations():
if n.name in cond_merges:
self.assertTrue(control_flow_util.IsMerge(n))
self.assertTrue(control_flow_util.IsCondMerge(n))
self.assertFalse(control_flow_util.IsLoopMerge(n))
else:
self.assertFalse(control_flow_util.IsCondMerge(n))
self.assertTrue(not control_flow_util.IsMerge(n) or
control_flow_util.IsLoopMerge(n))
def testIsLoopMerge(self):
g = self.build_test_graph()
loop_merges = [
"OuterCond/cond/OuterWhile/while/Merge",
]
for n in g.get_operations():
if n.name in loop_merges:
self.assertTrue(control_flow_util.IsMerge(n))
self.assertFalse(control_flow_util.IsCondMerge(n))
self.assertTrue(control_flow_util.IsLoopMerge(n))
else:
self.assertFalse(control_flow_util.IsLoopMerge(n))
self.assertTrue(not control_flow_util.IsMerge(n) or
control_flow_util.IsCondMerge(n))
if __name__ == "__main__":
test.main()
@@ -0,0 +1,62 @@
# 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.
# ==============================================================================
"""Tests for tensorflow.python.ops.control_flow_util_v2."""
from tensorflow.python.eager import def_function
from tensorflow.python.framework import constant_op
from tensorflow.python.framework import test_util
from tensorflow.python.ops import cond
from tensorflow.python.ops import control_flow_util
from tensorflow.python.ops import control_flow_util_v2
from tensorflow.python.ops import while_loop
from tensorflow.python.platform import test
class ControlFlowUtilV2Test(test.TestCase):
def setUp(self):
self._enable_control_flow_v2_old = control_flow_util.ENABLE_CONTROL_FLOW_V2
control_flow_util.ENABLE_CONTROL_FLOW_V2 = True
def tearDown(self):
control_flow_util.ENABLE_CONTROL_FLOW_V2 = self._enable_control_flow_v2_old
def _create_control_flow(self, expect_in_defun):
"""Helper method for testInDefun."""
def body(i):
def branch():
self.assertEqual(control_flow_util_v2.in_defun(), expect_in_defun)
return i + 1
return cond.cond(constant_op.constant(True),
branch, lambda: 0)
return while_loop.while_loop(lambda i: i < 4, body,
[constant_op.constant(0)])
@test_util.run_in_graph_and_eager_modes
def testInDefun(self):
self._create_control_flow(False)
@def_function.function
def defun():
self._create_control_flow(True)
defun()
self.assertFalse(control_flow_util_v2.in_defun())
if __name__ == "__main__":
test.main()
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,275 @@
# Copyright 2015 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.
# ==============================================================================
# pylint: disable=anomalous-backslash-in-string
"""Tests for tensorflow.kernels.functional_ops."""
import numpy as np
from tensorflow.python.eager import context
from tensorflow.python.eager import def_function
from tensorflow.python.framework import constant_op
from tensorflow.python.framework import dtypes
from tensorflow.python.framework import sparse_tensor
from tensorflow.python.framework import test_util
from tensorflow.python.ops import array_ops
from tensorflow.python.ops import gradients_impl
from tensorflow.python.ops import init_ops
from tensorflow.python.ops import map_fn
from tensorflow.python.ops import math_ops
from tensorflow.python.ops import resource_variable_ops
from tensorflow.python.ops import variable_scope
from tensorflow.python.ops import variables
from tensorflow.python.ops.ragged import ragged_factory_ops
from tensorflow.python.ops.ragged import ragged_tensor
import tensorflow.python.ops.tensor_array_grad # pylint: disable=unused-import
from tensorflow.python.platform import test
# pylint: disable=invalid-name
def simple_scoped_fn(a, x):
"""Simple function: (a, x) -> 2(x+a), but with "2" as a variable in scope."""
with variable_scope.variable_scope("body"):
# Dummy variable, just to check that scoping works as intended.
two = variable_scope.get_variable(
"two", [],
dtype=dtypes.int32,
initializer=init_ops.constant_initializer(2))
return math_ops.multiply(math_ops.add(a, x), two)
@test_util.with_control_flow_v2
class MapFnTest(test.TestCase):
@test_util.run_in_graph_and_eager_modes
def testMap_Simple(self):
nums = [1, 2, 3, 4, 5, 6]
elems = constant_op.constant(nums, name="data")
r = map_fn.map_fn(
lambda x: math_ops.multiply(math_ops.add(x, 3), 2), elems)
self.assertAllEqual(
np.array([(x + 3) * 2 for x in nums]), self.evaluate(r))
def testMapDtypeEager(self):
with context.eager_mode():
dtype = map_fn.map_fn(lambda x: constant_op.constant(""),
constant_op.constant([]),
dtype=dtypes.string).dtype
self.assertEqual(dtype, dtypes.string)
def testMapSparseTensor(self):
with self.cached_session():
st = sparse_tensor.SparseTensor(
indices=[[0, 0], [0, 1], [1, 0]],
values=constant_op.constant([0, 1, 2]),
dense_shape=[2, 2])
result = map_fn.map_fn(lambda x: x, st)
self.assertAllEqual(result.indices, st.indices)
self.assertAllEqual(result.values, st.values)
self.assertAllEqual(result.dense_shape, st.dense_shape)
def testMapRaggedTensor(self):
# Note: there are additional tests in ragged/ragged_map_fn_op_test.py
with self.cached_session():
rt = ragged_factory_ops.constant([[1, 2], [3]])
result = map_fn.map_fn(
lambda x: x + 1,
rt,
fn_output_signature=ragged_tensor.RaggedTensorSpec([None], rt.dtype))
self.assertAllEqual([[2, 3], [4]], result)
self.assertEqual([2, None], result.shape.as_list())
@test_util.run_in_graph_and_eager_modes
def testMapVariable(self):
v = resource_variable_ops.ResourceVariable([1, 2])
self.evaluate(v.initializer)
def loop_fn(x):
return x + 1
result = map_fn.map_fn(loop_fn, v)
expected_result = [2, 3]
self.assertAllEqual(result, expected_result)
@test_util.run_in_graph_and_eager_modes
def testMapOverScalarErrors(self):
with self.assertRaisesRegex(ValueError, "must be .* Tensor.* not scalar"):
map_fn.map_fn(lambda x: x, [1, 2])
with self.assertRaisesRegex(ValueError, "must be .* Tensor.* not scalar"):
map_fn.map_fn(lambda x: x, 1)
@test_util.run_deprecated_v1
def testMap_Scoped(self):
with self.cached_session() as sess:
def double_scoped(x):
"""2x with a dummy 2 that is scoped."""
with variable_scope.variable_scope("body"):
# Dummy variable, just to check that scoping works as intended.
two = variable_scope.get_variable(
"two", [],
dtype=dtypes.int32,
initializer=init_ops.constant_initializer(2))
return math_ops.multiply(x, two)
with variable_scope.variable_scope("root") as varscope:
elems = constant_op.constant([1, 2, 3, 4, 5, 6], name="data")
doubles = np.array([2 * x for x in [1, 2, 3, 4, 5, 6]])
r = map_fn.map_fn(double_scoped, elems)
# Check that we have the one variable we asked for here.
self.assertEqual(len(variables.trainable_variables()), 1)
self.assertEqual(variables.trainable_variables()[0].name,
"root/body/two:0")
sess.run([variables.global_variables_initializer()])
self.assertAllEqual(doubles, self.evaluate(r))
# Now let's reuse our single variable.
varscope.reuse_variables()
r = map_fn.map_fn(double_scoped, elems)
self.assertEqual(len(variables.trainable_variables()), 1)
self.assertAllEqual(doubles, self.evaluate(r))
@test_util.run_deprecated_v1
def testMap_Grad(self):
with self.cached_session():
param = constant_op.constant(2.0)
elems = constant_op.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], name="elems")
y = map_fn.map_fn(
lambda x: math_ops.multiply(math_ops.square(x), param), elems)
r_param = gradients_impl.gradients(y, param)[0]
r_elems = gradients_impl.gradients(y, elems)[0]
self.assertAllEqual(91.0, self.evaluate(r_param))
self.assertAllEqual([4.0, 8.0, 12.0, 16.0, 20.0, 24.0],
self.evaluate(r_elems))
@test_util.run_in_graph_and_eager_modes
def testMap_SimpleNotTensor(self):
nums = np.array([1, 2, 3, 4, 5, 6])
r = map_fn.map_fn(
lambda x: math_ops.multiply(math_ops.add(x, 3), 2), nums)
self.assertAllEqual(
np.array([(x + 3) * 2 for x in nums]), self.evaluate(r))
@test_util.run_in_graph_and_eager_modes
def testMap_SingleInputMultiOutput(self):
nums = np.array([1, 2, 3, 4, 5, 6])
r = map_fn.map_fn(
lambda x: ((x + 3) * 2, -(x + 3) * 2),
nums,
dtype=(dtypes.int64, dtypes.int64))
self.assertEqual(2, len(r))
self.assertEqual((6,), r[0].get_shape())
self.assertEqual((6,), r[1].get_shape())
received = self.evaluate(r)
self.assertAllEqual((nums + 3) * 2, received[0])
self.assertAllEqual(-(nums + 3) * 2, received[1])
@test_util.run_in_graph_and_eager_modes
def testMap_MultiOutputMismatchedDtype(self):
nums = np.array([1, 2, 3, 4, 5, 6])
with self.assertRaisesRegex(
TypeError, r"two structures don't have the same nested structure"):
# lambda emits tuple, but dtype is a list
map_fn.map_fn(
lambda x: ((x + 3) * 2, -(x + 3) * 2),
nums,
dtype=[dtypes.int64, dtypes.int64])
@test_util.run_in_graph_and_eager_modes
def testMap_MultiInputSingleOutput(self):
nums = np.array([1, 2, 3, 4, 5, 6])
r = map_fn.map_fn(
lambda x: x[0] * x[1][0] + x[1][1], (nums, (nums, -nums)),
dtype=dtypes.int64)
self.assertEqual((6,), r.get_shape())
received = self.evaluate(r)
self.assertAllEqual(nums * nums + (-nums), received)
@test_util.run_in_graph_and_eager_modes
def testMap_MultiInputSameStructureOutput(self):
nums = np.array([1, 2, 3, 4, 5, 6])
r = map_fn.map_fn(lambda x: (x[1][0], (x[1][1], x[0])),
(nums, (2 * nums, -nums)))
r = [r[0], r[1][0], r[1][1]]
self.assertEqual((6,), r[0].get_shape())
self.assertEqual((6,), r[1].get_shape())
self.assertEqual((6,), r[2].get_shape())
received = self.evaluate(r)
self.assertAllEqual(2 * nums, received[0])
self.assertAllEqual(-nums, received[1])
self.assertAllEqual(nums, received[2])
@test_util.run_in_graph_and_eager_modes
def testMap_autograph_indirect(self):
def test_function(x):
cond = constant_op.constant(-1)
if cond == 0:
result = x
else:
result = x
return result
@def_function.function
def map_call(x):
return map_fn.map_fn(test_function, x)
x = constant_op.constant([1])
y = map_call(x)
self.assertAllEqual([1], self.evaluate(y))
@test_util.run_in_graph_and_eager_modes
def testMapShape(self):
x = constant_op.constant([[1, 2, 3], [4, 5, 6]])
y = map_fn.map_fn(lambda e: e, x)
self.assertAllEqual(y.get_shape(), self.evaluate(y).shape)
@test_util.run_deprecated_v1
def testMapUnknownShape(self):
x = array_ops.placeholder(dtypes.float32)
y = map_fn.map_fn(lambda e: e, x)
self.assertIs(None, y.get_shape().dims)
# TODO(b/124383826): this test fails in eager: the iterable is of length 0 so
# so the body of the while loop never executes
@test_util.run_v1_only("b/120545219")
def testMapEmptyScalar(self):
map_return = map_fn.map_fn(lambda x: 1,
constant_op.constant([], dtype=dtypes.int32))
self.assertAllEqual([0], map_return.get_shape().dims)
self.assertAllEqual([0], self.evaluate(map_return).shape)
# TODO(b/124383826): this test fails in eager: the iterable is of length 0 so
# so the body of the while loop never executes
@test_util.run_v1_only("b/120545219")
def testMapEmptyTensor(self):
with self.cached_session():
map_return = map_fn.map_fn(lambda x: array_ops.zeros([3, 2]),
constant_op.constant([]))
self.assertAllEqual([0, 3, 2], map_return.get_shape().dims)
self.assertAllEqual([0, 3, 2], self.evaluate(map_return).shape)
@test_util.run_in_graph_and_eager_modes
def testMapEmptyList(self):
x = []
with self.assertRaisesRegex(ValueError, r"elems must be a Tensor or"):
_ = map_fn.map_fn(lambda e: e, x)
if __name__ == "__main__":
test.main()
# pylint: enable=invalid-name
@@ -0,0 +1,894 @@
# -*- coding: utf-8 -*-
# Copyright 2015 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.
# ==============================================================================
"""Tests for py_func op."""
import gc
import queue
import re
import numpy as np
from tensorflow.python.client import session as session_lib
from tensorflow.python.eager import backprop
from tensorflow.python.eager import context
from tensorflow.python.eager import def_function
from tensorflow.python.framework import constant_op
from tensorflow.python.framework import dtypes
from tensorflow.python.framework import errors
from tensorflow.python.framework import ops
from tensorflow.python.framework import test_util
from tensorflow.python.framework import type_spec
from tensorflow.python.ops import array_ops
from tensorflow.python.ops import batch_ops
from tensorflow.python.ops import gradients_impl
from tensorflow.python.ops import math_ops
from tensorflow.python.ops import resource_variable_ops
from tensorflow.python.ops import script_ops
from tensorflow.python.ops.ragged import ragged_factory_ops
from tensorflow.python.ops.ragged import ragged_tensor
from tensorflow.python.platform import test
def np_func(x, y):
return np.sinh(x) + np.cosh(y)
def matmul(x, y):
return math_ops.matmul(x, y)
class PyFuncTestBase(test.TestCase):
def verifyExceptionHandling(self, py_exp, tf_exp, eager=False):
def inner_exception():
raise py_exp("blah") # pylint: disable=not-callable
def raise_exception():
inner_exception()
expected_regexp = r": blah.*" # Error at the top
expected_regexp += r"in raise_exception.*" # Stacktrace outer
expected_regexp += r"in inner_exception.*" # Stacktrace inner
expected_regexp += r": blah" # Stacktrace of raise
def expected_error_check(exception):
return re.search(expected_regexp, str(exception), re.DOTALL)
if eager:
if context.executing_eagerly():
with self.assertRaisesWithPredicateMatch(tf_exp, expected_error_check):
f = script_ops.eager_py_func(raise_exception, [], [])
return
else:
f = script_ops.eager_py_func(raise_exception, [], [])
else:
f = script_ops.py_func(raise_exception, [], [])
with self.assertRaisesWithPredicateMatch(tf_exp, expected_error_check):
self.evaluate(f)
class PyFuncTest(PyFuncTestBase):
"""Encapsulates tests for py_func only."""
def testRealDataTypes(self):
def sum_func(x, y):
return x + y
for dtype in [dtypes.float16, dtypes.float32, dtypes.float64,
dtypes.uint8, dtypes.int8, dtypes.uint16, dtypes.int16,
dtypes.int32, dtypes.int64]:
with self.cached_session():
x = constant_op.constant(1, dtype=dtype)
y = constant_op.constant(2, dtype=dtype)
z = self.evaluate(script_ops.py_func(sum_func, [x, y], dtype))
self.assertEqual(z, 3)
def testComplexDataTypes(self):
def sub_func(x, y):
return x - y
for dtype in [dtypes.complex64, dtypes.complex128]:
with self.cached_session():
x = constant_op.constant(1 + 1j, dtype=dtype)
y = constant_op.constant(2 - 2j, dtype=dtype)
z = self.evaluate(script_ops.py_func(sub_func, [x, y], dtype))
self.assertEqual(z, -1 + 3j)
def testBoolDataTypes(self):
def and_func(x, y):
return x and y
dtype = dtypes.bool
with self.cached_session():
x = constant_op.constant(True, dtype=dtype)
y = constant_op.constant(False, dtype=dtype)
z = self.evaluate(script_ops.py_func(and_func, [x, y], dtype))
self.assertEqual(z, False)
def testSingleType(self):
with self.cached_session():
x = constant_op.constant(1.0, dtypes.float32)
y = constant_op.constant(2.0, dtypes.float32)
z = self.evaluate(script_ops.py_func(np_func, [x, y], dtypes.float32))
self.assertEqual(z, np_func(1.0, 2.0).astype(np.float32))
def testScalar(self):
with self.cached_session():
x = constant_op.constant(1.0, dtypes.float32)
y = constant_op.constant(2.0, dtypes.float32)
z = self.evaluate(
script_ops.eager_py_func(np_func, [x, y], [dtypes.float32]))
self.assertEqual(z[0], np_func(1.0, 2.0).astype(np.float32))
@test_util.run_v1_only("b/120545219")
def testArray(self):
with self.cached_session():
x = constant_op.constant([1.0, 2.0], dtypes.float64)
y = constant_op.constant([2.0, 3.0], dtypes.float64)
z = self.evaluate(script_ops.py_func(np_func, [x, y], [dtypes.float64]))
self.assertAllEqual(z[0],
np_func([1.0, 2.0], [2.0, 3.0]).astype(np.float64))
def testComplexType(self):
with self.cached_session():
x = constant_op.constant(1 + 2j, dtypes.complex64)
y = constant_op.constant(3 + 4j, dtypes.complex64)
z = self.evaluate(script_ops.py_func(np_func, [x, y], dtypes.complex64))
self.assertAllClose(z, np_func(1 + 2j, 3 + 4j))
def testRFFT(self):
with self.cached_session():
x = constant_op.constant([1., 2., 3., 4.], dtypes.float32)
def rfft(x):
return np.fft.rfft(x).astype(np.complex64)
y = self.evaluate(script_ops.py_func(rfft, [x], dtypes.complex64))
self.assertAllClose(y, np.fft.rfft([1., 2., 3., 4.]))
def testPythonLiteral(self):
with self.cached_session():
def literal(x):
return 1.0 if float(x) == 0.0 else 0.0
x = constant_op.constant(0.0, dtypes.float64)
y = self.evaluate(script_ops.py_func(literal, [x], dtypes.float64))
self.assertAllClose(y, 1.0)
def testList(self):
with self.cached_session():
def list_func(x):
return [x, x + 1]
x = constant_op.constant(0.0, dtypes.float64)
y = self.evaluate(
script_ops.py_func(list_func, [x], [dtypes.float64] * 2))
self.assertAllClose(y, [0.0, 1.0])
def testTuple(self):
# returns a tuple
with self.cached_session():
def tuple_func(x):
return x, x + 1
x = constant_op.constant(0.0, dtypes.float64)
y = self.evaluate(
script_ops.py_func(tuple_func, [x], [dtypes.float64] * 2))
self.assertAllClose(y, [0.0, 1.0])
# returns a tuple, Tout and inp a tuple
with self.cached_session():
x = constant_op.constant(0.0, dtypes.float64)
y = self.evaluate(
script_ops.py_func(tuple_func, (x,),
(dtypes.float64, dtypes.float64)))
self.assertAllClose(y, [0.0, 1.0])
@test_util.run_v1_only("b/120545219")
def testStrings(self):
def read_fixed_length_numpy_strings():
return np.array([b" there"])
def read_and_return_strings(x, y):
return x + y
with self.cached_session():
x = constant_op.constant([b"hello", b"hi"], dtypes.string)
y = self.evaluate(
script_ops.py_func(read_fixed_length_numpy_strings, [],
dtypes.string))
z = self.evaluate(
script_ops.py_func(read_and_return_strings, [x, y], dtypes.string))
self.assertAllEqual(z, [b"hello there", b"hi there"])
@test_util.run_v1_only("b/120545219")
def testStringsAreConvertedToBytes(self):
def read_fixed_length_numpy_strings():
return np.array([" there"])
def read_and_return_strings(x, y):
return x + y
with self.cached_session():
x = constant_op.constant(["hello", "hi"], dtypes.string)
y = self.evaluate(
script_ops.py_func(read_fixed_length_numpy_strings, [],
dtypes.string))
z = self.evaluate(
script_ops.py_func(read_and_return_strings, [x, y], dtypes.string))
self.assertAllEqual(z, [b"hello there", b"hi there"])
@test_util.run_v1_only("b/120545219")
def testObjectArraysAreConvertedToBytes(self):
def read_object_array():
return np.array([b" there", u" ya"], dtype=np.object_)
def read_and_return_strings(x, y):
return x + y
with self.cached_session():
x = constant_op.constant(["hello", "hi"], dtypes.string)
y, = script_ops.py_func(read_object_array, [],
[dtypes.string])
z, = script_ops.py_func(read_and_return_strings, [x, y], [dtypes.string])
self.assertListEqual(list(self.evaluate(z)), [b"hello there", b"hi ya"])
@test_util.run_v1_only("b/120545219")
def testStringPadding(self):
correct = [b"this", b"is", b"a", b"test"]
with self.cached_session():
s, = script_ops.py_func(lambda: [correct], [], [dtypes.string])
self.assertAllEqual(s, correct)
@test_util.run_v1_only("b/120545219")
def testStringPaddingAreConvertedToBytes(self):
inp = ["this", "is", "a", "test"]
correct = [b"this", b"is", b"a", b"test"]
with self.cached_session():
s, = script_ops.py_func(lambda: [inp], [], [dtypes.string])
self.assertAllEqual(s, correct)
@test_util.run_v1_only("b/120545219")
def testNulTerminatedStrings(self):
inp = np.array(["this\0", "is\0\0", "a\0", "test\0\0"], dtype=np.str_)
correct = [b"this", b"is", b"a", b"test"]
with self.cached_session():
s, = script_ops.py_func(lambda: [inp], [], [dtypes.string])
self.assertAllEqual(s, correct)
@test_util.run_v1_only("b/120545219")
def testLarge(self):
with self.cached_session() as sess:
x = array_ops.zeros([1000000], dtype=np.float32)
y = script_ops.py_func(lambda x: x + 1, [x], [dtypes.float32])
z = script_ops.py_func(lambda x: x * 2, [x], [dtypes.float32])
for _ in range(100):
sess.run([y[0].op, z[0].op])
def testNoInput(self):
with self.cached_session():
x = self.evaluate(script_ops.py_func(lambda: 42.0, [], dtypes.float64))
self.assertAllClose(x, 42.0)
@test_util.run_v1_only("b/120545219")
def testAlias(self):
with self.cached_session():
np_array = np.array([1.0, 2.0], dtype=np.float32)
tf_array = script_ops.py_func(lambda: np_array, [], [dtypes.float32])
value = tf_array + constant_op.constant([2.0, 3.0], dtype=dtypes.float32)
value.op.run()
self.assertAllEqual(np_array, [1.0, 2.0])
@test_util.run_v1_only("b/120545219")
def testReturnUnicodeString(self):
with self.cached_session():
correct = u"你好 世界"
def unicode_string():
return correct
z, = script_ops.py_func(unicode_string, [], [dtypes.string])
self.assertEqual(self.evaluate(z), correct.encode("utf8"))
@test_util.run_v1_only("b/120545219")
def testBadNumpyReturnType(self):
with self.cached_session():
def bad():
# Structured numpy arrays aren't supported.
return np.array([], dtype=[("foo", np.float32)])
y, = script_ops.py_func(bad, [], [dtypes.float32])
with self.assertRaisesRegex(errors.InternalError,
"Unsupported numpy data type"):
self.evaluate(y)
@test_util.run_v1_only("b/120545219")
def testBadReturnType(self):
with self.cached_session():
def bad():
# Non-string python objects aren't supported.
return {"foo": dtypes.float32}
z, = script_ops.py_func(bad, [], [dtypes.int64])
with self.assertRaisesRegex(errors.InternalError,
"Unsupported object type"):
self.evaluate(z)
@test_util.run_v1_only("b/120545219")
def testReturnInput(self):
with self.cached_session():
def ident(x):
return x[0]
p = array_ops.placeholder(dtypes.float32)
# Create a numpy array aliasing a tensor and a tensor aliasing this array
z, = script_ops.py_func(ident, [p], [dtypes.float32])
z += 0.0 # Makes sure we release the tensor aliasing the numpy array x[0]
# above instead of using its memory as the return value of
# session.run
self.assertEqual(0.0, z.eval(feed_dict={p: [0.0]}))
def testStateful(self):
# Not using self.cached_session(), which disables optimization.
with session_lib.Session():
producer = iter(range(3))
x, = script_ops.py_func(lambda: next(producer), [], [dtypes.int64])
self.assertEqual(self.evaluate(x), 0)
self.assertEqual(self.evaluate(x), 1)
self.assertEqual(self.evaluate(x), 2)
@test_util.enable_tf_xla_constant_folding("b/134376434")
def testStateless(self):
# Not using self.cached_session(), which disables optimization.
with session_lib.Session():
producer = iter(range(3))
x, = script_ops.py_func(
lambda: next(producer), [], [dtypes.int64], stateful=False)
self.assertEqual(self.evaluate(x), 0)
self.assertEqual(self.evaluate(x), 0)
self.assertEqual(self.evaluate(x), 0)
@test_util.run_v1_only("b/120545219")
def testGradientFunction(self):
# Input to tf.compat.v1.py_func is necessary,
# otherwise get_gradient_function() returns None per default.
a = constant_op.constant(0)
x, = script_ops.py_func(lambda a: 0, [a], [dtypes.int64])
y, = script_ops.py_func(lambda a: 0, [a], [dtypes.int64], stateful=False)
self.assertEqual(None, ops.get_gradient_function(x.op))
self.assertEqual(None, ops.get_gradient_function(y.op))
@test_util.run_v1_only("b/120545219")
def testCOrder(self):
with self.cached_session():
val = [[1, 2], [3, 4]]
x, = script_ops.py_func(lambda: np.array(val, order="F"), [],
[dtypes.int64])
self.assertAllEqual(val, self.evaluate(x))
@test_util.run_v1_only("b/120545219")
def testParallel(self):
# Tests that tf.compat.v1.py_func's can run in parallel if they release
# the GIL.
with self.cached_session() as session:
q = queue.Queue(1)
def blocking_put():
q.put(42)
q.join() # Wait for task_done().
return 42
def blocking_get():
v = q.get(block=True) # Wait for put().
q.task_done()
return v
x, = script_ops.py_func(blocking_put, [], [dtypes.int64])
y, = script_ops.py_func(blocking_get, [], [dtypes.int64])
# This will result in a deadlock if the py_func's don't run in parallel.
session.run([x, y])
def testNoReturnValueStateful(self):
class State:
def __init__(self):
self._value = np.array([1], np.int64)
def _increment(self, diff):
self._value += diff
def increment(self, diff):
return script_ops.py_func(self._increment, [diff], [], stateful=True)
@property
def value(self):
return self._value
with self.cached_session():
s = State()
op = s.increment(constant_op.constant(2, dtypes.int64))
ret = self.evaluate(op)
self.assertIsNone(ret)
self.assertAllEqual([3], s.value)
@test_util.run_v1_only("b/120545219")
def testNoReturnValueStateless(self):
def do_nothing(unused_x):
pass
f = script_ops.py_func(
do_nothing, [constant_op.constant(3, dtypes.int64)], [], stateful=False)
with self.cached_session():
self.assertEqual(self.evaluate(f), [])
@test_util.run_v1_only("b/120545219")
def testExceptionHandling(self):
with self.cached_session():
self.verifyExceptionHandling(ValueError, errors.InvalidArgumentError)
self.verifyExceptionHandling(TypeError, errors.InvalidArgumentError)
self.verifyExceptionHandling(StopIteration, errors.OutOfRangeError)
self.verifyExceptionHandling(MemoryError, errors.ResourceExhaustedError)
self.verifyExceptionHandling(NotImplementedError,
errors.UnimplementedError)
class WeirdError(Exception):
pass
self.verifyExceptionHandling(WeirdError, errors.UnknownError)
def testFunctionReferencesAreKept(self):
g = ops.Graph()
with g.as_default():
c = constant_op.constant([1.], dtypes.float32)
@batch_ops.batch_function(1, 10, 100000)
def fn(x):
# Upon exiting this function, the py_func holds the sole reference
# to this lambda, without which it would be garbage collected.
return script_ops.py_func(lambda x: x, [x], [dtypes.float32])
result = fn(c)
gc.collect()
self.evaluate(result)
class PyFuncAndEagerPyFuncTest(PyFuncTestBase):
"""Encapsulates tests shared between py_func and eager_py_func."""
def verifyPyFuncsNoIncrease(self, make_graph):
ops.reset_default_graph()
gc.collect()
gc.collect()
initial_size = script_ops._py_funcs.size()
for _ in range(1000):
make_graph()
ops.reset_default_graph()
gc.collect()
gc.collect()
self.assertEqual(initial_size, script_ops._py_funcs.size())
def testCleanup(self):
def make_graph():
g = ops.Graph()
with g.as_default():
c = constant_op.constant([1.], dtypes.float32)
_ = script_ops.py_func(lambda x: x + 1, [c], [dtypes.float32])
_ = script_ops.eager_py_func(lambda x: x + 1, [c], [dtypes.float32])
# These ops have a reference to 'c' which has a reference to the
# graph.
# Checks if the functions are being deleted though the graph is
# referenced from them (see #18292).
script_ops.py_func(
lambda x: x + c.shape[0], [c], [dtypes.float32])
script_ops.eager_py_func(
lambda x: x + c.shape[0], [c], [dtypes.float32])
self.verifyPyFuncsNoIncrease(make_graph)
def testCleanupInTfFunction(self):
self.skipTest("b/144098211")
def make_graph():
g = ops.Graph()
with g.as_default():
@def_function.function
def fn():
c = constant_op.constant([1.], dtypes.float32)
_ = script_ops.py_func(lambda x: x + 1, [c], [dtypes.float32])
_ = script_ops.eager_py_func(lambda x: x + 1, [c], [dtypes.float32])
# These ops have a reference to 'c' which has a reference to the
# graph.
# Checks if the functions are being deleted though the graph is
# referenced from them (see #18292).
script_ops.py_func(
lambda x: x + c.shape[0], [c], [dtypes.float32])
script_ops.eager_py_func(
lambda x: x + c.shape[0], [c], [dtypes.float32])
fn()
self.verifyPyFuncsNoIncrease(make_graph)
class EagerPyFuncTest(PyFuncTestBase):
"""Encapsulates tests for eager_py_func only."""
@test_util.run_in_graph_and_eager_modes
def testEagerSingleOutputInt32(self):
a = array_ops.ones((3, 3), dtype=dtypes.int32)
x = array_ops.ones((3, 1), dtype=dtypes.int32)
output = script_ops.eager_py_func(matmul, inp=[a, x], Tout=dtypes.int32)
ret = self.evaluate(output)
self.assertAllEqual(ret, [[3], [3], [3]])
@test_util.run_in_graph_and_eager_modes
def testRenamedDeviceInTestClusterCorrectlyIdentifiedAsLocalhost(self):
if context.executing_eagerly():
self.skipTest("b/126565353: We don't test eager's remote execution.")
workers, _ = test_util.create_local_cluster(num_workers=1, num_ps=0)
worker = workers[0]
session = session_lib.Session(worker.target)
with ops.device("/job:worker/task:0/cpu:0"):
a = array_ops.ones((3, 3), dtype=dtypes.float32)
x = array_ops.ones((3, 1), dtype=dtypes.float32)
output = script_ops.eager_py_func(matmul, inp=[a, x], Tout=dtypes.float32)
ret = session.run(output)
self.assertAllClose(ret, [[3.0], [3.0], [3.0]])
@test_util.run_in_graph_and_eager_modes
def testEagerSingleOutputFloat32(self):
with test_util.device(use_gpu=True):
a = array_ops.ones((3, 3), dtype=dtypes.float32)
x = array_ops.ones((3, 1), dtype=dtypes.float32)
output = script_ops.eager_py_func(matmul, inp=[a, x], Tout=dtypes.float32)
ret = self.evaluate(output)
self.assertAllClose(ret, [[3.0], [3.0], [3.0]])
@test_util.run_in_graph_and_eager_modes
def testEagerArrayOutput(self):
with test_util.device(use_gpu=True):
a = array_ops.ones((3, 3), dtype=dtypes.float32)
x = array_ops.ones((3, 1), dtype=dtypes.float32)
output = script_ops.eager_py_func(
lambda a, x: [matmul(a, x)], inp=[a, x], Tout=[dtypes.float32])
ret = self.evaluate(output)
self.assertAllEqual(ret, [[[3.0], [3.0], [3.0]]])
@test_util.run_in_graph_and_eager_modes
def testEagerReturnNone(self):
with test_util.device(use_gpu=True):
def no_return_value():
return
output = script_ops.eager_py_func(no_return_value, inp=[], Tout=[])
ret = self.evaluate(output)
if context.executing_eagerly():
self.assertEqual(len(ret), 0)
else:
self.assertIsNone(ret)
@test_util.run_in_graph_and_eager_modes
@test_util.disable_tfrt("b/180469928")
def testEagerPyFuncInDefun(self):
with test_util.device(use_gpu=True):
def wrapper():
a = array_ops.ones((3, 3), dtype=dtypes.float32)
x = array_ops.ones((3, 1), dtype=dtypes.float32)
return script_ops.eager_py_func(matmul, inp=[a, x], Tout=dtypes.float32)
wrapped = def_function.function(wrapper)
ret = self.evaluate(wrapped())
self.assertAllEqual(ret, [[3.0], [3.0], [3.0]])
@test_util.run_in_graph_and_eager_modes
@test_util.run_v1_only("b/120545219")
def testEagerExceptionHandling(self):
with test_util.device(use_gpu=True):
self.verifyExceptionHandling(
ValueError, errors.InvalidArgumentError, eager=True)
self.verifyExceptionHandling(
TypeError, errors.InvalidArgumentError, eager=True)
self.verifyExceptionHandling(
StopIteration, errors.OutOfRangeError, eager=True)
self.verifyExceptionHandling(
MemoryError, errors.ResourceExhaustedError, eager=True)
self.verifyExceptionHandling(
NotImplementedError, errors.UnimplementedError, eager=True)
class WeirdError(Exception):
pass
self.verifyExceptionHandling(WeirdError, errors.UnknownError, eager=True)
@test_util.run_in_graph_and_eager_modes
@test_util.run_v1_only("b/120545219")
def testEagerReturningVariableRaisesError(self):
def return_variable():
return resource_variable_ops.ResourceVariable(0.0)
with self.assertRaisesRegex(errors.UnknownError,
"Attempting to return a variable"):
output = script_ops.eager_py_func(
return_variable, inp=[], Tout=dtypes.float32)
self.evaluate(output)
@test_util.run_in_graph_and_eager_modes
def testTapeCache(self):
# Testing for b/198962664 (gh:#51839)
old_cache_size = len(script_ops.tape_cache)
def f(x):
return x**2
x = constant_op.constant(3.0)
y = script_ops.eager_py_func(f, inp=[x], Tout=dtypes.float32)
# No cache if there is no active tape
self.assertEqual(len(script_ops.tape_cache), old_cache_size)
with backprop.GradientTape() as tape:
tape.watch(x)
y = script_ops.eager_py_func(f, inp=[x], Tout=dtypes.float32)
# A new cache entry is created when running eagerly.
if context.executing_eagerly():
self.assertEqual(len(script_ops.tape_cache), old_cache_size + 1)
else:
self.assertEqual(len(script_ops.tape_cache), old_cache_size)
dy_dx = tape.gradient(y, x)
# Force a evaluation.
self.evaluate(dy_dx)
# Cache entry consumed after gradient calculation.
self.assertEqual(len(script_ops.tape_cache), old_cache_size)
@test_util.run_in_graph_and_eager_modes
def testEagerGradientTape(self):
def f(x):
return x**2
x = constant_op.constant(3.0)
with backprop.GradientTape() as tape:
tape.watch(x)
y = script_ops.eager_py_func(f, inp=[x], Tout=dtypes.float32)
dy_dx = tape.gradient(y, x)
self.assertAllClose(self.evaluate(dy_dx), 6.0)
# Test complex values
x = constant_op.constant(3.0 + 3.0j)
with backprop.GradientTape() as tape:
tape.watch(x)
y = script_ops.eager_py_func(f, inp=[x], Tout=dtypes.complex128)
dy_dx = tape.gradient(y, x)
# Gradient of complex will be the conj
self.assertAllClose(self.evaluate(dy_dx), 6.0 - 6.0j)
@test_util.run_v1_only("b/120545219")
def testEagerGradientGraph(self):
def f(x):
return x**2
x = constant_op.constant(3.0)
y = script_ops.eager_py_func(f, inp=[x], Tout=dtypes.float32)
dy_dx = gradients_impl.gradients(y, x)[0]
self.assertEqual(self.evaluate(dy_dx), 6.0)
@test_util.run_v1_only("b/120545219")
def testEagerGradientGraphTwoOutputs(self):
def f(x, y):
return x * y, x / y
x = constant_op.constant(3.0)
y = constant_op.constant(2.0)
fa, fb = script_ops.eager_py_func(f, inp=[x, y],
Tout=[dtypes.float32, dtypes.float32])
dy_dx = gradients_impl.gradients(fa + fb, x)[0]
self.assertEqual(self.evaluate(dy_dx), 2.5)
@test_util.run_in_graph_and_eager_modes
def testEagerGradientTapeMultipleArgs(self):
def f(x, y):
return x**2 + y**2
x = constant_op.constant(3.0)
y = constant_op.constant(4.0)
with backprop.GradientTape() as tape:
tape.watch(x)
tape.watch(y)
z = script_ops.eager_py_func(f, inp=[x, y], Tout=dtypes.float32)
dz_dx, dz_dy = tape.gradient(z, [x, y])
self.assertEqual(self.evaluate(dz_dx), 6.0)
self.assertEqual(self.evaluate(dz_dy), 8.0)
@test_util.run_v1_only("b/120545219")
def testEagerGradientGraphMultipleArgs(self):
def f(x, y):
return x**2 + y**2
x = constant_op.constant(3.0)
y = constant_op.constant(4.0)
z = script_ops.eager_py_func(f, inp=[x, y], Tout=dtypes.float32)
dz_dx, dz_dy = gradients_impl.gradients(z, [x, y])
self.assertEqual(self.evaluate(dz_dx), 6.0)
self.assertEqual(self.evaluate(dz_dy), 8.0)
@test_util.run_v1_only("b/120545219")
def testEagerGradientGraphLogHuber(self):
def log_huber(x, m):
if math_ops.abs(x) <= m:
return x**2
else:
return m**2 * (1 - 2 * math_ops.log(m) + math_ops.log(x**2))
x = array_ops.placeholder(dtypes.float32)
m = array_ops.placeholder(dtypes.float32)
y = script_ops.eager_py_func(
func=log_huber, inp=[x, m], Tout=dtypes.float32)
dy_dx = gradients_impl.gradients(y, x)[0]
with self.cached_session() as sess:
# Takes the first branch of log_huber.
y, dy_dx = sess.run([y, dy_dx], feed_dict={x: 1.0, m: 2.0})
self.assertEqual(y, 1.0)
self.assertEqual(dy_dx, 2.0)
@test_util.run_v1_only("b/120545219")
def testEagerRespectsDevicePlacementOfOp(self):
def f(x):
return math_ops.square(x)
def g(x):
return math_ops.add(x, x)
with ops.device("/CPU:0"):
# Explicitly ask for the py_funcs to execute on CPU, even if
# a GPU is available.
x = array_ops.placeholder(dtypes.float32)
y = script_ops.eager_py_func(func=f, inp=[x], Tout=dtypes.float32)
z = script_ops.eager_py_func(func=g, inp=[y], Tout=dtypes.float32)
with self.session() as sess:
output = sess.run(z, feed_dict={x: 3.0})
self.assertEqual(output, 18.0)
@test_util.run_in_graph_and_eager_modes
def testEagerPyFuncOnGPUWithStrings(self):
def fn(a):
return str(a.dtype)
x = constant_op.constant("x", dtype=dtypes.string)
output = script_ops.eager_py_func(fn, inp=[x], Tout=dtypes.string)
self.assertEqual(self.evaluate(output), "<dtype: 'string'>".encode("utf8"))
@test_util.run_in_graph_and_eager_modes
def testEagerPyFuncNotACallable(self):
x = constant_op.constant("x", dtype=dtypes.string)
with self.assertRaisesRegex(ValueError, "callable"):
_ = script_ops.eager_py_func(x, inp=[x], Tout=dtypes.string)
def testUnsupportedToutType(self):
with self.assertRaisesRegex(
TypeError, "Cannot convert .* to a TensorFlow DType."):
script_ops.eager_py_func(lambda x: x, [1], [{}])
def testRaggedTensorArg(self):
x = ragged_factory_ops.constant([[1, 2, 3], [4], [5, 6]])
y, = script_ops.eager_py_func(math_ops.reduce_sum, [x], [dtypes.int32])
self.assertAllEqual(y, 21)
def testRaggedTensorReturn(self):
def fn(v, l):
return ragged_tensor.RaggedTensor.from_row_lengths(v, l)
values = [1, 2, 3, 4, 5, 6]
lengths = constant_op.constant([3, 1, 2], dtypes.int64)
out_signature = [ragged_tensor.RaggedTensorSpec([None, None], dtypes.int32)]
y, = script_ops.eager_py_func(fn, [values, lengths], out_signature)
self.assertIsInstance(y, ragged_tensor.RaggedTensor)
self.assertAllEqual(y, [[1, 2, 3], [4], [5, 6]])
def testRaggedTensorBroadcast(self):
# Check that eager_py_func preserves output shape information, which is
# required by broadcasting.
def fn(x):
return 2 * x
def foo(x):
spec = ragged_tensor.RaggedTensorSpec.from_value(x)
res = script_ops.eager_py_func(fn, [x], spec)
return x + res
x = ragged_factory_ops.constant([[1.0, 2.0], [3.0]])
expected_result = [[3.0, 6.0], [9.0]]
result1 = foo(x)
self.assertAllEqual(result1, expected_result)
result2 = def_function.function(foo)(x)
self.assertAllEqual(result2, expected_result)
def testRaggedExpectedListGotList(self):
x = ragged_factory_ops.constant([[1, 2, 3], [4], [5, 6]])
x_spec = type_spec.type_spec_from_value(x)
y, = script_ops.eager_py_func(lambda v: [v], [x], [x_spec])
self.assertAllEqual(y, x)
def testRaggedExpectedListGotTuple(self):
x = ragged_factory_ops.constant([[1, 2, 3], [4], [5, 6]])
x_spec = type_spec.type_spec_from_value(x)
y, = script_ops.eager_py_func(lambda v: (v,), [x], [x_spec])
self.assertAllEqual(y, x)
def testRaggedExpectedListGotSingleValue(self):
x = ragged_factory_ops.constant([[1, 2, 3], [4], [5, 6]])
x_spec = type_spec.type_spec_from_value(x)
y, = script_ops.eager_py_func(lambda v: v, [x], [x_spec])
self.assertAllEqual(y, x)
def testRaggedNoReturnValue(self):
x = ragged_factory_ops.constant([[1, 2, 3], [4], [5, 6]])
result = self.evaluate(script_ops.eager_py_func(lambda v: None, [x], []))
if context.executing_eagerly():
self.assertEqual(result, [])
else:
self.assertIsNone(result)
def testRaggedBadReturnTypeExpectedTensorReturnedRagged(self):
rt = ragged_factory_ops.constant([[1, 2], [3, 4, 5]])
with self.assertRaisesRegex(
(ValueError, errors.InvalidArgumentError),
"py_function: func=.* returned .* which did not match Tout=.*"):
result = script_ops.eager_py_func(lambda x: x + 3, [rt], [dtypes.int32])
self.evaluate(result)
def testRaggedBadReturnTypeExpectedRaggedReturnedTensor(self):
with self.assertRaisesRegex(
(ValueError, errors.InvalidArgumentError),
"py_function: func=.* returned .* which did not match Tout=.*"):
result = script_ops.eager_py_func(
func=lambda x: x,
inp=[constant_op.constant([[1, 2, 3]])],
Tout=[ragged_tensor.RaggedTensorSpec([None, None], dtypes.int32)])
self.evaluate(result)
if __name__ == "__main__":
test.main()
@@ -0,0 +1,356 @@
# Copyright 2016 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 scan ops."""
import numpy as np
from tensorflow.python.framework import constant_op
from tensorflow.python.framework import dtypes
from tensorflow.python.framework import errors_impl
from tensorflow.python.framework import ops
from tensorflow.python.framework import test_util
from tensorflow.python.ops import gradient_checker
from tensorflow.python.ops import math_ops
from tensorflow.python.platform import test
def numpy_reverse(x, axis):
length = len(x.shape)
if axis < 0:
axis = length + axis
ix = [
slice(None, None, -1) if i == axis else slice(None) for i in range(length)
]
return x[tuple(ix)]
def handle_options(func, x, axis, exclusive, reverse):
"""Adds tf options to numpy scan ops."""
length = len(x.shape)
if axis < 0:
axis = length + axis
if reverse:
x = numpy_reverse(x, axis)
if exclusive:
ix_head = [slice(0, 1) if i == axis else slice(None) for i in range(length)]
ix_init = [
slice(0, -1) if i == axis else slice(None) for i in range(length)
]
if func == np.cumsum:
init = np.zeros_like(x[tuple(ix_head)])
elif func == np.cumprod:
init = np.ones_like(x[tuple(ix_head)])
else:
raise ValueError("Unknown scan function.")
x = np.concatenate([init, func(x[tuple(ix_init)], axis)], axis=axis)
else:
x = func(x, axis=axis)
if reverse:
x = numpy_reverse(x, axis)
return x
class CumsumTest(test.TestCase):
valid_dtypes = [
np.int32,
np.int64,
np.float16,
np.float32,
np.float64,
np.complex64,
np.complex128,
dtypes.bfloat16.as_numpy_dtype,
]
def _compare(self, x, axis, exclusive, reverse):
np_out = handle_options(np.cumsum, x, axis, exclusive, reverse)
with self.cached_session():
tf_out = math_ops.cumsum(x, axis, exclusive, reverse).eval()
self.assertAllClose(np_out, tf_out)
def _compareAll(self, x, axis):
for exclusive in [True, False]:
for reverse in [True, False]:
self._compare(x, axis, exclusive, reverse)
@test_util.run_deprecated_v1
def testEmpty(self):
for dtype in self.valid_dtypes:
x = np.zeros([0]).astype(dtype)
for axis in (-1, 0):
self._compareAll(x, axis)
@test_util.run_deprecated_v1
def testAxisType(self):
for dtype in self.valid_dtypes:
x = np.arange(1, 6).reshape([5]).astype(dtype)
for axis_dtype in [dtypes.int64, dtypes.int32]:
with self.cached_session():
axis = constant_op.constant(0, axis_dtype)
tf_out = math_ops.cumsum(x, axis).eval()
@test_util.run_deprecated_v1
def testNaN(self):
for dtype in (
np.float16,
np.float32,
np.float64,
dtypes.bfloat16.as_numpy_dtype,
):
for nan_idx in range(0, 5):
x = np.arange(1, 6).reshape([5]).astype(dtype)
x[nan_idx] = np.nan
for axis in (-1, 0):
self._compareAll(x, axis)
@test_util.run_deprecated_v1
def test1D(self):
for dtype in self.valid_dtypes:
x = np.arange(1, 6).reshape([5]).astype(dtype)
for axis in (-1, 0):
self._compareAll(x, axis)
@test_util.run_deprecated_v1
def test2D(self):
for dtype in self.valid_dtypes:
x = np.arange(0, 10).reshape([2, 5]).astype(dtype)
for axis in (-2, -1, 0, 1):
self._compareAll(x, axis)
@test_util.run_deprecated_v1
def test3D(self):
for dtype in self.valid_dtypes:
x = np.arange(0, 20).reshape([2, 2, 5]).astype(dtype)
for axis in (-3, -2, -1, 0, 1, 2):
self._compareAll(x, axis)
@test_util.run_deprecated_v1
def test6D(self):
for dtype in self.valid_dtypes:
x = np.arange(1, 145).reshape([2, 2, 3, 3, 2, 2]).astype(dtype)
for axis in range(-6, 6, 3):
self._compareAll(x, axis)
@test_util.run_deprecated_v1
@test_util.disable_xla("b/123860949") # The computation is constant folded
def testLarge(self):
for dtype in self.valid_dtypes:
if np.__version__ >= np.lib.NumpyVersion("2.0.0") and dtype == np.float16:
continue
if dtype == dtypes.bfloat16.as_numpy_dtype:
# https://github.com/numpy/numpy/issues/27709, which might be fixed
# in some numpy version after 2.1.3.
continue
x = np.ones([1000000], dtype=dtype) / 1024
self._compareAll(x, 0)
def testInvalidAxis(self):
x = np.arange(0, 10).reshape([2, 5]).astype(np.float32)
input_tensor = ops.convert_to_tensor(x)
with self.session():
with self.assertRaisesWithPredicateMatch(
errors_impl.InvalidArgumentError,
lambda e: "Expected scan axis in the range [-2, 2)" in str(e)):
math_ops.cumsum(input_tensor, -3).eval()
with self.assertRaisesWithPredicateMatch(
errors_impl.InvalidArgumentError,
lambda e: "Expected scan axis in the range [-2, 2)" in str(e)):
math_ops.cumsum(input_tensor, 2).eval()
with self.assertRaisesWithPredicateMatch(
errors_impl.InvalidArgumentError,
lambda e: "axis must be a scalar" in str(e)):
math_ops.cumsum(input_tensor, [0]).eval()
def _compareGradient(self, shape, axis, exclusive, reverse):
x = np.arange(0, 50).reshape(shape).astype(np.float64)
with self.cached_session():
t = ops.convert_to_tensor(x)
result = math_ops.cumsum(t, axis, exclusive, reverse)
jacob_t, jacob_n = gradient_checker.compute_gradient(
t, shape, result, shape, x_init_value=x, delta=1)
self.assertAllClose(jacob_t, jacob_n, rtol=1e-8, atol=1e-8)
@test_util.run_deprecated_v1
def testGradient(self):
for axis in (-1, 0):
self._compareGradient([50], axis, False, False)
@test_util.run_deprecated_v1
def testGradientReverse(self):
for axis in (-1, 0):
self._compareGradient([50], axis, False, True)
@test_util.run_deprecated_v1
def testGradientExclusive(self):
for axis in (-1, 0):
self._compareGradient([50], axis, True, False)
@test_util.run_deprecated_v1
def testGradientExclusiveReverse(self):
for axis in (-1, 0):
self._compareGradient([50], axis, True, True)
@test_util.run_deprecated_v1
def testGradient2D(self):
for axis in (-1, 0, 1):
for exclusive in [True, False]:
for reverse in [True, False]:
self._compareGradient([5, 10], axis, exclusive, reverse)
class CumprodTest(test.TestCase):
valid_dtypes = [
np.int32,
np.int64,
np.float16,
np.float32,
np.float64,
np.complex64,
np.complex128,
dtypes.bfloat16.as_numpy_dtype,
]
def _compare(self, x, axis, exclusive, reverse):
np_out = handle_options(np.cumprod, x, axis, exclusive, reverse)
with self.cached_session():
tf_out = math_ops.cumprod(x, axis, exclusive, reverse).eval()
atol = rtol = 1e-6
if x.dtype == dtypes.bfloat16.as_numpy_dtype:
atol = rtol = 1e-2
self.assertAllClose(np_out, tf_out, atol=atol, rtol=rtol)
def _compareAll(self, x, axis):
for exclusive in [True, False]:
for reverse in [True, False]:
self._compare(x, axis, exclusive, reverse)
@test_util.run_deprecated_v1
def testEmpty(self):
for dtype in self.valid_dtypes:
x = np.zeros([0]).astype(dtype)
for axis in (-1, 0):
self._compareAll(x, axis)
@test_util.run_deprecated_v1
def testAxisType(self):
for dtype in self.valid_dtypes:
x = np.arange(1, 6).reshape([5]).astype(dtype)
for axis_dtype in [dtypes.int64, dtypes.int32]:
with self.cached_session():
axis = constant_op.constant(0, axis_dtype)
tf_out = math_ops.cumprod(x, axis).eval()
@test_util.run_deprecated_v1
def testNaN(self):
for dtype in (np.float16, np.float32, np.float64):
for nan_idx in range(0, 5):
x = np.arange(1, 6).reshape([5]).astype(dtype)
x[nan_idx] = np.nan
for axis in (-1, 0):
self._compareAll(x, axis)
@test_util.run_deprecated_v1
def test1D(self):
for dtype in self.valid_dtypes:
x = np.arange(1, 6).reshape([5]).astype(dtype)
for axis in (-1, 0):
self._compareAll(x, axis)
@test_util.run_deprecated_v1
def test2D(self):
for dtype in self.valid_dtypes:
x = np.arange(1, 11).reshape([2, 5]).astype(dtype)
for axis in (-2, -1, 0, 1):
self._compareAll(x, axis)
@test_util.run_deprecated_v1
def test3D(self):
for dtype in self.valid_dtypes:
x = np.arange(1, 21).reshape([2, 2, 5]).astype(dtype)
for axis in (-3, -2, -1, 0, 1, 2):
self._compareAll(x, axis)
@test_util.run_deprecated_v1
def test6D(self):
for dtype in self.valid_dtypes:
x = np.arange(1, 145).reshape([2, 2, 3, 3, 2, 2]).astype(dtype)
for axis in range(-6, 6, 3):
self._compareAll(x, axis)
def testInvalidAxis(self):
x = np.arange(0, 10).reshape([2, 5]).astype(np.float32)
input_tensor = ops.convert_to_tensor(x)
with self.session():
with self.assertRaisesWithPredicateMatch(
errors_impl.InvalidArgumentError,
lambda e: "Expected scan axis in the range [-2, 2)" in str(e)):
math_ops.cumprod(input_tensor, -3).eval()
with self.assertRaisesWithPredicateMatch(
errors_impl.InvalidArgumentError,
lambda e: "Expected scan axis in the range [-2, 2)" in str(e)):
math_ops.cumprod(input_tensor, 2).eval()
with self.assertRaisesWithPredicateMatch(
errors_impl.InvalidArgumentError,
lambda e: "axis must be a scalar" in str(e)):
math_ops.cumprod(input_tensor, [0]).eval()
def _compareGradient(self, shape, axis, exclusive, reverse):
x = np.arange(1, 9).reshape(shape).astype(np.float64)
with self.cached_session():
t = ops.convert_to_tensor(x)
result = math_ops.cumprod(t, axis, exclusive, reverse)
jacob_t, jacob_n = gradient_checker.compute_gradient(
t, shape, result, shape, x_init_value=x, delta=1)
self.assertAllClose(jacob_t, jacob_n, rtol=1e-8, atol=1e-8)
@test_util.run_deprecated_v1
def testGradient(self):
for axis in (-1, 0):
self._compareGradient([8], axis, False, False)
@test_util.run_deprecated_v1
def testGradientReverse(self):
for axis in (-1, 0):
self._compareGradient([8], axis, False, True)
@test_util.run_deprecated_v1
def testGradientExclusive(self):
for axis in (-1, 0):
self._compareGradient([8], axis, True, False)
@test_util.run_deprecated_v1
def testGradientExclusiveReverse(self):
for axis in (-1, 0):
self._compareGradient([8], axis, True, True)
@test_util.run_deprecated_v1
def testGradient2D(self):
for axis in (-2, -1, 0, 1):
for exclusive in [True, False]:
for reverse in [True, False]:
self._compareGradient([2, 4], axis, exclusive, reverse)
if __name__ == "__main__":
test.main()
File diff suppressed because it is too large Load Diff