def testArrayViewSlicingDownNumericTensorToOneElement(self): x = np.array([[1.1, 2.2, np.inf], [-np.inf, 3.3, np.nan]], dtype=np.float32) dtype, shape, data = tensor_helper.array_view(x, slicing='[0,0]') self.assertEqual('float32', dtype) self.assertEqual(tuple(), shape) self.assertTrue(np.allclose(1.1, data))
def query(self, time_indices): """Query the values at given time indices. Args: time_indices: 0-based time indices to query, as a `list` of `int`. Returns: Values as a list of `numpy.ndarray` (for time indices in memory) or `None` (for time indices discarded). """ if self._disposed: raise ValueError( 'Cannot query: this _WatchStore instance is already disposed') if not isinstance(time_indices, (tuple, list)): time_indices = [time_indices] output = [] for time_index in time_indices: if isinstance(self._data[time_index], _TensorValueDiscarded): output.append(None) else: data_item = self._data[time_index] if (hasattr(data_item, 'dtype') and tensor_helper.translate_dtype(data_item.dtype) == 'string'): _, _, data_item = tensor_helper.array_view(data_item) data_item = np.array( tensor_helper.process_buffers_for_display(data_item), dtype=np.object) output.append(data_item) return output
def query(self, watch_key, time_indices=None, slicing=None, mapping=None): """Query tensor store for a given watch_key. Args: watch_key: The watch key to query. time_indices: A numpy-style slicing string for time indices. E.g., `-1`, `:-2`, `[::2]`. If not provided (`None`), will use -1. slicing: A numpy-style slicing string for individual time steps. mapping: An mapping string or a list of them. Supported mappings: `{None, 'image/png', 'health-pill'}`. Returns: The potentially sliced values as a nested list of values or its mapped format. A `list` of nested `list` of values. Raises: ValueError: If the shape of the sliced array is incompatible with mapping mode. Or if the mapping type is invalid. """ if watch_key not in self._tensor_data: raise KeyError("watch_key not found: %s" % watch_key) if time_indices is None: time_indices = "-1" time_slicing = tensor_helper.parse_time_indices(time_indices) all_time_indices = list(range(self._tensor_data[watch_key].num_total())) sliced_time_indices = all_time_indices[time_slicing] if not isinstance(sliced_time_indices, list): sliced_time_indices = [sliced_time_indices] recombine_and_map = False step_mapping = mapping if len(sliced_time_indices) > 1 and mapping not in (None,): recombine_and_map = True step_mapping = None output = [] for index in sliced_time_indices: value = self._tensor_data[watch_key].query(index)[0] if value is not None and not isinstance( value, debug_data.InconvertibleTensorProto ): output.append( tensor_helper.array_view( value, slicing=slicing, mapping=step_mapping )[2] ) else: output.append(None) if recombine_and_map: if mapping == "image/png": output = tensor_helper.array_to_base64_png(output) elif mapping and mapping != "none": logger.warn( "Unsupported mapping mode after recomining time steps: %s", mapping, ) return output
def testArrayViewOnScalarString(self): # Construct a numpy scalar that corresponds to a TensorFlow string tensor # value. x = np.array('foo', dtype=np.object) dtype, shape, data = tensor_helper.array_view(x) self.assertEqual('string', dtype) self.assertEqual(tuple(), shape) self.assertEqual('foo', data)
def query(self, watch_key, time_indices=None, slicing=None, mapping=None): """Query tensor store for a given watch_key. Args: watch_key: The watch key to query. time_indices: A numpy-style slicing string for time indices. E.g., `-1`, `:-2`, `[::2]`. If not provided (`None`), will use -1. slicing: A numpy-style slicing string for individual time steps. mapping: An mapping string or a list of them. Supported mappings: `{None, 'image/png', 'health-pill'}`. Returns: The potentially sliced values as a nested list of values or its mapped format. A `list` of nested `list` of values. Raises: ValueError: If the shape of the sliced array is incompatible with mapping mode. Or if the mapping type is invalid. """ if watch_key not in self._tensor_data: raise KeyError("watch_key not found: %s" % watch_key) if time_indices is None: time_indices = '-1' time_slicing = tensor_helper.parse_time_indices(time_indices) all_time_indices = list(range(self._tensor_data[watch_key].num_total())) sliced_time_indices = all_time_indices[time_slicing] if not isinstance(sliced_time_indices, list): sliced_time_indices = [sliced_time_indices] recombine_and_map = False step_mapping = mapping if len(sliced_time_indices) > 1 and mapping not in (None, ): recombine_and_map = True step_mapping = None output = [] for index in sliced_time_indices: value = self._tensor_data[watch_key].query(index)[0] if (value is not None and not isinstance(value, debug_data.InconvertibleTensorProto)): output.append(tensor_helper.array_view( value, slicing=slicing, mapping=step_mapping)[2]) else: output.append(None) if recombine_and_map: if mapping == 'image/png': output = tensor_helper.array_to_base64_png(output) elif mapping and mapping != 'none': tf.logging.warn( 'Unsupported mapping mode after recomining time steps: %s', mapping) return output
def testImagePngMappingWorksForArrayWithOnlyOneElement(self): x = np.array([[-42]], dtype=np.int16) dtype, shape, data = tensor_helper.array_view(x, mapping="image/png") self.assertEqual("int16", dtype) self.assertEqual((1, 1), shape) decoded_x = im_util.decode_png(base64.b64decode(data)) self.assertEqual((1, 1, 3), decoded_x.shape) self.assertEqual(np.uint8, decoded_x.dtype) self.assertAllClose(np.zeros([1, 1, 3]), decoded_x)
def testArrayViewSlicingStringTensorToScalar(self): # Construct a numpy array that corresponds to a TensorFlow string tensor # value. x = np.array([['foo', 'bar', 'qux'], ['baz', 'corge', 'grault']], dtype=np.object) dtype, shape, data = tensor_helper.array_view(x, slicing='[1, 1]') self.assertEqual('string', dtype) self.assertEqual((1, 1), shape) self.assertEqual([['corge']], data)
def testArrayView2DWithSlicingAndImagePngMapping(self): x = np.ones([15, 16], dtype=np.int32) dtype, shape, data = tensor_helper.array_view(x, slicing="[:15:3, :16:2]", mapping="image/png") self.assertEqual("int32", dtype) self.assertEqual((5, 8), shape) decoded_x = im_util.decode_png(base64.b64decode(data)) self.assertEqual((5, 8, 3), decoded_x.shape)
def testArrayViewSlicingStringTensorToScalar(self): # Construct a numpy array that corresponds to a TensorFlow string tensor # value. x = np.array([["foo", "bar", "qux"], ["baz", "corge", "grault"]], dtype=np.object) dtype, shape, data = tensor_helper.array_view(x, slicing="[1, 1]") self.assertEqual("string", dtype) self.assertEqual((1, 1), shape) self.assertEqual([["corge"]], data)
def testArrayView2DWithSlicingAndImagePngMapping(self): x = np.ones([15, 16], dtype=np.int32) dtype, shape, data = tensor_helper.array_view( x, slicing="[:15:3, :16:2]", mapping="image/png") self.assertEqual("int32", dtype) self.assertEqual((5, 8), shape) decoded_x = im_util.decode_png(base64.b64decode(data)) self.assertEqual((5, 8, 3), decoded_x.shape) self.assertEqual(np.uint8, decoded_x.dtype) self.assertAllClose(np.zeros([5, 8, 3]), decoded_x)
def _comm_tensor_data(device_name, node_name, maybe_base_expanded_node_name, output_slot, debug_op, tensor_value, wall_time): """Create a dict() as the outgoing data in the tensor data comm route. Args: device_name: Name of the device that the tensor is on. node_name: (Original) name of the node that produces the tensor. maybe_base_expanded_node_name: Possbily base-expanded node name. output_slot: Output slot number. debug_op: Name of the debug op. tensor_value: Value of the tensor, as a numpy.ndarray. wall_time: Wall timestamp for the tensor. Returns: A dict representing the tensor data. """ output_slot = int(output_slot) tf.logging.info( 'Recording tensor value: %s, %d, %s', node_name, output_slot, debug_op) tensor_values = None if isinstance(tensor_value, debug_data.InconvertibleTensorProto): if not tensor_value.initialized: tensor_dtype = UNINITIALIZED_TAG tensor_shape = UNINITIALIZED_TAG else: tensor_dtype = UNSUPPORTED_TAG tensor_dtype = UNSUPPORTED_TAG tensor_values = NA_TAG else: tensor_dtype = str(tensor_value.dtype) tensor_shape = tensor_value.shape # The /comm endpoint should respond with tensor values only if the tensor is # small enough. Otherwise, the detailed values sould be queried through a # dedicated tensor_data that supports slicing. if tensor_helper.numel(tensor_shape) < 5: _, _, tensor_values = tensor_helper.array_view(tensor_value) return { 'type': 'tensor', 'timestamp': wall_time, 'data': { 'device_name': device_name, 'node_name': node_name, 'maybe_base_expanded_node_name': maybe_base_expanded_node_name, 'output_slot': output_slot, 'debug_op': debug_op, 'dtype': tensor_dtype, 'shape': tensor_shape, 'values': tensor_values, }, }
def testArrayViewFloat2DWithSlicing(self): x = np.ones([4, 4], dtype=np.float64) y = np.zeros([4, 4], dtype=np.float64) float_array = np.concatenate((x, y), axis=1) dtype, shape, values = tensor_helper.array_view(float_array, slicing="[2:, :]") self.assertEqual("float64", dtype) self.assertEqual((2, 8), shape) self.assertAllClose( [[1, 1, 1, 1, 0, 0, 0, 0], [1, 1, 1, 1, 0, 0, 0, 0]], values)
def testArrayViewInt3DWithSlicing(self): x = np.ones([4, 4], dtype=np.int32) int_array = np.zeros([3, 4, 4], dtype=np.int32) int_array[0, ...] = x int_array[1, ...] = 2 * x int_array[2, ...] = 3 * x dtype, shape, values = tensor_helper.array_view( int_array, slicing="[:, :, 2]") self.assertEqual("int32", dtype) self.assertEqual((3, 4), shape) self.assertEqual([[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]], values)
def testArrayViewFloat2DWithSlicing(self): x = np.ones([4, 4], dtype=np.float64) y = np.zeros([4, 4], dtype=np.float64) float_array = np.concatenate((x, y), axis=1) dtype, shape, values = tensor_helper.array_view( float_array, slicing="[2:, :]") self.assertEqual("float64", dtype) self.assertEqual((2, 8), shape) self.assertAllClose( [[1, 1, 1, 1, 0, 0, 0, 0], [1, 1, 1, 1, 0, 0, 0, 0]], values)
def testArrayViewInt3DWithSlicing(self): x = np.ones([4, 4], dtype=np.int32) int_array = np.zeros([3, 4, 4], dtype=np.int32) int_array[0, ...] = x int_array[1, ...] = 2 * x int_array[2, ...] = 3 * x dtype, shape, values = tensor_helper.array_view(int_array, slicing="[:, :, 2]") self.assertEqual("int32", dtype) self.assertEqual((3, 4), shape) self.assertEqual([[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]], values)
def testImagePngMappingWorksForArrayWithOnlyInfAndNaN(self): x = np.array([[np.nan, -np.inf], [np.inf, np.nan]], dtype=np.float32) dtype, shape, data = tensor_helper.array_view(x, mapping="image/png") self.assertEqual("float32", dtype) self.assertEqual((2, 2), shape) decoded_x = im_util.decode_png(base64.b64decode(data)) self.assertEqual((2, 2, 3), decoded_x.shape) self.assertEqual(np.uint8, decoded_x.dtype) self.assertAllClose(tensor_helper.NAN_RGB, decoded_x[0, 0, :]) # nan. self.assertAllClose(tensor_helper.NEGATIVE_INFINITY_RGB, decoded_x[0, 1, :]) # -infinity. self.assertAllClose(tensor_helper.POSITIVE_INFINITY_RGB, decoded_x[1, 0, :]) # +infinity. self.assertAllClose(tensor_helper.NAN_RGB, decoded_x[1, 1, :]) # nan.
def testImagePngMappingRaisesExceptionForEmptyArray(self): x = np.zeros([0, 0]) with six.assertRaisesRegex( self, ValueError, r"Cannot encode an empty array .* \(0, 0\)"): tensor_helper.array_view(x, mapping="image/png")
def testArrayViewFloat2DNoSlicing(self): float_array = np.ones([3, 3], dtype=np.float32) dtype, shape, values = tensor_helper.array_view(float_array) self.assertEqual("float32", dtype) self.assertEqual((3, 3), shape) self.assertEqual(float_array.tolist(), values)
def _comm_tensor_data(device_name, node_name, maybe_base_expanded_node_name, output_slot, debug_op, tensor_value, wall_time): """Create a dict() as the outgoing data in the tensor data comm route. Note: The tensor data in the comm route does not include the value of the tensor in its entirety in general. Only if a tensor satisfies the following conditions will its entire value be included in the return value of this method: 1. Has a numeric data type (e.g., float32, int32) and has fewer than 5 elements. 2. Is a string tensor and has fewer than 5 elements. Each string element is up to 40 bytes. Args: device_name: Name of the device that the tensor is on. node_name: (Original) name of the node that produces the tensor. maybe_base_expanded_node_name: Possbily base-expanded node name. output_slot: Output slot number. debug_op: Name of the debug op. tensor_value: Value of the tensor, as a numpy.ndarray. wall_time: Wall timestamp for the tensor. Returns: A dict representing the tensor data. """ output_slot = int(output_slot) tf.logging.info( 'Recording tensor value: %s, %d, %s', node_name, output_slot, debug_op) tensor_values = None if isinstance(tensor_value, debug_data.InconvertibleTensorProto): if not tensor_value.initialized: tensor_dtype = UNINITIALIZED_TAG tensor_shape = UNINITIALIZED_TAG else: tensor_dtype = UNSUPPORTED_TAG tensor_shape = UNSUPPORTED_TAG tensor_values = NA_TAG else: tensor_dtype = tensor_helper.translate_dtype(tensor_value.dtype) tensor_shape = tensor_value.shape # The /comm endpoint should respond with tensor values only if the tensor is # small enough. Otherwise, the detailed values sould be queried through a # dedicated tensor_data that supports slicing. if tensor_helper.numel(tensor_shape) < 5: _, _, tensor_values = tensor_helper.array_view(tensor_value) if tensor_dtype == 'string' and tensor_value is not None: tensor_values = tensor_helper.process_buffers_for_display( tensor_values, limit=STRING_ELEMENT_MAX_LEN) return { 'type': 'tensor', 'timestamp': wall_time, 'data': { 'device_name': device_name, 'node_name': node_name, 'maybe_base_expanded_node_name': maybe_base_expanded_node_name, 'output_slot': output_slot, 'debug_op': debug_op, 'dtype': tensor_dtype, 'shape': tensor_shape, 'values': tensor_values, }, }
def _comm_tensor_data(device_name, node_name, maybe_base_expanded_node_name, output_slot, debug_op, tensor_value, wall_time): """Create a dict() as the outgoing data in the tensor data comm route. Note: The tensor data in the comm route does not include the value of the tensor in its entirety in general. Only if a tensor satisfies the following conditions will its entire value be included in the return value of this method: 1. Has a numeric data type (e.g., float32, int32) and has fewer than 5 elements. 2. Is a string tensor and has fewer than 5 elements. Each string element is up to 40 bytes. Args: device_name: Name of the device that the tensor is on. node_name: (Original) name of the node that produces the tensor. maybe_base_expanded_node_name: Possbily base-expanded node name. output_slot: Output slot number. debug_op: Name of the debug op. tensor_value: Value of the tensor, as a numpy.ndarray. wall_time: Wall timestamp for the tensor. Returns: A dict representing the tensor data. """ output_slot = int(output_slot) tf.logging.info('Recording tensor value: %s, %d, %s', node_name, output_slot, debug_op) tensor_values = None if isinstance(tensor_value, debug_data.InconvertibleTensorProto): if not tensor_value.initialized: tensor_dtype = UNINITIALIZED_TAG tensor_shape = UNINITIALIZED_TAG else: tensor_dtype = UNSUPPORTED_TAG tensor_shape = UNSUPPORTED_TAG tensor_values = NA_TAG else: tensor_dtype = tensor_helper.translate_dtype(tensor_value.dtype) tensor_shape = tensor_value.shape # The /comm endpoint should respond with tensor values only if the tensor is # small enough. Otherwise, the detailed values sould be queried through a # dedicated tensor_data that supports slicing. if tensor_helper.numel(tensor_shape) < 5: _, _, tensor_values = tensor_helper.array_view(tensor_value) if tensor_dtype == 'string' and tensor_value is not None: tensor_values = tensor_helper.process_buffers_for_display( tensor_values, limit=STRING_ELEMENT_MAX_LEN) return { 'type': 'tensor', 'timestamp': wall_time, 'data': { 'device_name': device_name, 'node_name': node_name, 'maybe_base_expanded_node_name': maybe_base_expanded_node_name, 'output_slot': output_slot, 'debug_op': debug_op, 'dtype': tensor_dtype, 'shape': tensor_shape, 'values': tensor_values, }, }