# 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 ConstantOp.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function import numpy as np from google.protobuf import text_format from tensorflow.core.framework import graph_pb2 from tensorflow.core.framework import tensor_pb2 from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes as dtypes_lib from tensorflow.python.framework import errors_impl from tensorflow.python.framework import importer from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import logging_ops from tensorflow.python.ops import math_ops from tensorflow.python.platform import test from tensorflow.python.util import compat class ConstantTest(test.TestCase): def _testCpu(self, x): np_ans = np.array(x) with self.test_session(use_gpu=False): tf_ans = ops.convert_to_tensor(x).eval() dtype = dtypes_lib.as_dtype(np_ans.dtype) if dtype.is_floating or dtype.is_complex: self.assertAllClose(np_ans, tf_ans) else: self.assertAllEqual(np_ans, tf_ans) def _testGpu(self, x): np_ans = np.array(x) with self.test_session(use_gpu=True): tf_ans = ops.convert_to_tensor(x).eval() dtype = dtypes_lib.as_dtype(np_ans.dtype) if dtype.is_floating or dtype.is_complex: self.assertAllClose(np_ans, tf_ans) else: self.assertAllEqual(np_ans, tf_ans) def _testAll(self, x): self._testCpu(x) self._testGpu(x) def testInvalidDType(self): # Test case for GitHub issue 18474 with self.assertRaises(TypeError): constant_op.constant(dtypes_lib.string, "[,]") def testBFloat16(self): bfloat16 = dtypes_lib.bfloat16.as_numpy_dtype self._testAll(np.arange(-15, 15).reshape([2, 3, 5]).astype(bfloat16)) self._testAll( np.random.normal(size=30).reshape([2, 3, 5]).astype(bfloat16)) self._testAll(np.empty((2, 0, 5)).astype(bfloat16)) def testHalf(self): self._testAll(np.arange(-15, 15).reshape([2, 3, 5]).astype(np.float16)) self._testAll( np.random.normal(size=30).reshape([2, 3, 5]).astype(np.float16)) self._testAll(np.empty((2, 0, 5)).astype(np.float16)) def testFloat(self): self._testAll(np.arange(-15, 15).reshape([2, 3, 5]).astype(np.float32)) self._testAll( np.random.normal(size=30).reshape([2, 3, 5]).astype(np.float32)) self._testAll(np.empty((2, 0, 5)).astype(np.float32)) def testDouble(self): self._testAll(np.arange(-15, 15).reshape([2, 3, 5]).astype(np.float64)) self._testAll( np.random.normal(size=30).reshape([2, 3, 5]).astype(np.float64)) self._testAll(np.empty((2, 0, 5)).astype(np.float64)) def testInt32(self): self._testAll(np.arange(-15, 15).reshape([2, 3, 5]).astype(np.int32)) self._testAll((100 * np.random.normal(size=30)).reshape([2, 3, 5]).astype( np.int32)) self._testAll(np.empty((2, 0, 5)).astype(np.int32)) def testInt64(self): self._testAll(np.arange(-15, 15).reshape([2, 3, 5]).astype(np.int64)) self._testAll((100 * np.random.normal(size=30)).reshape([2, 3, 5]).astype( np.int64)) self._testAll(np.empty((2, 0, 5)).astype(np.int64)) def testComplex64(self): self._testAll( np.complex(1, 2) * np.arange(-15, 15).reshape([2, 3, 5]).astype(np.complex64)) self._testAll( np.complex(1, 2) * np.random.normal(size=30).reshape([2, 3, 5]).astype(np.complex64)) self._testAll(np.empty((2, 0, 5)).astype(np.complex64)) def testComplex128(self): self._testAll( np.complex(1, 2) * np.arange(-15, 15).reshape([2, 3, 5]).astype(np.complex128)) self._testAll( np.complex(1, 2) * np.random.normal(size=30).reshape([2, 3, 5]).astype(np.complex128)) self._testAll(np.empty((2, 0, 5)).astype(np.complex128)) def testString(self): self._testCpu( np.array([compat.as_bytes(str(x)) for x in np.arange(-15, 15)]).reshape( [2, 3, 5])) self._testCpu(np.empty((2, 0, 5)).astype(np.str_)) def testVariant(self): # TODO(ebrevdo): Re-enable use_gpu=True once non-DMA Variant # copying between CPU and GPU is supported. with self.test_session(use_gpu=False): variant_tensor = tensor_pb2.TensorProto( dtype=dtypes_lib.variant.as_datatype_enum, tensor_shape=tensor_shape.TensorShape([]).as_proto(), variant_val=[ tensor_pb2.VariantTensorDataProto( # Match registration in variant_op_registry.cc type_name=b"int", metadata=np.array(1, dtype=np.int32).tobytes()) ]) const = constant_op.constant(variant_tensor) const_value = const.op.get_attr("value") # Ensure we stored the tensor proto properly. self.assertProtoEquals(variant_tensor, const_value) # Smoke test -- ensure this executes without trouble. # Right now, non-numpy-compatible objects cannot be returned from a # session.run call; similarly, objects that can't be converted to # native numpy types cannot be passed to ops.convert_to_tensor. # TODO(ebrevdo): Add registration mechanism for # ops.convert_to_tensor and for session.run output. logging_const_op = logging_ops.Print( const, [const], message="Variant storing an int, decoded const value:").op logging_const_op.run() def testStringWithNulls(self): with self.cached_session(): val = ops.convert_to_tensor(b"\0\0\0\0").eval() self.assertEqual(len(val), 4) self.assertEqual(val, b"\0\0\0\0") with self.cached_session(): val = ops.convert_to_tensor(b"xx\0xx").eval() self.assertEqual(len(val), 5) self.assertAllEqual(val, b"xx\0xx") nested = [[b"\0\0\0\0", b"xx\0xx"], [b"\0_\0_\0_\0", b"\0"]] with self.cached_session(): val = ops.convert_to_tensor(nested).eval() # NOTE(mrry): Do not use assertAllEqual, because it converts nested to a # numpy array, which loses the null terminators. self.assertEqual(val.tolist(), nested) def testExplicitShapeNumPy(self): with ops.Graph().as_default(): c = constant_op.constant( np.arange(-15, 15).reshape([2, 3, 5]).astype(np.float32), shape=[2, 3, 5]) self.assertEqual(c.get_shape(), [2, 3, 5]) @test_util.assert_no_new_pyobjects_executing_eagerly def testEagerMemory(self): """Tests PyObject refs are managed correctly when executing eagerly.""" constant_op.constant([[1.]]) def testImplicitShapeNumPy(self): with ops.Graph().as_default(): c = constant_op.constant( np.arange(-15, 15).reshape([2, 3, 5]).astype(np.float32)) self.assertEqual(c.get_shape(), [2, 3, 5]) def testExplicitShapeList(self): with ops.Graph().as_default(): c = constant_op.constant([1, 2, 3, 4, 5, 6, 7], shape=[7]) self.assertEqual(c.get_shape(), [7]) def testImplicitShapeList(self): with ops.Graph().as_default(): c = constant_op.constant([1, 2, 3, 4, 5, 6, 7]) self.assertEqual(c.get_shape(), [7]) def testExplicitShapeNumber(self): with ops.Graph().as_default(): c = constant_op.constant(1, shape=[1]) self.assertEqual(c.get_shape(), [1]) def testImplicitShapeNumber(self): with ops.Graph().as_default(): c = constant_op.constant(1) self.assertEqual(c.get_shape(), []) def testShapeInconsistent(self): with ops.Graph().as_default(): c = constant_op.constant([1, 2, 3, 4, 5, 6, 7], shape=[10]) self.assertEqual(c.get_shape(), [10]) # pylint: disable=g-long-lambda def testShapeWrong(self): with ops.Graph().as_default(): with self.assertRaisesWithPredicateMatch( ValueError, lambda e: ("Too many elements provided. Needed at most 5, " "but received 7" == str(e))): constant_op.constant([1, 2, 3, 4, 5, 6, 7], shape=[5]) # pylint: enable=g-long-lambda # TODO(b/35396543): Temporarily disable: suspicion that # this is causing test timeouts. def _testTooLargeConstant(self): with ops.Graph().as_default(): large_array = np.zeros((512, 1024, 1024), dtype=np.float32) with self.assertRaisesRegexp( ValueError, "Cannot create a tensor proto whose content is larger than 2GB."): c = constant_op.constant(large_array) # TODO(b/35396543): Temporarily disable: suspicion that # this is causing test timeouts. def _testTooLargeGraph(self): with ops.Graph().as_default() as g: large_array = np.zeros((256, 1024, 1024), dtype=np.float32) c = constant_op.constant(large_array) d = constant_op.constant(large_array) with self.assertRaisesRegexp(ValueError, "GraphDef cannot be larger than 2GB."): g.as_graph_def() def testSparseValuesRaiseErrors(self): with self.assertRaisesRegexp(ValueError, "setting an array element with a sequence"): c = constant_op.constant([[1, 2], [3]], dtype=dtypes_lib.int32) with self.assertRaisesRegexp(ValueError, "must be a dense"): c = constant_op.constant([[1, 2], [3]]) with self.assertRaisesRegexp(ValueError, "must be a dense"): c = constant_op.constant([[1, 2], [3], [4, 5]]) class AsTensorTest(test.TestCase): def testAsTensorForTensorInput(self): with ops.Graph().as_default(): t = constant_op.constant(10.0) x = ops.convert_to_tensor(t) self.assertIs(t, x) def testAsTensorForNonTensorInput(self): with ops.Graph().as_default(): x = ops.convert_to_tensor(10.0) self.assertTrue(isinstance(x, ops.Tensor)) def testAsTensorForShapeInput(self): with self.cached_session(): x = ops.convert_to_tensor(tensor_shape.TensorShape([])) self.assertEqual(dtypes_lib.int32, x.dtype) self.assertAllEqual([], x.eval()) x = ops.convert_to_tensor(tensor_shape.TensorShape([1, 2, 3])) self.assertEqual(dtypes_lib.int32, x.dtype) self.assertAllEqual([1, 2, 3], x.eval()) x = ops.convert_to_tensor(tensor_shape.TensorShape([2**31-1, 2, 3])) self.assertEqual(dtypes_lib.int32, x.dtype) self.assertAllEqual([2**31-1, 2, 3], x.eval()) x = ops.convert_to_tensor(tensor_shape.TensorShape([2**31-1, 2, 3]), dtype=dtypes_lib.int32) self.assertEqual(dtypes_lib.int32, x.dtype) self.assertAllEqual([2**31-1, 2, 3], x.eval()) x = ops.convert_to_tensor(tensor_shape.TensorShape([2**31, 2, 3])) self.assertEqual(dtypes_lib.int64, x.dtype) self.assertAllEqual([2**31, 2, 3], x.eval()) x = ops.convert_to_tensor(tensor_shape.TensorShape([2**31, 2, 3]), dtype=dtypes_lib.int64) self.assertEqual(dtypes_lib.int64, x.dtype) self.assertAllEqual([2**31, 2, 3], x.eval()) with self.assertRaisesRegexp( ValueError, "a dimension is too large .2147483648."): x = ops.convert_to_tensor(tensor_shape.TensorShape([2**31, 2, 3]), dtype=dtypes_lib.int32) x = ops.convert_to_tensor( tensor_shape.TensorShape([1, 2, 3]), dtype=dtypes_lib.int64) self.assertEqual(dtypes_lib.int64, x.dtype) self.assertAllEqual([1, 2, 3], x.eval()) x = array_ops.reshape( array_ops.zeros([6]), tensor_shape.TensorShape([2, 3])) self.assertAllEqual([[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]], x.eval()) with self.assertRaisesRegexp(ValueError, "partially known"): ops.convert_to_tensor(tensor_shape.TensorShape(None)) with self.assertRaisesRegexp(ValueError, "partially known"): ops.convert_to_tensor(tensor_shape.TensorShape([1, None, 64])) with self.assertRaises(TypeError): ops.convert_to_tensor( tensor_shape.TensorShape([1, 2, 3]), dtype=dtypes_lib.float32) def testAsTensorForDimensionInput(self): with self.cached_session(): x = ops.convert_to_tensor(tensor_shape.TensorShape([1, 2, 3])[1]) self.assertEqual(dtypes_lib.int32, x.dtype) self.assertAllEqual(2, x.eval()) x = ops.convert_to_tensor( tensor_shape.TensorShape([1, 2, 3])[1], dtype=dtypes_lib.int64) self.assertEqual(dtypes_lib.int64, x.dtype) self.assertAllEqual(2, x.eval()) with self.assertRaisesRegexp(ValueError, "unknown Dimension"): ops.convert_to_tensor(tensor_shape.TensorShape(None)[1]) with self.assertRaisesRegexp(ValueError, "unknown Dimension"): ops.convert_to_tensor(tensor_shape.TensorShape([1, None, 64])[1]) with self.assertRaises(TypeError): ops.convert_to_tensor( tensor_shape.TensorShape([1, 2, 3])[1], dtype=dtypes_lib.float32) class IdentityOpTest(test.TestCase): def testIdTensor(self): with ops.Graph().as_default(): x = constant_op.constant(2.0, shape=[6], name="input") id_op = array_ops.identity(x, name="id") self.assertTrue(isinstance(id_op.op.inputs[0], ops.Tensor)) self.assertProtoEquals("name: 'id' op: 'Identity' input: 'input' " "attr { key: 'T' value { type: DT_FLOAT } }", id_op.op.node_def) class ZerosTest(test.TestCase): def _Zeros(self, shape): with self.cached_session(): ret = array_ops.zeros(shape) self.assertEqual(shape, ret.get_shape()) return ret.eval() def testConst(self): self.assertTrue( np.array_equal(self._Zeros([2, 3]), np.array([[0] * 3] * 2))) def testScalar(self): self.assertEqual(0, self._Zeros([])) self.assertEqual(0, self._Zeros(())) with self.cached_session(): scalar = array_ops.zeros(constant_op.constant([], dtype=dtypes_lib.int32)) self.assertEqual(0, scalar.eval()) def testDynamicSizes(self): np_ans = np.array([[0] * 3] * 2) with self.cached_session(): # Creates a tensor of 2 x 3. d = array_ops.fill([2, 3], 12., name="fill") # Constructs a tensor of zeros of the same dimensions as "d". z = array_ops.zeros(array_ops.shape(d)) out = z.eval() self.assertAllEqual(np_ans, out) self.assertShapeEqual(np_ans, d) self.assertShapeEqual(np_ans, z) def testDtype(self): with self.cached_session(): d = array_ops.fill([2, 3], 12., name="fill") self.assertEqual(d.get_shape(), [2, 3]) # Test default type for both constant size and dynamic size z = array_ops.zeros([2, 3]) self.assertEqual(z.dtype, dtypes_lib.float32) self.assertEqual([2, 3], z.get_shape()) self.assertAllEqual(z.eval(), np.zeros([2, 3])) z = array_ops.zeros(array_ops.shape(d)) self.assertEqual(z.dtype, dtypes_lib.float32) self.assertEqual([2, 3], z.get_shape()) self.assertAllEqual(z.eval(), np.zeros([2, 3])) # Test explicit type control for dtype in [ dtypes_lib.float32, dtypes_lib.float64, dtypes_lib.int32, dtypes_lib.uint8, dtypes_lib.int16, dtypes_lib.int8, dtypes_lib.complex64, dtypes_lib.complex128, dtypes_lib.int64, dtypes_lib.bool, dtypes_lib.string ]: z = array_ops.zeros([2, 3], dtype=dtype) self.assertEqual(z.dtype, dtype) self.assertEqual([2, 3], z.get_shape()) z_value = z.eval() self.assertFalse(np.any(z_value)) self.assertEqual((2, 3), z_value.shape) z = array_ops.zeros(array_ops.shape(d), dtype=dtype) self.assertEqual(z.dtype, dtype) self.assertEqual([2, 3], z.get_shape()) z_value = z.eval() self.assertFalse(np.any(z_value)) self.assertEqual((2, 3), z_value.shape) class ZerosLikeTest(test.TestCase): def _compareZeros(self, dtype, fully_defined_shape, use_gpu): with self.test_session(use_gpu=use_gpu): # Creates a tensor of non-zero values with shape 2 x 3. # NOTE(kearnes): The default numpy dtype associated with tf.string is # np.object (and can't be changed without breaking a lot things), which # causes a TypeError in constant_op.constant below. Here we catch the # special case of tf.string and set the numpy dtype appropriately. if dtype == dtypes_lib.string: numpy_dtype = np.string_ else: numpy_dtype = dtype.as_numpy_dtype if fully_defined_shape: d = constant_op.constant( np.ones((2, 3), dtype=numpy_dtype), dtype=dtype) else: d = array_ops.placeholder(dtype=dtype) # Constructs a tensor of zeros of the same dimensions and type as "d". z_var = array_ops.zeros_like(d) # Test that the type is correct self.assertEqual(z_var.dtype, dtype) # Test that the shape is correct if fully_defined_shape: self.assertEqual([2, 3], z_var.get_shape()) # Test that the value is correct feed_dict = {} if not fully_defined_shape: feed_dict[d] = np.ones((2, 3), dtype=numpy_dtype) z_value = z_var.eval(feed_dict=feed_dict) self.assertFalse(np.any(z_value)) self.assertEqual((2, 3), z_value.shape) def testZerosLikeCPU(self): for dtype in [ dtypes_lib.half, dtypes_lib.float32, dtypes_lib.float64, dtypes_lib.int8, dtypes_lib.uint8, dtypes_lib.int16, dtypes_lib.uint16, dtypes_lib.int32, dtypes_lib.int64, dtypes_lib.bool, dtypes_lib.complex64, dtypes_lib.complex128, dtypes_lib.string ]: self._compareZeros(dtype, fully_defined_shape=False, use_gpu=False) self._compareZeros(dtype, fully_defined_shape=True, use_gpu=False) def testZerosLikeGPU(self): for dtype in [ dtypes_lib.half, dtypes_lib.float32, dtypes_lib.float64, dtypes_lib.int32, dtypes_lib.int64, dtypes_lib.complex64, dtypes_lib.complex128, dtypes_lib.bool ]: self._compareZeros(dtype, fully_defined_shape=False, use_gpu=True) self._compareZeros(dtype, fully_defined_shape=True, use_gpu=True) def testZerosLikePartialShape(self): d = array_ops.placeholder(dtypes_lib.float32, shape=[None, 4, None]) z = array_ops.zeros_like(d) self.assertEqual(d.get_shape().as_list(), z.get_shape().as_list()) def testZerosLikeDtype(self): # Make sure zeros_like works even for dtypes that cannot be cast between with self.cached_session(): shape = (3, 5) dtypes = np.float32, np.complex64 for in_type in dtypes: x = np.arange(15).astype(in_type).reshape(*shape) for out_type in dtypes: y = array_ops.zeros_like(x, dtype=out_type).eval() self.assertEqual(y.dtype, out_type) self.assertEqual(y.shape, shape) self.assertAllEqual(y, np.zeros(shape, dtype=out_type)) def testZerosLikeVariant(self): # TODO(ebrevdo): Re-enable use_gpu=True once non-DMA Variant # copying between CPU and GPU is supported AND we register a # ZerosLike callback for GPU for Variant storing primitive types # in variant_op_registry.cc. with self.test_session(use_gpu=False): variant_tensor = tensor_pb2.TensorProto( dtype=dtypes_lib.variant.as_datatype_enum, tensor_shape=tensor_shape.TensorShape([]).as_proto(), variant_val=[ tensor_pb2.VariantTensorDataProto( # Match registration in variant_op_registry.cc type_name=b"int", metadata=np.array(1, dtype=np.int32).tobytes()) ]) const_variant = constant_op.constant(variant_tensor) zeros_like = array_ops.zeros_like(const_variant) zeros_like_op = logging_ops.Print( zeros_like, [const_variant, zeros_like], message="Variant storing an int, input and output of zeros_like:").op # Smoke test -- ensure this executes without trouble. # Right now, non-numpy-compatible objects cannot be returned from a # session.run call; similarly, objects that can't be converted to # native numpy types cannot be passed to ops.convert_to_tensor. # TODO(ebrevdo): Add registration mechanism for # ops.convert_to_tensor and for session.run output. zeros_like_op.run() class OnesTest(test.TestCase): def _Ones(self, shape): with self.cached_session(): ret = array_ops.ones(shape) self.assertEqual(shape, ret.get_shape()) return ret.eval() def testConst(self): self.assertTrue(np.array_equal(self._Ones([2, 3]), np.array([[1] * 3] * 2))) def testScalar(self): self.assertEqual(1, self._Ones([])) self.assertEqual(1, self._Ones(())) with self.cached_session(): scalar = array_ops.ones(constant_op.constant([], dtype=dtypes_lib.int32)) self.assertEqual(1, scalar.eval()) def testDynamicSizes(self): np_ans = np.array([[1] * 3] * 2) with self.cached_session(): # Creates a tensor of 2 x 3. d = array_ops.fill([2, 3], 12., name="fill") # Constructs a tensor of ones of the same dimensions as "d". z = array_ops.ones(array_ops.shape(d)) out = z.eval() self.assertAllEqual(np_ans, out) self.assertShapeEqual(np_ans, d) self.assertShapeEqual(np_ans, z) def testAutoPack(self): with self.cached_session(): h = array_ops.placeholder(dtypes_lib.int32, shape=[]) w = array_ops.placeholder(dtypes_lib.int32, shape=[]) z = array_ops.ones([h, w]) out = z.eval(feed_dict={h: 4, w: 16}) self.assertAllEqual(out, np.array([[1] * 16] * 4)) def testDtype(self): with self.cached_session(): d = array_ops.fill([2, 3], 12., name="fill") self.assertEqual(d.get_shape(), [2, 3]) # Test default type for both constant size and dynamic size z = array_ops.ones([2, 3]) self.assertEqual(z.dtype, dtypes_lib.float32) self.assertEqual([2, 3], z.get_shape()) self.assertAllEqual(z.eval(), np.ones([2, 3])) z = array_ops.ones(array_ops.shape(d)) self.assertEqual(z.dtype, dtypes_lib.float32) self.assertEqual([2, 3], z.get_shape()) self.assertAllEqual(z.eval(), np.ones([2, 3])) # Test explicit type control for dtype in (dtypes_lib.float32, dtypes_lib.float64, dtypes_lib.int32, dtypes_lib.uint8, dtypes_lib.int16, dtypes_lib.int8, dtypes_lib.complex64, dtypes_lib.complex128, dtypes_lib.int64, dtypes_lib.bool): z = array_ops.ones([2, 3], dtype=dtype) self.assertEqual(z.dtype, dtype) self.assertEqual([2, 3], z.get_shape()) self.assertAllEqual(z.eval(), np.ones([2, 3])) z = array_ops.ones(array_ops.shape(d), dtype=dtype) self.assertEqual(z.dtype, dtype) self.assertEqual([2, 3], z.get_shape()) self.assertAllEqual(z.eval(), np.ones([2, 3])) class OnesLikeTest(test.TestCase): def testOnesLike(self): for dtype in [ dtypes_lib.float32, dtypes_lib.float64, dtypes_lib.int8, dtypes_lib.uint8, dtypes_lib.int16, dtypes_lib.uint16, dtypes_lib.int32, dtypes_lib.int64, dtypes_lib.bool, dtypes_lib.complex64, dtypes_lib.complex128 ]: numpy_dtype = dtype.as_numpy_dtype with self.cached_session(): # Creates a tensor of non-zero values with shape 2 x 3. d = constant_op.constant( np.ones( (2, 3), dtype=numpy_dtype), dtype=dtype) # Constructs a tensor of zeros of the same dimensions and type as "d". z_var = array_ops.ones_like(d) # Test that the type is correct self.assertEqual(z_var.dtype, dtype) z_value = z_var.eval() # Test that the value is correct self.assertTrue(np.array_equal(z_value, np.array([[1] * 3] * 2))) self.assertEqual([2, 3], z_var.get_shape()) def testOnesLikePartialShape(self): d = array_ops.placeholder(dtypes_lib.float32, shape=[None, 4, None]) z = array_ops.ones_like(d) self.assertEqual(d.get_shape().as_list(), z.get_shape().as_list()) class FillTest(test.TestCase): def _compare(self, dims, val, np_ans, use_gpu): with self.test_session(use_gpu=use_gpu): tf_ans = array_ops.fill(dims, val, name="fill") out = tf_ans.eval() self.assertAllClose(np_ans, out) # Fill does not set the shape. # self.assertShapeEqual(np_ans, tf_ans) def _compareAll(self, dims, val, np_ans): self._compare(dims, val, np_ans, False) self._compare(dims, val, np_ans, True) def testFillFloat(self): np_ans = np.array([[3.1415] * 3] * 2).astype(np.float32) self._compareAll([2, 3], np_ans[0][0], np_ans) def testFillDouble(self): np_ans = np.array([[3.1415] * 3] * 2).astype(np.float64) self._compareAll([2, 3], np_ans[0][0], np_ans) def testFillInt32(self): np_ans = np.array([[42] * 3] * 2).astype(np.int32) self._compareAll([2, 3], np_ans[0][0], np_ans) def testFillInt64(self): np_ans = np.array([[-42] * 3] * 2).astype(np.int64) self._compareAll([2, 3], np_ans[0][0], np_ans) def testFillComplex64(self): np_ans = np.array([[0.15 + 0.3j] * 3] * 2).astype(np.complex64) self._compareAll([2, 3], np_ans[0][0], np_ans) def testFillComplex128(self): np_ans = np.array([[0.15 + 0.3j] * 3] * 2).astype(np.complex128) self._compareAll([2, 3], np_ans[0][0], np_ans) def testFillString(self): np_ans = np.array([[b"yolo"] * 3] * 2) with self.test_session(use_gpu=False): tf_ans = array_ops.fill([2, 3], np_ans[0][0], name="fill").eval() self.assertAllEqual(np_ans, tf_ans) def testFillNegative(self): with self.cached_session(): for shape in (-1,), (2, -1), (-1, 2), (-2), (-3): with self.assertRaises(ValueError): array_ops.fill(shape, 7) # Using a placeholder so this won't be caught in static analysis. dims = array_ops.placeholder(dtypes_lib.int32) fill_t = array_ops.fill(dims, 3.0) for shape in (-1,), (2, -1), (-1, 2), (-2), (-3): with self.assertRaises(errors_impl.InvalidArgumentError): fill_t.eval({dims: shape}) def testShapeFunctionEdgeCases(self): # Non-vector dimensions. with self.assertRaises(ValueError): array_ops.fill([[0, 1], [2, 3]], 1.0) # Non-scalar value. with self.assertRaises(ValueError): array_ops.fill([3, 2], [1.0, 2.0]) # Partial dimension information. f = array_ops.fill(array_ops.placeholder(dtypes_lib.int32, shape=(4,)), 3.0) self.assertEqual([None, None, None, None], f.get_shape().as_list()) f = array_ops.fill( [array_ops.placeholder( dtypes_lib.int32, shape=()), 17], 1.0) self.assertEqual([None, 17], f.get_shape().as_list()) def testGradient(self): with self.cached_session(): in_v = constant_op.constant(5.0) out_shape = [3, 2] out_filled = array_ops.fill(out_shape, in_v) err = gradient_checker.compute_gradient_error(in_v, [], out_filled, out_shape) self.assertLess(err, 1e-3) class PlaceholderTest(test.TestCase): def testDtype(self): with self.cached_session(): p = array_ops.placeholder(dtypes_lib.float32, shape=(10, 10), name="p") p_identity = array_ops.identity(p) feed_array = np.random.rand(10, 10) self.assertAllClose( p_identity.eval(feed_dict={p: feed_array}), feed_array) with self.assertRaisesOpError( "must feed a value for placeholder tensor 'p' with dtype float"): p_identity.eval() def testShape(self): with self.cached_session(): p = array_ops.placeholder(dtypes_lib.float32, shape=(10, 10), name="p") p_identity = array_ops.identity(p) feed_array = np.random.rand(10, 10) self.assertAllClose( p_identity.eval(feed_dict={p: feed_array}), feed_array) with self.assertRaisesOpError( "must feed a value for placeholder tensor 'p' with dtype float and " r"shape \[10,10\]"): p_identity.eval() with self.assertRaisesWithPredicateMatch( ValueError, lambda e: "Cannot feed value of shape" in str(e)): p_identity.eval(feed_dict={p: feed_array[:5, :5]}) def testUnknownShape(self): with self.cached_session(): p = array_ops.placeholder(dtypes_lib.float32, shape=None, name="p") p_identity = array_ops.identity(p) # can feed anything feed_array = np.random.rand(10, 3) self.assertAllClose( p_identity.eval(feed_dict={p: feed_array}), feed_array) feed_array = np.random.rand(4, 2, 5) self.assertAllClose( p_identity.eval(feed_dict={p: feed_array}), feed_array) def testScalarShape(self): with self.cached_session(): p = array_ops.placeholder(dtypes_lib.float32, shape=[], name="p") p_identity = array_ops.identity(p) self.assertAllClose(p_identity.eval(feed_dict={p: 5}), 5) def testPartialShape(self): with self.cached_session(): p = array_ops.placeholder(dtypes_lib.float32, shape=[None, 3], name="p") p_identity = array_ops.identity(p) feed_array = np.random.rand(10, 3) self.assertAllClose( p_identity.eval(feed_dict={p: feed_array}), feed_array) with self.assertRaisesWithPredicateMatch( ValueError, lambda e: "Cannot feed value of shape" in str(e)): p_identity.eval(feed_dict={p: feed_array[:5, :2]}) def testPartialShapeWhenNotFed(self): with self.cached_session(): p = array_ops.placeholder(dtypes_lib.float32, shape=[None, 3], name="p") p_identity = array_ops.identity(p) # Should trigger an operator error, not a shape error. with self.assertRaisesOpError( "must feed a value for placeholder tensor 'p' with dtype float"): p_identity.eval() def testControlDependency(self): with self.cached_session(): p = array_ops.placeholder(dtypes_lib.int32, shape=[], name="p") with ops.control_dependencies([p]): c = constant_op.constant(5, dtypes_lib.int32) d = math_ops.multiply(p, c) val = np.array(2).astype(np.int) self.assertEqual(10, d.eval(feed_dict={p: val})) def testBadShape(self): with self.assertRaises(ValueError): array_ops.placeholder(dtypes_lib.float32, shape=(-1, 10)) def testTensorStr(self): a = array_ops.placeholder(dtypes_lib.float32, shape=None, name="a") self.assertEqual(" dtype=float32>", repr(a)) b = array_ops.placeholder(dtypes_lib.int32, shape=(32, 40), name="b") self.assertEqual("", repr(b)) c = array_ops.placeholder(dtypes_lib.qint32, shape=(32, None, 2), name="c") self.assertEqual("", repr(c)) def testOldGraph(self): # Load graph generated from earlier version of TF where # placeholder shape was not set. # # a = tf.placeholder(tf.float32) # b = a + 1.0 # # Older graph's default shape is 'shape {}', not 'shape { # unknown_rank: true }' graph = """ node { name: "Placeholder" op: "Placeholder" attr { key: "dtype" value { type: DT_FLOAT } } attr { key: "shape" value { shape { } } } } node { name: "add/y" op: "Const" attr { key: "dtype" value { type: DT_FLOAT } } attr { key: "value" value { tensor { dtype: DT_FLOAT tensor_shape { } float_val: 1.0 } } } } node { name: "add" op: "Add" input: "Placeholder" input: "add/y" attr { key: "T" value { type: DT_FLOAT } } } versions { producer: 21 } """ gdef = graph_pb2.GraphDef() text_format.Merge(graph, gdef) with self.cached_session(): p, ret = importer.import_graph_def( gdef, return_elements=["Placeholder:0", "add:0"]) # Feed in a vector of two elements. Since the producer version # of 21, a shape of {} is interpreted as "any shape". If # producer version were 22, then we'd get a shape mismatch # error. self.assertAllEqual([2.0, 3.0], ret.eval(feed_dict={p: [1.0, 2.0]})) class PlaceholderWithDefaultTest(test.TestCase): def testFullShape(self): with self.test_session(force_gpu=test_util.is_gpu_available()): p = array_ops.placeholder_with_default([[2, 2], [2, 2]], shape=[2, 2]) a = array_ops.identity(p) self.assertAllEqual([[2, 2], [2, 2]], a.eval()) self.assertAllEqual( [[3, 3], [3, 3]], a.eval(feed_dict={p: [[3, 3], [3, 3]]})) with self.assertRaises(ValueError): a.eval(feed_dict={p: [[6, 6, 6], [6, 6, 6]]}) def testPartialShape(self): with self.test_session(force_gpu=test_util.is_gpu_available()): p = array_ops.placeholder_with_default([1, 2, 3], shape=[None]) a = array_ops.identity(p) self.assertAllEqual([1, 2, 3], a.eval()) self.assertAllEqual([3, 37], a.eval(feed_dict={p: [3, 37]})) with self.assertRaises(ValueError): a.eval(feed_dict={p: [[2, 2], [2, 2]]}) def testNoShape(self): with self.test_session(force_gpu=test_util.is_gpu_available()): p = array_ops.placeholder_with_default([17], shape=None) a = array_ops.identity(p) self.assertAllEqual([17], a.eval()) self.assertAllEqual([3, 37], a.eval(feed_dict={p: [3, 37]})) self.assertAllEqual( [[3, 3], [3, 3]], a.eval(feed_dict={p: [[3, 3], [3, 3]]})) def testGradient(self): with self.test_session(force_gpu=test_util.is_gpu_available()): x = array_ops.placeholder(dtypes_lib.float32, [5, 7]) y = array_ops.placeholder_with_default(x, None) err = gradient_checker.compute_gradient_error(x, [5, 7], y, [5, 7]) self.assertLess(err, 1e-3) if __name__ == "__main__": test.main()