1# Copyright 2016 The TensorFlow Authors. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# ============================================================================== 15"""Unit tests for tensor formatter.""" 16import re 17 18import numpy as np 19 20from tensorflow.core.framework import tensor_pb2 21from tensorflow.core.framework import tensor_shape_pb2 22from tensorflow.core.framework import types_pb2 23from tensorflow.python.debug.cli import cli_test_utils 24from tensorflow.python.debug.cli import tensor_format 25from tensorflow.python.debug.lib import debug_data 26from tensorflow.python.framework import test_util 27from tensorflow.python.platform import googletest 28 29 30class RichTextLinesTest(test_util.TensorFlowTestCase): 31 32 def setUp(self): 33 np.set_printoptions( 34 precision=8, threshold=1000, edgeitems=3, linewidth=75) 35 36 def _checkTensorMetadata(self, tensor, annotations): 37 self.assertEqual( 38 {"dtype": tensor.dtype, "shape": tensor.shape}, 39 annotations["tensor_metadata"]) 40 41 # Regular expression for text representation of float numbers, possibly in 42 # engineering notation. 43 _ELEMENT_REGEX = re.compile( 44 r"([+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?|nan|inf|-inf)") 45 46 def _checkBeginIndicesAnnotations(self, out, a): 47 """Check the beginning-index annotations of an ndarray representation. 48 49 Args: 50 out: An instance of RichTextLines representing a numpy.ndarray. 51 a: The numpy.ndarray being represented. 52 53 Raises: 54 ValueError: if any ellipses ("...") are found in the lines representing 55 the array. 56 """ 57 begin_line_num = 0 58 while not out.lines[begin_line_num].startswith("array"): 59 begin_line_num += 1 60 element_index = 0 61 for line_num in range(begin_line_num, len(out.lines)): 62 line = out.lines[line_num] 63 if "..." in line: 64 raise ValueError("Unexpected found ellipses in line representing array") 65 matches = re.finditer(self._ELEMENT_REGEX, line) 66 for line_item_index, _ in enumerate(matches): 67 subscripts = list(np.unravel_index(element_index, a.shape)) 68 if line_item_index == 0: 69 self.assertEqual({tensor_format.BEGIN_INDICES_KEY: subscripts}, 70 out.annotations[line_num]) 71 element_index += 1 72 self.assertEqual(element_index, np.size(a)) 73 74 def _checkTensorElementLocations(self, out, a): 75 """Check the results of locate_tensor_element on an ndarray representation. 76 77 that represents a numpy.ndarray. 78 79 Args: 80 out: An instance of RichTextLines representing a numpy.ndarray. 81 a: The numpy.ndarray being represented. 82 83 Raises: 84 ValueError: if any ellipses ("...") are found in the lines representing 85 the array. 86 """ 87 # First, locate the beginning of the tensor value section. 88 begin_line_num = 0 89 while not out.lines[begin_line_num].startswith("array"): 90 begin_line_num += 1 91 # Second, find all matches to tensor-value regex. 92 element_index = 0 93 for line_num in range(begin_line_num, len(out.lines)): 94 line = out.lines[line_num] 95 if "..." in line: 96 raise ValueError("Unexpected found ellipses in line representing array") 97 matches = re.finditer(self._ELEMENT_REGEX, line) 98 for match in matches: 99 subscripts = list(np.unravel_index(element_index, a.shape)) 100 is_omitted, row, start_col, end_col = ( 101 tensor_format.locate_tensor_element(out, subscripts)) 102 self.assertFalse(is_omitted) 103 self.assertEqual(line_num, row) 104 self.assertEqual(match.start(), start_col) 105 self.assertEqual(match.end(), end_col) 106 element_index += 1 107 self.assertEqual(element_index, np.size(a)) 108 109 def _findFirst(self, lines, string): 110 """Find first occurrence of a string in a list of strings.""" 111 for i, line in enumerate(lines): 112 find_index = line.find(string) 113 if find_index >= 0: 114 return i, find_index 115 116 def _extractBoldNumbers(self, out, start_line): 117 """Extract all numbers that have the bold font attribute. 118 119 Args: 120 out: An instance of RichTextLines. 121 start_line: 0-based index to start from. 122 123 Returns: 124 A list of floats. 125 """ 126 floats = [] 127 for i in range(start_line, len(out.lines)): 128 if i not in out.font_attr_segs: 129 continue 130 line_attrs = out.font_attr_segs[i] 131 for begin, end, attr_value in line_attrs: 132 if attr_value == "bold": 133 floats.append(float(out.lines[i][begin:end])) 134 return floats 135 136 def testFormatZeroDimensionTensor(self): 137 a = np.array(42, dtype=np.int32) 138 139 out = tensor_format.format_tensor(a, "a") 140 141 cli_test_utils.assert_lines_equal_ignoring_whitespace( 142 self, ["Tensor \"a\":", ""], out.lines[:2]) 143 self.assertTrue(out.lines[2].startswith("array(42")) 144 self._checkTensorMetadata(a, out.annotations) 145 146 def testFormatTensorHighlightsTensorNameWithoutDebugOp(self): 147 tensor_name = "a_tensor:0" 148 a = np.zeros(2) 149 out = tensor_format.format_tensor( 150 a, tensor_name, np_printoptions={"linewidth": 40}) 151 self.assertEqual([(8, 8 + len(tensor_name), "bold")], out.font_attr_segs[0]) 152 153 def testFormatTensorHighlightsTensorNameWithDebugOp(self): 154 tensor_name = "a_tensor:0" 155 debug_op = "DebugIdentity" 156 a = np.zeros(2) 157 out = tensor_format.format_tensor( 158 a, "%s:%s" % (tensor_name, debug_op), np_printoptions={"linewidth": 40}) 159 self.assertEqual([(8, 8 + len(tensor_name), "bold"), 160 (8 + len(tensor_name) + 1, 161 8 + len(tensor_name) + 1 + len(debug_op), "yellow")], 162 out.font_attr_segs[0]) 163 164 def testFormatTensor1DNoEllipsis(self): 165 a = np.zeros(20) 166 167 out = tensor_format.format_tensor( 168 a, "a", np_printoptions={"linewidth": 40}) 169 170 cli_test_utils.assert_lines_equal_ignoring_whitespace( 171 self, ["Tensor \"a\":", ""], out.lines[:2]) 172 self.assertEqual(repr(a).split("\n"), out.lines[2:]) 173 174 self._checkTensorMetadata(a, out.annotations) 175 176 # Check annotations for beginning indices of the lines. 177 self._checkBeginIndicesAnnotations(out, a) 178 179 def testFormatTensor2DNoEllipsisNoRowBreak(self): 180 a = np.linspace(0.0, 1.0 - 1.0 / 16.0, 16).reshape([4, 4]) 181 182 out = tensor_format.format_tensor(a, "a") 183 184 cli_test_utils.assert_lines_equal_ignoring_whitespace( 185 self, ["Tensor \"a\":", ""], out.lines[:2]) 186 self.assertEqual(repr(a).split("\n"), out.lines[2:]) 187 188 self._checkTensorMetadata(a, out.annotations) 189 self._checkBeginIndicesAnnotations(out, a) 190 191 def testFormatTensorSuppressingTensorName(self): 192 a = np.linspace(0.0, 1.0 - 1.0 / 16.0, 16).reshape([4, 4]) 193 194 out = tensor_format.format_tensor(a, None) 195 self.assertEqual(repr(a).split("\n"), out.lines) 196 197 self._checkTensorMetadata(a, out.annotations) 198 self._checkBeginIndicesAnnotations(out, a) 199 200 def testFormatTensorWithMetadata(self): 201 a = np.linspace(0.0, 1.0 - 1.0 / 16.0, 16).reshape([4, 4]) 202 203 out = tensor_format.format_tensor(a, "a", include_metadata=True) 204 205 cli_test_utils.assert_lines_equal_ignoring_whitespace( 206 self, 207 ["Tensor \"a\":", 208 " dtype: float64", 209 " shape: (4, 4)", 210 ""], out.lines[:4]) 211 self.assertEqual(repr(a).split("\n"), out.lines[4:]) 212 213 self._checkTensorMetadata(a, out.annotations) 214 self._checkBeginIndicesAnnotations(out, a) 215 216 def testFormatTensor2DNoEllipsisWithRowBreak(self): 217 a = np.linspace(0.0, 1.0 - 1.0 / 40.0, 40).reshape([2, 20]) 218 219 out = tensor_format.format_tensor( 220 a, "a", np_printoptions={"linewidth": 50}) 221 222 self.assertEqual( 223 {"dtype": a.dtype, "shape": a.shape}, 224 out.annotations["tensor_metadata"]) 225 226 cli_test_utils.assert_lines_equal_ignoring_whitespace( 227 self, ["Tensor \"a\":", ""], out.lines[:2]) 228 self.assertEqual(repr(a).split("\n"), out.lines[2:]) 229 230 self._checkTensorMetadata(a, out.annotations) 231 232 # Check annotations for the beginning indices of the lines. 233 self._checkBeginIndicesAnnotations(out, a) 234 235 def testFormatTensor3DNoEllipsis(self): 236 a = np.linspace(0.0, 1.0 - 1.0 / 24.0, 24).reshape([2, 3, 4]) 237 238 out = tensor_format.format_tensor(a, "a") 239 240 cli_test_utils.assert_lines_equal_ignoring_whitespace( 241 self, ["Tensor \"a\":", ""], out.lines[:2]) 242 self.assertEqual(repr(a).split("\n"), out.lines[2:]) 243 244 self._checkTensorMetadata(a, out.annotations) 245 self._checkBeginIndicesAnnotations(out, a) 246 247 def testFormatTensor3DNoEllipsisWithArgwhereHighlightWithMatches(self): 248 a = np.linspace(0.0, 1.0 - 1.0 / 24.0, 24).reshape([2, 3, 4]) 249 250 lower_bound = 0.26 251 upper_bound = 0.5 252 253 def highlight_filter(x): 254 return np.logical_and(x > lower_bound, x < upper_bound) 255 256 highlight_options = tensor_format.HighlightOptions( 257 highlight_filter, description="between 0.26 and 0.5") 258 out = tensor_format.format_tensor( 259 a, "a", highlight_options=highlight_options) 260 261 cli_test_utils.assert_lines_equal_ignoring_whitespace( 262 self, 263 ["Tensor \"a\": " 264 "Highlighted(between 0.26 and 0.5): 5 of 24 element(s) (20.83%)", 265 ""], 266 out.lines[:2]) 267 self.assertEqual(repr(a).split("\n"), out.lines[2:]) 268 269 self._checkTensorMetadata(a, out.annotations) 270 271 # Check annotations for beginning indices of the lines. 272 self._checkBeginIndicesAnnotations(out, a) 273 274 self.assertAllClose( 275 [0.29166667, 0.33333333, 0.375, 0.41666667, 0.45833333], 276 self._extractBoldNumbers(out, 2)) 277 278 def testFormatTensor3DNoEllipsisWithArgwhereHighlightWithNoMatches(self): 279 a = np.linspace(0.0, 1.0 - 1.0 / 24.0, 24).reshape([2, 3, 4]) 280 281 def highlight_filter(x): 282 return x > 10.0 283 284 highlight_options = tensor_format.HighlightOptions(highlight_filter) 285 out = tensor_format.format_tensor( 286 a, "a", highlight_options=highlight_options) 287 288 cli_test_utils.assert_lines_equal_ignoring_whitespace( 289 self, 290 ["Tensor \"a\": Highlighted: 0 of 24 element(s) (0.00%)", ""], 291 out.lines[:2]) 292 self.assertEqual(repr(a).split("\n"), out.lines[2:]) 293 294 self._checkTensorMetadata(a, out.annotations) 295 self._checkBeginIndicesAnnotations(out, a) 296 297 # Check font attribute segments for highlighted elements. 298 for i in range(2, len(out.lines)): 299 self.assertNotIn(i, out.font_attr_segs) 300 301 def testFormatTensorWithEllipses(self): 302 a = (np.arange(11 * 11 * 11) + 1000).reshape([11, 11, 11]).astype(np.int32) 303 304 out = tensor_format.format_tensor( 305 a, "a", False, np_printoptions={"threshold": 100, "edgeitems": 2}) 306 307 cli_test_utils.assert_lines_equal_ignoring_whitespace( 308 self, ["Tensor \"a\":", ""], out.lines[:2]) 309 self.assertEqual(repr(a).split("\n"), out.lines[2:]) 310 311 self._checkTensorMetadata(a, out.annotations) 312 313 # Check annotations for beginning indices of the lines. 314 actual_row_0_0_0, _ = self._findFirst(out.lines, "1000") 315 self.assertEqual({tensor_format.BEGIN_INDICES_KEY: [0, 0, 0]}, 316 out.annotations[actual_row_0_0_0]) 317 actual_row_0_1_0, _ = self._findFirst(out.lines, "1011") 318 self.assertEqual({tensor_format.BEGIN_INDICES_KEY: [0, 1, 0]}, 319 out.annotations[actual_row_0_1_0]) 320 # Find the first line that is completely omitted. 321 omitted_line = 2 322 while not out.lines[omitted_line].strip().startswith("..."): 323 omitted_line += 1 324 self.assertEqual({tensor_format.OMITTED_INDICES_KEY: [0, 2, 0]}, 325 out.annotations[omitted_line]) 326 327 actual_row_10_10_0, _ = self._findFirst(out.lines, "2320") 328 self.assertEqual({tensor_format.BEGIN_INDICES_KEY: [10, 10, 0]}, 329 out.annotations[actual_row_10_10_0]) 330 # Find the last line that is completely omitted. 331 omitted_line = len(out.lines) - 1 332 while not out.lines[omitted_line].strip().startswith("..."): 333 omitted_line -= 1 334 self.assertEqual({tensor_format.OMITTED_INDICES_KEY: [10, 2, 0]}, 335 out.annotations[omitted_line]) 336 337 def testFormatUninitializedTensor(self): 338 tensor_proto = tensor_pb2.TensorProto( 339 dtype=types_pb2.DataType.Value("DT_FLOAT"), 340 tensor_shape=tensor_shape_pb2.TensorShapeProto( 341 dim=[tensor_shape_pb2.TensorShapeProto.Dim(size=1)])) 342 out = tensor_format.format_tensor( 343 debug_data.InconvertibleTensorProto(tensor_proto, False), "a") 344 345 self.assertEqual(["Tensor \"a\":", "", "Uninitialized tensor:"], 346 out.lines[:3]) 347 self.assertEqual(str(tensor_proto).split("\n"), out.lines[3:]) 348 349 def testFormatResourceTypeTensor(self): 350 tensor_proto = tensor_pb2.TensorProto( 351 dtype=types_pb2.DataType.Value("DT_RESOURCE"), 352 tensor_shape=tensor_shape_pb2.TensorShapeProto( 353 dim=[tensor_shape_pb2.TensorShapeProto.Dim(size=1)])) 354 out = tensor_format.format_tensor( 355 debug_data.InconvertibleTensorProto(tensor_proto), "a") 356 357 self.assertEqual(["Tensor \"a\":", ""], out.lines[:2]) 358 self.assertEqual(str(tensor_proto).split("\n"), out.lines[2:]) 359 360 def testLocateTensorElement1DNoEllipsis(self): 361 a = np.zeros(20) 362 363 out = tensor_format.format_tensor( 364 a, "a", np_printoptions={"linewidth": 40}) 365 366 cli_test_utils.assert_lines_equal_ignoring_whitespace( 367 self, ["Tensor \"a\":", ""], out.lines[:2]) 368 self.assertEqual(repr(a).split("\n"), out.lines[2:]) 369 370 self._checkTensorElementLocations(out, a) 371 372 with self.assertRaisesRegex(ValueError, "Indices exceed tensor dimensions"): 373 tensor_format.locate_tensor_element(out, [20]) 374 375 with self.assertRaisesRegex(ValueError, "Indices contain negative"): 376 tensor_format.locate_tensor_element(out, [-1]) 377 378 with self.assertRaisesRegex(ValueError, "Dimensions mismatch"): 379 tensor_format.locate_tensor_element(out, [0, 0]) 380 381 def testLocateTensorElement1DNoEllipsisBatchMode(self): 382 a = np.zeros(20) 383 384 out = tensor_format.format_tensor( 385 a, "a", np_printoptions={"linewidth": 40}) 386 387 cli_test_utils.assert_lines_equal_ignoring_whitespace( 388 self, ["Tensor \"a\":", ""], out.lines[:2]) 389 self.assertEqual(repr(a).split("\n"), out.lines[2:]) 390 391 self._checkTensorElementLocations(out, a) 392 393 def testBatchModeWithErrors(self): 394 a = np.zeros(20) 395 396 out = tensor_format.format_tensor( 397 a, "a", np_printoptions={"linewidth": 40}) 398 399 cli_test_utils.assert_lines_equal_ignoring_whitespace( 400 self, ["Tensor \"a\":", ""], out.lines[:2]) 401 self.assertEqual(repr(a).split("\n"), out.lines[2:]) 402 403 with self.assertRaisesRegex(ValueError, "Dimensions mismatch"): 404 tensor_format.locate_tensor_element(out, [[0, 0], [0]]) 405 406 with self.assertRaisesRegex(ValueError, "Indices exceed tensor dimensions"): 407 tensor_format.locate_tensor_element(out, [[0], [20]]) 408 409 with self.assertRaisesRegex(ValueError, 410 r"Indices contain negative value\(s\)"): 411 tensor_format.locate_tensor_element(out, [[0], [-1]]) 412 413 with self.assertRaisesRegex( 414 ValueError, "Input indices sets are not in ascending order"): 415 tensor_format.locate_tensor_element(out, [[5], [0]]) 416 417 def testLocateTensorElement1DTinyAndNanValues(self): 418 a = np.ones([3, 3]) * 1e-8 419 a[1, 0] = np.nan 420 a[1, 2] = np.inf 421 422 out = tensor_format.format_tensor( 423 a, "a", np_printoptions={"linewidth": 100}) 424 425 cli_test_utils.assert_lines_equal_ignoring_whitespace( 426 self, ["Tensor \"a\":", ""], out.lines[:2]) 427 self.assertEqual(repr(a).split("\n"), out.lines[2:]) 428 429 self._checkTensorElementLocations(out, a) 430 431 def testLocateTensorElement2DNoEllipsis(self): 432 a = np.linspace(0.0, 1.0 - 1.0 / 16.0, 16).reshape([4, 4]) 433 434 out = tensor_format.format_tensor(a, "a") 435 436 cli_test_utils.assert_lines_equal_ignoring_whitespace( 437 self, ["Tensor \"a\":", ""], out.lines[:2]) 438 self.assertEqual(repr(a).split("\n"), out.lines[2:]) 439 440 self._checkTensorElementLocations(out, a) 441 442 with self.assertRaisesRegex(ValueError, "Indices exceed tensor dimensions"): 443 tensor_format.locate_tensor_element(out, [1, 4]) 444 445 with self.assertRaisesRegex(ValueError, "Indices contain negative"): 446 tensor_format.locate_tensor_element(out, [-1, 2]) 447 448 with self.assertRaisesRegex(ValueError, "Dimensions mismatch"): 449 tensor_format.locate_tensor_element(out, [0]) 450 451 def testLocateTensorElement2DNoEllipsisWithNumericSummary(self): 452 a = np.linspace(0.0, 1.0 - 1.0 / 16.0, 16).reshape([4, 4]) 453 454 out = tensor_format.format_tensor(a, "a", include_numeric_summary=True) 455 456 cli_test_utils.assert_lines_equal_ignoring_whitespace( 457 self, 458 ["Tensor \"a\":", 459 "", 460 "Numeric summary:", 461 "| 0 + | total |", 462 "| 1 15 | 16 |", 463 "| min max mean std |"], 464 out.lines[:6]) 465 cli_test_utils.assert_array_lines_close( 466 self, [0.0, 0.9375, 0.46875, 0.28811076429], out.lines[6:7]) 467 cli_test_utils.assert_array_lines_close(self, a, out.lines[8:]) 468 469 self._checkTensorElementLocations(out, a) 470 471 with self.assertRaisesRegex(ValueError, "Indices exceed tensor dimensions"): 472 tensor_format.locate_tensor_element(out, [1, 4]) 473 474 with self.assertRaisesRegex(ValueError, "Indices contain negative"): 475 tensor_format.locate_tensor_element(out, [-1, 2]) 476 477 with self.assertRaisesRegex(ValueError, "Dimensions mismatch"): 478 tensor_format.locate_tensor_element(out, [0]) 479 480 def testLocateTensorElement3DWithEllipses(self): 481 a = (np.arange(11 * 11 * 11) + 1000).reshape([11, 11, 11]).astype(np.int32) 482 483 out = tensor_format.format_tensor( 484 a, "a", False, np_printoptions={"threshold": 100, "edgeitems": 2}) 485 486 cli_test_utils.assert_lines_equal_ignoring_whitespace( 487 self, ["Tensor \"a\":", ""], out.lines[:2]) 488 489 actual_row_0_0_0, actual_col_0_0_0 = self._findFirst(out.lines, "1000") 490 is_omitted, row, start_col, end_col = tensor_format.locate_tensor_element( 491 out, [0, 0, 0]) 492 self.assertFalse(is_omitted) 493 self.assertEqual(actual_row_0_0_0, row) 494 self.assertEqual(actual_col_0_0_0, start_col) 495 self.assertEqual(actual_col_0_0_0 + 4, end_col) 496 497 actual_row_0_0_10, _ = self._findFirst(out.lines, "1010") 498 is_omitted, row, start_col, end_col = tensor_format.locate_tensor_element( 499 out, [0, 0, 10]) 500 self.assertFalse(is_omitted) 501 self.assertEqual(actual_row_0_0_10, row) 502 self.assertIsNone(start_col) # Passes ellipsis. 503 self.assertIsNone(end_col) 504 505 actual_row_0_1_0, actual_col_0_1_0 = self._findFirst(out.lines, "1011") 506 is_omitted, row, start_col, end_col = tensor_format.locate_tensor_element( 507 out, [0, 1, 0]) 508 self.assertFalse(is_omitted) 509 self.assertEqual(actual_row_0_1_0, row) 510 self.assertEqual(actual_col_0_1_0, start_col) 511 self.assertEqual(actual_col_0_1_0 + 4, end_col) 512 513 is_omitted, row, start_col, end_col = tensor_format.locate_tensor_element( 514 out, [0, 2, 0]) 515 self.assertTrue(is_omitted) # In omitted line. 516 self.assertIsNone(start_col) 517 self.assertIsNone(end_col) 518 519 is_omitted, row, start_col, end_col = tensor_format.locate_tensor_element( 520 out, [0, 2, 10]) 521 self.assertTrue(is_omitted) # In omitted line. 522 self.assertIsNone(start_col) 523 self.assertIsNone(end_col) 524 525 is_omitted, row, start_col, end_col = tensor_format.locate_tensor_element( 526 out, [0, 8, 10]) 527 self.assertTrue(is_omitted) # In omitted line. 528 self.assertIsNone(start_col) 529 self.assertIsNone(end_col) 530 531 actual_row_0_10_1, actual_col_0_10_1 = self._findFirst(out.lines, "1111") 532 is_omitted, row, start_col, end_col = tensor_format.locate_tensor_element( 533 out, [0, 10, 1]) 534 self.assertFalse(is_omitted) 535 self.assertEqual(actual_row_0_10_1, row) 536 self.assertEqual(actual_col_0_10_1, start_col) 537 self.assertEqual(actual_col_0_10_1 + 4, end_col) 538 539 is_omitted, row, start_col, end_col = tensor_format.locate_tensor_element( 540 out, [5, 1, 1]) 541 self.assertTrue(is_omitted) # In omitted line. 542 self.assertIsNone(start_col) 543 self.assertIsNone(end_col) 544 545 actual_row_10_10_10, _ = self._findFirst(out.lines, "2330") 546 is_omitted, row, start_col, end_col = tensor_format.locate_tensor_element( 547 out, [10, 10, 10]) 548 self.assertFalse(is_omitted) 549 self.assertEqual(actual_row_10_10_10, row) 550 self.assertIsNone(start_col) # Past ellipsis. 551 self.assertIsNone(end_col) 552 553 with self.assertRaisesRegex(ValueError, "Indices exceed tensor dimensions"): 554 tensor_format.locate_tensor_element(out, [11, 5, 5]) 555 556 with self.assertRaisesRegex(ValueError, "Indices contain negative"): 557 tensor_format.locate_tensor_element(out, [-1, 5, 5]) 558 559 with self.assertRaisesRegex(ValueError, "Dimensions mismatch"): 560 tensor_format.locate_tensor_element(out, [5, 5]) 561 562 def testLocateTensorElement3DWithEllipsesBatchMode(self): 563 a = (np.arange(11 * 11 * 11) + 1000).reshape([11, 11, 11]).astype(np.int32) 564 565 out = tensor_format.format_tensor( 566 a, "a", False, np_printoptions={"threshold": 100, 567 "edgeitems": 2}) 568 569 cli_test_utils.assert_lines_equal_ignoring_whitespace( 570 self, ["Tensor \"a\":", ""], out.lines[:2]) 571 self.assertEqual(repr(a).split("\n"), out.lines[2:]) 572 573 actual_row_0_0_0, actual_col_0_0_0 = self._findFirst(out.lines, "1000") 574 actual_row_0_0_10, _ = self._findFirst(out.lines, "1010") 575 actual_row_10_10_10, _ = self._findFirst(out.lines, "2330") 576 577 (are_omitted, rows, start_cols, 578 end_cols) = tensor_format.locate_tensor_element(out, [[0, 0, 0]]) 579 self.assertEqual([False], are_omitted) 580 self.assertEqual([actual_row_0_0_0], rows) 581 self.assertEqual([actual_col_0_0_0], start_cols) 582 self.assertEqual([actual_col_0_0_0 + 4], end_cols) 583 584 (are_omitted, rows, start_cols, 585 end_cols) = tensor_format.locate_tensor_element(out, 586 [[0, 0, 0], [0, 0, 10]]) 587 self.assertEqual([False, False], are_omitted) 588 self.assertEqual([actual_row_0_0_0, actual_row_0_0_10], rows) 589 self.assertEqual([actual_col_0_0_0, None], start_cols) 590 self.assertEqual([actual_col_0_0_0 + 4, None], end_cols) 591 592 (are_omitted, rows, start_cols, 593 end_cols) = tensor_format.locate_tensor_element(out, 594 [[0, 0, 0], [0, 2, 0]]) 595 self.assertEqual([False, True], are_omitted) 596 self.assertEqual([2, 4], rows) 597 self.assertEqual(2, len(start_cols)) 598 self.assertEqual(2, len(end_cols)) 599 600 (are_omitted, rows, start_cols, 601 end_cols) = tensor_format.locate_tensor_element(out, 602 [[0, 0, 0], [10, 10, 10]]) 603 self.assertEqual([False, False], are_omitted) 604 self.assertEqual([actual_row_0_0_0, actual_row_10_10_10], rows) 605 self.assertEqual([actual_col_0_0_0, None], start_cols) 606 self.assertEqual([actual_col_0_0_0 + 4, None], end_cols) 607 608 def testLocateTensorElementAnnotationsUnavailable(self): 609 tensor_proto = tensor_pb2.TensorProto( 610 dtype=types_pb2.DataType.Value("DT_FLOAT"), 611 tensor_shape=tensor_shape_pb2.TensorShapeProto( 612 dim=[tensor_shape_pb2.TensorShapeProto.Dim(size=1)])) 613 out = tensor_format.format_tensor( 614 debug_data.InconvertibleTensorProto(tensor_proto, False), "a") 615 616 self.assertEqual(["Tensor \"a\":", "", "Uninitialized tensor:"], 617 out.lines[:3]) 618 619 with self.assertRaisesRegex( 620 AttributeError, "tensor_metadata is not available in annotations"): 621 tensor_format.locate_tensor_element(out, [0]) 622 623 624class NumericSummaryTest(test_util.TensorFlowTestCase): 625 626 def testNumericSummaryOnFloatFullHouse(self): 627 x = np.array([np.nan, np.nan, -np.inf, np.inf, np.inf, np.inf, -2, -3, -4, 628 0, 1, 2, 2, 2, 2, 0, 0, 0, np.inf, np.inf, np.inf]) 629 out = tensor_format.numeric_summary(x) 630 cli_test_utils.assert_lines_equal_ignoring_whitespace( 631 self, 632 ["| nan -inf - 0 + +inf | total |", 633 "| 2 1 3 4 5 6 | 21 |", 634 "| min max mean std |"], out.lines[:3]) 635 cli_test_utils.assert_array_lines_close( 636 self, [-4.0, 2.0, 0.0, 1.95789002075], out.lines[3:4]) 637 638 def testNumericSummaryOnFloatMissingCategories(self): 639 x = np.array([np.nan, np.nan]) 640 out = tensor_format.numeric_summary(x) 641 self.assertEqual(2, len(out.lines)) 642 cli_test_utils.assert_lines_equal_ignoring_whitespace( 643 self, ["| nan | total |", "| 2 | 2 |"], out.lines[:2]) 644 645 x = np.array([-np.inf, np.inf, 0, 0, np.inf, np.inf]) 646 out = tensor_format.numeric_summary(x) 647 cli_test_utils.assert_lines_equal_ignoring_whitespace( 648 self, 649 ["| -inf 0 +inf | total |", 650 "| 1 2 3 | 6 |", 651 "| min max mean std |"], out.lines[:3]) 652 cli_test_utils.assert_array_lines_close( 653 self, [0.0, 0.0, 0.0, 0.0], out.lines[3:4]) 654 655 x = np.array([-120, 120, 130]) 656 out = tensor_format.numeric_summary(x) 657 cli_test_utils.assert_lines_equal_ignoring_whitespace( 658 self, 659 ["| - + | total |", 660 "| 1 2 | 3 |", 661 "| min max mean std |"], 662 out.lines[:3]) 663 cli_test_utils.assert_array_lines_close( 664 self, [-120, 130, 43.3333333333, 115.566238822], out.lines[3:4]) 665 666 def testNumericSummaryOnEmptyFloat(self): 667 x = np.array([], dtype=np.float32) 668 out = tensor_format.numeric_summary(x) 669 self.assertEqual(["No numeric summary available due to empty tensor."], 670 out.lines) 671 672 def testNumericSummaryOnInt(self): 673 x = np.array([-3] * 50 + [3] * 200 + [0], dtype=np.int32) 674 out = tensor_format.numeric_summary(x) 675 cli_test_utils.assert_lines_equal_ignoring_whitespace( 676 self, 677 ["| - 0 + | total |", 678 "| 50 1 200 | 251 |", 679 "| min max mean std |"], 680 out.lines[:3]) 681 cli_test_utils.assert_array_lines_close( 682 self, [-3, 3, 1.79282868526, 2.39789673081], out.lines[3:4]) 683 684 def testNumericSummaryOnBool(self): 685 x = np.array([False, True, True, False], dtype=np.bool_) 686 out = tensor_format.numeric_summary(x) 687 cli_test_utils.assert_lines_equal_ignoring_whitespace( 688 self, 689 ["| False True | total |", "| 2 2 | 4 |"], out.lines) 690 691 x = np.array([True] * 10, dtype=np.bool_) 692 out = tensor_format.numeric_summary(x) 693 cli_test_utils.assert_lines_equal_ignoring_whitespace( 694 self, ["| True | total |", "| 10 | 10 |"], out.lines) 695 696 x = np.array([False] * 10, dtype=np.bool_) 697 out = tensor_format.numeric_summary(x) 698 cli_test_utils.assert_lines_equal_ignoring_whitespace( 699 self, ["| False | total |", "| 10 | 10 |"], out.lines) 700 701 x = np.array([], dtype=np.bool_) 702 out = tensor_format.numeric_summary(x) 703 self.assertEqual(["No numeric summary available due to empty tensor."], 704 out.lines) 705 706 def testNumericSummaryOnStrTensor(self): 707 x = np.array(["spam", "egg"], dtype=np.object_) 708 out = tensor_format.numeric_summary(x) 709 self.assertEqual( 710 ["No numeric summary available due to tensor dtype: object."], 711 out.lines) 712 713 714if __name__ == "__main__": 715 googletest.main() 716