tensorbored 2.21.0rc1769983804__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. tensorbored/__init__.py +112 -0
  2. tensorbored/_vendor/__init__.py +0 -0
  3. tensorbored/_vendor/bleach/__init__.py +125 -0
  4. tensorbored/_vendor/bleach/_vendor/__init__.py +0 -0
  5. tensorbored/_vendor/bleach/_vendor/html5lib/__init__.py +35 -0
  6. tensorbored/_vendor/bleach/_vendor/html5lib/_ihatexml.py +289 -0
  7. tensorbored/_vendor/bleach/_vendor/html5lib/_inputstream.py +918 -0
  8. tensorbored/_vendor/bleach/_vendor/html5lib/_tokenizer.py +1735 -0
  9. tensorbored/_vendor/bleach/_vendor/html5lib/_trie/__init__.py +5 -0
  10. tensorbored/_vendor/bleach/_vendor/html5lib/_trie/_base.py +40 -0
  11. tensorbored/_vendor/bleach/_vendor/html5lib/_trie/py.py +67 -0
  12. tensorbored/_vendor/bleach/_vendor/html5lib/_utils.py +159 -0
  13. tensorbored/_vendor/bleach/_vendor/html5lib/constants.py +2946 -0
  14. tensorbored/_vendor/bleach/_vendor/html5lib/filters/__init__.py +0 -0
  15. tensorbored/_vendor/bleach/_vendor/html5lib/filters/alphabeticalattributes.py +29 -0
  16. tensorbored/_vendor/bleach/_vendor/html5lib/filters/base.py +12 -0
  17. tensorbored/_vendor/bleach/_vendor/html5lib/filters/inject_meta_charset.py +73 -0
  18. tensorbored/_vendor/bleach/_vendor/html5lib/filters/lint.py +93 -0
  19. tensorbored/_vendor/bleach/_vendor/html5lib/filters/optionaltags.py +207 -0
  20. tensorbored/_vendor/bleach/_vendor/html5lib/filters/sanitizer.py +916 -0
  21. tensorbored/_vendor/bleach/_vendor/html5lib/filters/whitespace.py +38 -0
  22. tensorbored/_vendor/bleach/_vendor/html5lib/html5parser.py +2795 -0
  23. tensorbored/_vendor/bleach/_vendor/html5lib/serializer.py +409 -0
  24. tensorbored/_vendor/bleach/_vendor/html5lib/treeadapters/__init__.py +30 -0
  25. tensorbored/_vendor/bleach/_vendor/html5lib/treeadapters/genshi.py +54 -0
  26. tensorbored/_vendor/bleach/_vendor/html5lib/treeadapters/sax.py +50 -0
  27. tensorbored/_vendor/bleach/_vendor/html5lib/treebuilders/__init__.py +88 -0
  28. tensorbored/_vendor/bleach/_vendor/html5lib/treebuilders/base.py +417 -0
  29. tensorbored/_vendor/bleach/_vendor/html5lib/treebuilders/dom.py +239 -0
  30. tensorbored/_vendor/bleach/_vendor/html5lib/treebuilders/etree.py +343 -0
  31. tensorbored/_vendor/bleach/_vendor/html5lib/treebuilders/etree_lxml.py +392 -0
  32. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/__init__.py +154 -0
  33. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/base.py +252 -0
  34. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/dom.py +43 -0
  35. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/etree.py +131 -0
  36. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/etree_lxml.py +215 -0
  37. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/genshi.py +69 -0
  38. tensorbored/_vendor/bleach/_vendor/parse.py +1078 -0
  39. tensorbored/_vendor/bleach/callbacks.py +32 -0
  40. tensorbored/_vendor/bleach/html5lib_shim.py +757 -0
  41. tensorbored/_vendor/bleach/linkifier.py +633 -0
  42. tensorbored/_vendor/bleach/parse_shim.py +1 -0
  43. tensorbored/_vendor/bleach/sanitizer.py +638 -0
  44. tensorbored/_vendor/bleach/six_shim.py +19 -0
  45. tensorbored/_vendor/webencodings/__init__.py +342 -0
  46. tensorbored/_vendor/webencodings/labels.py +231 -0
  47. tensorbored/_vendor/webencodings/mklabels.py +59 -0
  48. tensorbored/_vendor/webencodings/x_user_defined.py +325 -0
  49. tensorbored/assets.py +36 -0
  50. tensorbored/auth.py +102 -0
  51. tensorbored/backend/__init__.py +0 -0
  52. tensorbored/backend/application.py +604 -0
  53. tensorbored/backend/auth_context_middleware.py +38 -0
  54. tensorbored/backend/client_feature_flags.py +113 -0
  55. tensorbored/backend/empty_path_redirect.py +46 -0
  56. tensorbored/backend/event_processing/__init__.py +0 -0
  57. tensorbored/backend/event_processing/data_ingester.py +276 -0
  58. tensorbored/backend/event_processing/data_provider.py +535 -0
  59. tensorbored/backend/event_processing/directory_loader.py +142 -0
  60. tensorbored/backend/event_processing/directory_watcher.py +272 -0
  61. tensorbored/backend/event_processing/event_accumulator.py +950 -0
  62. tensorbored/backend/event_processing/event_file_inspector.py +463 -0
  63. tensorbored/backend/event_processing/event_file_loader.py +292 -0
  64. tensorbored/backend/event_processing/event_multiplexer.py +521 -0
  65. tensorbored/backend/event_processing/event_util.py +68 -0
  66. tensorbored/backend/event_processing/io_wrapper.py +223 -0
  67. tensorbored/backend/event_processing/plugin_asset_util.py +104 -0
  68. tensorbored/backend/event_processing/plugin_event_accumulator.py +721 -0
  69. tensorbored/backend/event_processing/plugin_event_multiplexer.py +522 -0
  70. tensorbored/backend/event_processing/reservoir.py +266 -0
  71. tensorbored/backend/event_processing/tag_types.py +29 -0
  72. tensorbored/backend/experiment_id.py +71 -0
  73. tensorbored/backend/experimental_plugin.py +51 -0
  74. tensorbored/backend/http_util.py +263 -0
  75. tensorbored/backend/json_util.py +70 -0
  76. tensorbored/backend/path_prefix.py +67 -0
  77. tensorbored/backend/process_graph.py +74 -0
  78. tensorbored/backend/security_validator.py +202 -0
  79. tensorbored/compat/__init__.py +69 -0
  80. tensorbored/compat/proto/__init__.py +0 -0
  81. tensorbored/compat/proto/allocation_description_pb2.py +35 -0
  82. tensorbored/compat/proto/api_def_pb2.py +82 -0
  83. tensorbored/compat/proto/attr_value_pb2.py +80 -0
  84. tensorbored/compat/proto/cluster_pb2.py +58 -0
  85. tensorbored/compat/proto/config_pb2.py +271 -0
  86. tensorbored/compat/proto/coordination_config_pb2.py +45 -0
  87. tensorbored/compat/proto/cost_graph_pb2.py +87 -0
  88. tensorbored/compat/proto/cpp_shape_inference_pb2.py +70 -0
  89. tensorbored/compat/proto/debug_pb2.py +65 -0
  90. tensorbored/compat/proto/event_pb2.py +149 -0
  91. tensorbored/compat/proto/full_type_pb2.py +74 -0
  92. tensorbored/compat/proto/function_pb2.py +157 -0
  93. tensorbored/compat/proto/graph_debug_info_pb2.py +111 -0
  94. tensorbored/compat/proto/graph_pb2.py +41 -0
  95. tensorbored/compat/proto/histogram_pb2.py +39 -0
  96. tensorbored/compat/proto/meta_graph_pb2.py +254 -0
  97. tensorbored/compat/proto/node_def_pb2.py +61 -0
  98. tensorbored/compat/proto/op_def_pb2.py +81 -0
  99. tensorbored/compat/proto/resource_handle_pb2.py +48 -0
  100. tensorbored/compat/proto/rewriter_config_pb2.py +93 -0
  101. tensorbored/compat/proto/rpc_options_pb2.py +35 -0
  102. tensorbored/compat/proto/saved_object_graph_pb2.py +193 -0
  103. tensorbored/compat/proto/saver_pb2.py +38 -0
  104. tensorbored/compat/proto/step_stats_pb2.py +116 -0
  105. tensorbored/compat/proto/struct_pb2.py +144 -0
  106. tensorbored/compat/proto/summary_pb2.py +111 -0
  107. tensorbored/compat/proto/tensor_description_pb2.py +38 -0
  108. tensorbored/compat/proto/tensor_pb2.py +68 -0
  109. tensorbored/compat/proto/tensor_shape_pb2.py +46 -0
  110. tensorbored/compat/proto/tfprof_log_pb2.py +307 -0
  111. tensorbored/compat/proto/trackable_object_graph_pb2.py +90 -0
  112. tensorbored/compat/proto/types_pb2.py +105 -0
  113. tensorbored/compat/proto/variable_pb2.py +62 -0
  114. tensorbored/compat/proto/verifier_config_pb2.py +38 -0
  115. tensorbored/compat/proto/versions_pb2.py +35 -0
  116. tensorbored/compat/tensorflow_stub/__init__.py +38 -0
  117. tensorbored/compat/tensorflow_stub/app.py +124 -0
  118. tensorbored/compat/tensorflow_stub/compat/__init__.py +131 -0
  119. tensorbored/compat/tensorflow_stub/compat/v1/__init__.py +20 -0
  120. tensorbored/compat/tensorflow_stub/dtypes.py +692 -0
  121. tensorbored/compat/tensorflow_stub/error_codes.py +169 -0
  122. tensorbored/compat/tensorflow_stub/errors.py +507 -0
  123. tensorbored/compat/tensorflow_stub/flags.py +124 -0
  124. tensorbored/compat/tensorflow_stub/io/__init__.py +17 -0
  125. tensorbored/compat/tensorflow_stub/io/gfile.py +1011 -0
  126. tensorbored/compat/tensorflow_stub/pywrap_tensorflow.py +285 -0
  127. tensorbored/compat/tensorflow_stub/tensor_shape.py +1035 -0
  128. tensorbored/context.py +129 -0
  129. tensorbored/data/__init__.py +0 -0
  130. tensorbored/data/grpc_provider.py +365 -0
  131. tensorbored/data/ingester.py +46 -0
  132. tensorbored/data/proto/__init__.py +0 -0
  133. tensorbored/data/proto/data_provider_pb2.py +517 -0
  134. tensorbored/data/proto/data_provider_pb2_grpc.py +374 -0
  135. tensorbored/data/provider.py +1365 -0
  136. tensorbored/data/server_ingester.py +301 -0
  137. tensorbored/data_compat.py +159 -0
  138. tensorbored/dataclass_compat.py +224 -0
  139. tensorbored/default.py +124 -0
  140. tensorbored/errors.py +130 -0
  141. tensorbored/lazy.py +99 -0
  142. tensorbored/main.py +48 -0
  143. tensorbored/main_lib.py +62 -0
  144. tensorbored/manager.py +487 -0
  145. tensorbored/notebook.py +441 -0
  146. tensorbored/plugin_util.py +266 -0
  147. tensorbored/plugins/__init__.py +0 -0
  148. tensorbored/plugins/audio/__init__.py +0 -0
  149. tensorbored/plugins/audio/audio_plugin.py +229 -0
  150. tensorbored/plugins/audio/metadata.py +69 -0
  151. tensorbored/plugins/audio/plugin_data_pb2.py +37 -0
  152. tensorbored/plugins/audio/summary.py +230 -0
  153. tensorbored/plugins/audio/summary_v2.py +124 -0
  154. tensorbored/plugins/base_plugin.py +367 -0
  155. tensorbored/plugins/core/__init__.py +0 -0
  156. tensorbored/plugins/core/core_plugin.py +981 -0
  157. tensorbored/plugins/custom_scalar/__init__.py +0 -0
  158. tensorbored/plugins/custom_scalar/custom_scalars_plugin.py +320 -0
  159. tensorbored/plugins/custom_scalar/layout_pb2.py +85 -0
  160. tensorbored/plugins/custom_scalar/metadata.py +35 -0
  161. tensorbored/plugins/custom_scalar/summary.py +79 -0
  162. tensorbored/plugins/debugger_v2/__init__.py +0 -0
  163. tensorbored/plugins/debugger_v2/debug_data_multiplexer.py +631 -0
  164. tensorbored/plugins/debugger_v2/debug_data_provider.py +634 -0
  165. tensorbored/plugins/debugger_v2/debugger_v2_plugin.py +504 -0
  166. tensorbored/plugins/distribution/__init__.py +0 -0
  167. tensorbored/plugins/distribution/compressor.py +158 -0
  168. tensorbored/plugins/distribution/distributions_plugin.py +116 -0
  169. tensorbored/plugins/distribution/metadata.py +19 -0
  170. tensorbored/plugins/graph/__init__.py +0 -0
  171. tensorbored/plugins/graph/graph_util.py +129 -0
  172. tensorbored/plugins/graph/graphs_plugin.py +336 -0
  173. tensorbored/plugins/graph/keras_util.py +328 -0
  174. tensorbored/plugins/graph/metadata.py +42 -0
  175. tensorbored/plugins/histogram/__init__.py +0 -0
  176. tensorbored/plugins/histogram/histograms_plugin.py +144 -0
  177. tensorbored/plugins/histogram/metadata.py +63 -0
  178. tensorbored/plugins/histogram/plugin_data_pb2.py +34 -0
  179. tensorbored/plugins/histogram/summary.py +234 -0
  180. tensorbored/plugins/histogram/summary_v2.py +292 -0
  181. tensorbored/plugins/hparams/__init__.py +14 -0
  182. tensorbored/plugins/hparams/_keras.py +93 -0
  183. tensorbored/plugins/hparams/api.py +130 -0
  184. tensorbored/plugins/hparams/api_pb2.py +208 -0
  185. tensorbored/plugins/hparams/backend_context.py +606 -0
  186. tensorbored/plugins/hparams/download_data.py +158 -0
  187. tensorbored/plugins/hparams/error.py +26 -0
  188. tensorbored/plugins/hparams/get_experiment.py +71 -0
  189. tensorbored/plugins/hparams/hparams_plugin.py +206 -0
  190. tensorbored/plugins/hparams/hparams_util_pb2.py +69 -0
  191. tensorbored/plugins/hparams/json_format_compat.py +38 -0
  192. tensorbored/plugins/hparams/list_metric_evals.py +57 -0
  193. tensorbored/plugins/hparams/list_session_groups.py +1040 -0
  194. tensorbored/plugins/hparams/metadata.py +125 -0
  195. tensorbored/plugins/hparams/metrics.py +41 -0
  196. tensorbored/plugins/hparams/plugin_data_pb2.py +69 -0
  197. tensorbored/plugins/hparams/summary.py +205 -0
  198. tensorbored/plugins/hparams/summary_v2.py +597 -0
  199. tensorbored/plugins/image/__init__.py +0 -0
  200. tensorbored/plugins/image/images_plugin.py +232 -0
  201. tensorbored/plugins/image/metadata.py +65 -0
  202. tensorbored/plugins/image/plugin_data_pb2.py +34 -0
  203. tensorbored/plugins/image/summary.py +159 -0
  204. tensorbored/plugins/image/summary_v2.py +130 -0
  205. tensorbored/plugins/mesh/__init__.py +14 -0
  206. tensorbored/plugins/mesh/mesh_plugin.py +292 -0
  207. tensorbored/plugins/mesh/metadata.py +152 -0
  208. tensorbored/plugins/mesh/plugin_data_pb2.py +37 -0
  209. tensorbored/plugins/mesh/summary.py +251 -0
  210. tensorbored/plugins/mesh/summary_v2.py +214 -0
  211. tensorbored/plugins/metrics/__init__.py +0 -0
  212. tensorbored/plugins/metrics/metadata.py +17 -0
  213. tensorbored/plugins/metrics/metrics_plugin.py +623 -0
  214. tensorbored/plugins/pr_curve/__init__.py +0 -0
  215. tensorbored/plugins/pr_curve/metadata.py +75 -0
  216. tensorbored/plugins/pr_curve/plugin_data_pb2.py +34 -0
  217. tensorbored/plugins/pr_curve/pr_curves_plugin.py +241 -0
  218. tensorbored/plugins/pr_curve/summary.py +574 -0
  219. tensorbored/plugins/profile_redirect/__init__.py +0 -0
  220. tensorbored/plugins/profile_redirect/profile_redirect_plugin.py +49 -0
  221. tensorbored/plugins/projector/__init__.py +67 -0
  222. tensorbored/plugins/projector/metadata.py +26 -0
  223. tensorbored/plugins/projector/projector_config_pb2.py +54 -0
  224. tensorbored/plugins/projector/projector_plugin.py +795 -0
  225. tensorbored/plugins/projector/tf_projector_plugin/index.js +32 -0
  226. tensorbored/plugins/projector/tf_projector_plugin/projector_binary.html +524 -0
  227. tensorbored/plugins/projector/tf_projector_plugin/projector_binary.js +15536 -0
  228. tensorbored/plugins/scalar/__init__.py +0 -0
  229. tensorbored/plugins/scalar/metadata.py +60 -0
  230. tensorbored/plugins/scalar/plugin_data_pb2.py +34 -0
  231. tensorbored/plugins/scalar/scalars_plugin.py +181 -0
  232. tensorbored/plugins/scalar/summary.py +109 -0
  233. tensorbored/plugins/scalar/summary_v2.py +124 -0
  234. tensorbored/plugins/text/__init__.py +0 -0
  235. tensorbored/plugins/text/metadata.py +62 -0
  236. tensorbored/plugins/text/plugin_data_pb2.py +34 -0
  237. tensorbored/plugins/text/summary.py +114 -0
  238. tensorbored/plugins/text/summary_v2.py +124 -0
  239. tensorbored/plugins/text/text_plugin.py +288 -0
  240. tensorbored/plugins/wit_redirect/__init__.py +0 -0
  241. tensorbored/plugins/wit_redirect/wit_redirect_plugin.py +49 -0
  242. tensorbored/program.py +910 -0
  243. tensorbored/summary/__init__.py +35 -0
  244. tensorbored/summary/_output.py +124 -0
  245. tensorbored/summary/_tf/__init__.py +14 -0
  246. tensorbored/summary/_tf/summary/__init__.py +178 -0
  247. tensorbored/summary/_writer.py +105 -0
  248. tensorbored/summary/v1.py +51 -0
  249. tensorbored/summary/v2.py +25 -0
  250. tensorbored/summary/writer/__init__.py +13 -0
  251. tensorbored/summary/writer/event_file_writer.py +291 -0
  252. tensorbored/summary/writer/record_writer.py +50 -0
  253. tensorbored/util/__init__.py +0 -0
  254. tensorbored/util/encoder.py +116 -0
  255. tensorbored/util/grpc_util.py +311 -0
  256. tensorbored/util/img_mime_type_detector.py +40 -0
  257. tensorbored/util/io_util.py +20 -0
  258. tensorbored/util/lazy_tensor_creator.py +110 -0
  259. tensorbored/util/op_evaluator.py +104 -0
  260. tensorbored/util/platform_util.py +20 -0
  261. tensorbored/util/tb_logging.py +24 -0
  262. tensorbored/util/tensor_util.py +617 -0
  263. tensorbored/util/timing.py +122 -0
  264. tensorbored/version.py +21 -0
  265. tensorbored/webfiles.zip +0 -0
  266. tensorbored-2.21.0rc1769983804.dist-info/METADATA +49 -0
  267. tensorbored-2.21.0rc1769983804.dist-info/RECORD +271 -0
  268. tensorbored-2.21.0rc1769983804.dist-info/WHEEL +5 -0
  269. tensorbored-2.21.0rc1769983804.dist-info/entry_points.txt +6 -0
  270. tensorbored-2.21.0rc1769983804.dist-info/licenses/LICENSE +739 -0
  271. tensorbored-2.21.0rc1769983804.dist-info/top_level.txt +1 -0
@@ -0,0 +1,328 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2019 The TensorFlow Authors. All Rights Reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ # ==============================================================================
16
+ """Utilities for handling Keras model in graph plugin.
17
+
18
+ Two canonical types of Keras model are Functional and Sequential.
19
+ A model can be serialized as JSON and deserialized to reconstruct a model.
20
+ This utility helps with dealing with the serialized Keras model.
21
+
22
+ They have distinct structures to the configurations in shapes below:
23
+ Functional:
24
+ config
25
+ name: Name of the model. If not specified, it is 'model' with
26
+ an optional suffix if there are more than one instance.
27
+ input_layers: Keras.layers.Inputs in the model.
28
+ output_layers: Layer names that are outputs of the model.
29
+ layers: list of layer configurations.
30
+ layer: [*]
31
+ inbound_nodes: inputs to this layer.
32
+
33
+ Sequential:
34
+ config
35
+ name: Name of the model. If not specified, it is 'sequential' with
36
+ an optional suffix if there are more than one instance.
37
+ layers: list of layer configurations.
38
+ layer: [*]
39
+
40
+ [*]: Note that a model can be a layer.
41
+ Please refer to https://github.com/tensorflow/tfjs-layers/blob/master/src/keras_format/model_serialization.ts
42
+ for more complete definition.
43
+ """
44
+
45
+ from tensorbored.compat.proto.graph_pb2 import GraphDef
46
+ from tensorbored.compat.tensorflow_stub import dtypes
47
+ from tensorbored.util import tb_logging
48
+
49
+ logger = tb_logging.get_logger()
50
+
51
+
52
+ def _walk_layers(keras_layer):
53
+ """Walks the nested keras layer configuration in preorder.
54
+
55
+ Args:
56
+ keras_layer: Keras configuration from model.to_json.
57
+
58
+ Yields:
59
+ A tuple of (name_scope, layer_config).
60
+ name_scope: a string representing a scope name, similar to that of tf.name_scope.
61
+ layer_config: a dict representing a Keras layer configuration.
62
+ """
63
+ yield ("", keras_layer)
64
+ if keras_layer.get("config").get("layers"):
65
+ name_scope = keras_layer.get("config").get("name")
66
+ for layer in keras_layer.get("config").get("layers"):
67
+ for sub_name_scope, sublayer in _walk_layers(layer):
68
+ sub_name_scope = (
69
+ "%s/%s" % (name_scope, sub_name_scope)
70
+ if sub_name_scope
71
+ else name_scope
72
+ )
73
+ yield (sub_name_scope, sublayer)
74
+
75
+
76
+ def _scoped_name(name_scope, node_name):
77
+ """Returns scoped name for a node as a string in the form '<scope>/<node
78
+ name>'.
79
+
80
+ Args:
81
+ name_scope: a string representing a scope name, similar to that of tf.name_scope.
82
+ node_name: a string representing the current node name.
83
+
84
+ Returns
85
+ A string representing a scoped name.
86
+ """
87
+ if name_scope:
88
+ return "%s/%s" % (name_scope, node_name)
89
+ return node_name
90
+
91
+
92
+ def _is_model(layer):
93
+ """Returns True if layer is a model.
94
+
95
+ Args:
96
+ layer: a dict representing a Keras model configuration.
97
+
98
+ Returns:
99
+ bool: True if layer is a model.
100
+ """
101
+ return layer.get("config").get("layers") is not None
102
+
103
+
104
+ def _norm_to_list_of_layers(maybe_layers):
105
+ """Normalizes to a list of layers.
106
+
107
+ Args:
108
+ maybe_layers: A list of data[1] or a list of list of data.
109
+
110
+ Returns:
111
+ List of list of data.
112
+
113
+ [1]: A Functional model has fields 'inbound_nodes' and 'output_layers' which can
114
+ look like below:
115
+ - ['in_layer_name', 0, 0]
116
+ - [['in_layer_is_model', 1, 0], ['in_layer_is_model', 1, 1]]
117
+ The data inside the list seems to describe [name, size, index].
118
+ """
119
+ return (
120
+ maybe_layers if isinstance(maybe_layers[0], (list,)) else [maybe_layers]
121
+ )
122
+
123
+
124
+ def _get_inbound_nodes(layer):
125
+ """Returns a list of [name, size, index] for all inbound nodes of the given layer."""
126
+ inbound_nodes = []
127
+ if layer.get("inbound_nodes") is not None:
128
+ for maybe_inbound_node in layer.get("inbound_nodes", []):
129
+ if not isinstance(maybe_inbound_node, dict):
130
+ # Note that the inbound node parsing is not backward compatible with
131
+ # Keras 2. If given a Keras 2 model, the input nodes will be missing
132
+ # in the final graph.
133
+ continue
134
+ for inbound_node_args in maybe_inbound_node.get("args", []):
135
+ # Sometimes this field is a list when there are multiple inbound nodes
136
+ # for the given layer.
137
+ if not isinstance(inbound_node_args, list):
138
+ inbound_node_args = [inbound_node_args]
139
+ for arg in inbound_node_args:
140
+ history = arg.get("config", {}).get("keras_history", [])
141
+ if len(history) < 3:
142
+ continue
143
+ inbound_nodes.append(history[:3])
144
+ return inbound_nodes
145
+
146
+
147
+ def _update_dicts(
148
+ name_scope,
149
+ model_layer,
150
+ input_to_in_layer,
151
+ model_name_to_output,
152
+ prev_node_name,
153
+ ):
154
+ """Updates input_to_in_layer, model_name_to_output, and prev_node_name
155
+ based on the model_layer.
156
+
157
+ Args:
158
+ name_scope: a string representing a scope name, similar to that of tf.name_scope.
159
+ model_layer: a dict representing a Keras model configuration.
160
+ input_to_in_layer: a dict mapping Keras.layers.Input to inbound layer.
161
+ model_name_to_output: a dict mapping Keras Model name to output layer of the model.
162
+ prev_node_name: a string representing a previous, in sequential model layout,
163
+ node name.
164
+
165
+ Returns:
166
+ A tuple of (input_to_in_layer, model_name_to_output, prev_node_name).
167
+ input_to_in_layer: a dict mapping Keras.layers.Input to inbound layer.
168
+ model_name_to_output: a dict mapping Keras Model name to output layer of the model.
169
+ prev_node_name: a string representing a previous, in sequential model layout,
170
+ node name.
171
+ """
172
+ layer_config = model_layer.get("config")
173
+ if not layer_config.get("layers"):
174
+ raise ValueError("layer is not a model.")
175
+
176
+ node_name = _scoped_name(name_scope, layer_config.get("name"))
177
+ input_layers = layer_config.get("input_layers")
178
+ output_layers = layer_config.get("output_layers")
179
+ inbound_nodes = _get_inbound_nodes(model_layer)
180
+
181
+ is_functional_model = bool(input_layers and output_layers)
182
+ # In case of [1] and the parent model is functional, current layer
183
+ # will have the 'inbound_nodes' property.
184
+ is_parent_functional_model = bool(inbound_nodes)
185
+
186
+ if is_parent_functional_model and is_functional_model:
187
+ for input_layer, inbound_node in zip(input_layers, inbound_nodes):
188
+ input_layer_name = _scoped_name(node_name, input_layer)
189
+ inbound_node_name = _scoped_name(name_scope, inbound_node[0])
190
+ input_to_in_layer[input_layer_name] = inbound_node_name
191
+ elif is_parent_functional_model and not is_functional_model:
192
+ # Sequential model can take only one input. Make sure inbound to the
193
+ # model is linked to the first layer in the Sequential model.
194
+ prev_node_name = _scoped_name(name_scope, inbound_nodes[0][0])
195
+ elif (
196
+ not is_parent_functional_model
197
+ and prev_node_name
198
+ and is_functional_model
199
+ ):
200
+ assert len(input_layers) == 1, (
201
+ "Cannot have multi-input Functional model when parent model "
202
+ "is not Functional. Number of input layers: %d" % len(input_layer)
203
+ )
204
+ input_layer = input_layers[0]
205
+ input_layer_name = _scoped_name(node_name, input_layer)
206
+ input_to_in_layer[input_layer_name] = prev_node_name
207
+
208
+ if is_functional_model and output_layers:
209
+ layers = _norm_to_list_of_layers(output_layers)
210
+ layer_names = [_scoped_name(node_name, layer[0]) for layer in layers]
211
+ model_name_to_output[node_name] = layer_names
212
+ else:
213
+ last_layer = layer_config.get("layers")[-1]
214
+ last_layer_name = last_layer.get("config").get("name")
215
+ output_node = _scoped_name(node_name, last_layer_name)
216
+ model_name_to_output[node_name] = [output_node]
217
+ return (input_to_in_layer, model_name_to_output, prev_node_name)
218
+
219
+
220
+ def keras_model_to_graph_def(keras_layer):
221
+ """Returns a GraphDef representation of the Keras model in a dict form.
222
+
223
+ Note that it only supports models that implemented to_json().
224
+
225
+ Args:
226
+ keras_layer: A dict from Keras model.to_json().
227
+
228
+ Returns:
229
+ A GraphDef representation of the layers in the model.
230
+ """
231
+ input_to_layer = {}
232
+ model_name_to_output = {}
233
+ g = GraphDef()
234
+
235
+ # Sequential model layers do not have a field "inbound_nodes" but
236
+ # instead are defined implicitly via order of layers.
237
+ prev_node_name = None
238
+
239
+ for name_scope, layer in _walk_layers(keras_layer):
240
+ if _is_model(layer):
241
+ (
242
+ input_to_layer,
243
+ model_name_to_output,
244
+ prev_node_name,
245
+ ) = _update_dicts(
246
+ name_scope,
247
+ layer,
248
+ input_to_layer,
249
+ model_name_to_output,
250
+ prev_node_name,
251
+ )
252
+ continue
253
+
254
+ layer_config = layer.get("config")
255
+ node_name = _scoped_name(name_scope, layer_config.get("name"))
256
+
257
+ node_def = g.node.add()
258
+ node_def.name = node_name
259
+
260
+ if layer.get("class_name") is not None:
261
+ keras_cls_name = layer.get("class_name").encode("ascii")
262
+ node_def.attr["keras_class"].s = keras_cls_name
263
+
264
+ dtype_or_policy = layer_config.get("dtype")
265
+ dtype = None
266
+ has_unsupported_value = False
267
+ # If this is a dict, try and extract the dtype string from
268
+ # `config.name`. Keras will export like this for non-input layers and
269
+ # some other cases (e.g. tf/keras/mixed_precision/Policy, as described
270
+ # in issue #5548).
271
+ if isinstance(dtype_or_policy, dict) and "config" in dtype_or_policy:
272
+ dtype = dtype_or_policy.get("config").get("name")
273
+ elif dtype_or_policy is not None:
274
+ dtype = dtype_or_policy
275
+
276
+ if dtype is not None:
277
+ try:
278
+ tf_dtype = dtypes.as_dtype(dtype)
279
+ node_def.attr["dtype"].type = tf_dtype.as_datatype_enum
280
+ except TypeError:
281
+ has_unsupported_value = True
282
+ elif dtype_or_policy is not None:
283
+ has_unsupported_value = True
284
+
285
+ if has_unsupported_value:
286
+ # There's at least one known case when this happens, which is when
287
+ # mixed precision dtype policies are used, as described in issue
288
+ # #5548. (See https://keras.io/api/mixed_precision/).
289
+ # There might be a better way to handle this, but here we are.
290
+ logger.warning(
291
+ "Unsupported dtype value in graph model config (json):\n%s",
292
+ dtype_or_policy,
293
+ )
294
+ if layer.get("inbound_nodes") is not None:
295
+ for name, size, index in _get_inbound_nodes(layer):
296
+ inbound_name = _scoped_name(name_scope, name)
297
+ # An input to a layer can be output from a model. In that case, the name
298
+ # of inbound_nodes to a layer is a name of a model. Remap the name of the
299
+ # model to output layer of the model. Also, since there can be multiple
300
+ # outputs in a model, make sure we pick the right output_layer from the model.
301
+ inbound_node_names = model_name_to_output.get(
302
+ inbound_name, [inbound_name]
303
+ )
304
+ # There can be multiple inbound_nodes that reference the
305
+ # same upstream layer. This causes issues when looking for
306
+ # a particular index in that layer, since the indices
307
+ # captured in `inbound_nodes` doesn't necessarily match the
308
+ # number of entries in the `inbound_node_names` list. To
309
+ # avoid IndexErrors, we just use the last element in the
310
+ # `inbound_node_names` in this situation.
311
+ # Note that this is a quick hack to avoid IndexErrors in
312
+ # this situation, and might not be an appropriate solution
313
+ # to this problem in general.
314
+ input_name = (
315
+ inbound_node_names[index]
316
+ if index < len(inbound_node_names)
317
+ else inbound_node_names[-1]
318
+ )
319
+ node_def.input.append(input_name)
320
+ elif prev_node_name is not None:
321
+ node_def.input.append(prev_node_name)
322
+
323
+ if node_name in input_to_layer:
324
+ node_def.input.append(input_to_layer.get(node_name))
325
+
326
+ prev_node_name = node_def.name
327
+
328
+ return g
@@ -0,0 +1,42 @@
1
+ # Copyright 2019 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
+ """Information on the graph plugin."""
16
+
17
+ # This name is used as the plugin prefix route and to identify this plugin
18
+ # generally, and is also the `plugin_name` for run graphs after data-compat
19
+ # transformations.
20
+ PLUGIN_NAME = "graphs"
21
+ # The Summary API is implemented in TensorFlow because it uses TensorFlow internal APIs.
22
+ # As a result, this SummaryMetadata is a bit unconventional and uses non-public
23
+ # hardcoded name as the plugin name. Please refer to link below for the summary ops.
24
+ # https://github.com/tensorflow/tensorflow/blob/11f4ecb54708865ec757ca64e4805957b05d7570/tensorflow/python/ops/summary_ops_v2.py#L757
25
+ PLUGIN_NAME_RUN_METADATA = "graph_run_metadata"
26
+ # https://github.com/tensorflow/tensorflow/blob/11f4ecb54708865ec757ca64e4805957b05d7570/tensorflow/python/ops/summary_ops_v2.py#L788
27
+ PLUGIN_NAME_RUN_METADATA_WITH_GRAPH = "graph_run_metadata_graph"
28
+ # https://github.com/tensorflow/tensorflow/blob/565952cc2f17fdfd995e25171cf07be0f6f06180/tensorflow/python/ops/summary_ops_v2.py#L825
29
+ PLUGIN_NAME_KERAS_MODEL = "graph_keras_model"
30
+ # Plugin name used for `Event.tagged_run_metadata`. This doesn't fall into one
31
+ # of the above cases because (despite the name) `PLUGIN_NAME_RUN_METADATA` is
32
+ # _required_ to have both profile and op graphs, whereas tagged run metadata
33
+ # need only have profile data.
34
+ PLUGIN_NAME_TAGGED_RUN_METADATA = "graph_tagged_run_metadata"
35
+
36
+ # In the context of the data provider interface, tag name given to a
37
+ # graph read from the `graph_def` field of an `Event` proto, which is
38
+ # not attached to a summary and thus does not have a proper tag name of
39
+ # its own. Run level graphs always represent `GraphDef`s (graphs of
40
+ # TensorFlow ops), never conceptual graphs, profile graphs, etc. This is
41
+ # the only tag name used by the `"graphs"` plugin.
42
+ RUN_GRAPH_NAME = "__run_graph__"
File without changes
@@ -0,0 +1,144 @@
1
+ # Copyright 2017 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
+ """The TensorBoard Histograms plugin.
16
+
17
+ See `http_api.md` in this directory for specifications of the routes for
18
+ this plugin.
19
+ """
20
+
21
+ from werkzeug import wrappers
22
+
23
+ from tensorbored import errors
24
+ from tensorbored import plugin_util
25
+ from tensorbored.backend import http_util
26
+ from tensorbored.data import provider
27
+ from tensorbored.plugins import base_plugin
28
+ from tensorbored.plugins.histogram import metadata
29
+
30
+ _DEFAULT_DOWNSAMPLING = 500 # histograms per time series
31
+
32
+
33
+ class HistogramsPlugin(base_plugin.TBPlugin):
34
+ """Histograms Plugin for TensorBoard.
35
+
36
+ This supports both old-style summaries (created with TensorFlow ops
37
+ that output directly to the `histo` field of the proto) and new-
38
+ style summaries (as created by the
39
+ `tensorboard.plugins.histogram.summary` module).
40
+ """
41
+
42
+ plugin_name = metadata.PLUGIN_NAME
43
+
44
+ # Use a round number + 1 since sampling includes both start and end steps,
45
+ # so N+1 samples corresponds to dividing the step sequence into N intervals.
46
+ SAMPLE_SIZE = 51
47
+
48
+ def __init__(self, context):
49
+ """Instantiates HistogramsPlugin via TensorBoard core.
50
+
51
+ Args:
52
+ context: A base_plugin.TBContext instance.
53
+ """
54
+ self._downsample_to = (context.sampling_hints or {}).get(
55
+ self.plugin_name, _DEFAULT_DOWNSAMPLING
56
+ )
57
+ self._data_provider = context.data_provider
58
+ self._version_checker = plugin_util._MetadataVersionChecker(
59
+ data_kind="histogram",
60
+ latest_known_version=0,
61
+ )
62
+
63
+ def get_plugin_apps(self):
64
+ return {
65
+ "/histograms": self.histograms_route,
66
+ "/tags": self.tags_route,
67
+ }
68
+
69
+ def is_active(self):
70
+ return False # `list_plugins` as called by TB core suffices
71
+
72
+ def index_impl(self, ctx, experiment):
73
+ """Return {runName: {tagName: {displayName: ..., description:
74
+ ...}}}."""
75
+ mapping = self._data_provider.list_tensors(
76
+ ctx,
77
+ experiment_id=experiment,
78
+ plugin_name=metadata.PLUGIN_NAME,
79
+ )
80
+ result = {run: {} for run in mapping}
81
+ for run, tag_to_content in mapping.items():
82
+ for tag, metadatum in tag_to_content.items():
83
+ description = plugin_util.markdown_to_safe_html(
84
+ metadatum.description
85
+ )
86
+ md = metadata.parse_plugin_metadata(metadatum.plugin_content)
87
+ if not self._version_checker.ok(md.version, run, tag):
88
+ continue
89
+ result[run][tag] = {
90
+ "displayName": metadatum.display_name,
91
+ "description": description,
92
+ }
93
+ return result
94
+
95
+ def frontend_metadata(self):
96
+ return base_plugin.FrontendMetadata(
97
+ element_name="tf-histogram-dashboard"
98
+ )
99
+
100
+ def histograms_impl(self, ctx, tag, run, experiment, downsample_to=None):
101
+ """Result of the form `(body, mime_type)`.
102
+
103
+ At most `downsample_to` events will be returned. If this value is
104
+ `None`, then default downsampling will be performed.
105
+
106
+ Raises:
107
+ tensorboard.errors.PublicError: On invalid request.
108
+ """
109
+ sample_count = (
110
+ downsample_to if downsample_to is not None else self._downsample_to
111
+ )
112
+ all_histograms = self._data_provider.read_tensors(
113
+ ctx,
114
+ experiment_id=experiment,
115
+ plugin_name=metadata.PLUGIN_NAME,
116
+ downsample=sample_count,
117
+ run_tag_filter=provider.RunTagFilter(runs=[run], tags=[tag]),
118
+ )
119
+ histograms = all_histograms.get(run, {}).get(tag, None)
120
+ if histograms is None:
121
+ raise errors.NotFoundError(
122
+ "No histogram tag %r for run %r" % (tag, run)
123
+ )
124
+ events = [(e.wall_time, e.step, e.numpy.tolist()) for e in histograms]
125
+ return (events, "application/json")
126
+
127
+ @wrappers.Request.application
128
+ def tags_route(self, request):
129
+ ctx = plugin_util.context(request.environ)
130
+ experiment = plugin_util.experiment_id(request.environ)
131
+ index = self.index_impl(ctx, experiment=experiment)
132
+ return http_util.Respond(request, index, "application/json")
133
+
134
+ @wrappers.Request.application
135
+ def histograms_route(self, request):
136
+ """Given a tag and single run, return array of histogram values."""
137
+ ctx = plugin_util.context(request.environ)
138
+ experiment = plugin_util.experiment_id(request.environ)
139
+ tag = request.args.get("tag")
140
+ run = request.args.get("run")
141
+ body, mime_type = self.histograms_impl(
142
+ ctx, tag, run, experiment=experiment, downsample_to=self.SAMPLE_SIZE
143
+ )
144
+ return http_util.Respond(request, body, mime_type)
@@ -0,0 +1,63 @@
1
+ # Copyright 2017 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
+ """Information about histogram summaries."""
16
+
17
+ from tensorbored.compat.proto import summary_pb2
18
+ from tensorbored.plugins.histogram import plugin_data_pb2
19
+
20
+ PLUGIN_NAME = "histograms"
21
+
22
+ # The most recent value for the `version` field of the
23
+ # `HistogramPluginData` proto.
24
+ PROTO_VERSION = 0
25
+
26
+
27
+ def create_summary_metadata(display_name, description):
28
+ """Create a `summary_pb2.SummaryMetadata` proto for histogram plugin data.
29
+
30
+ Returns:
31
+ A `summary_pb2.SummaryMetadata` protobuf object.
32
+ """
33
+ content = plugin_data_pb2.HistogramPluginData(version=PROTO_VERSION)
34
+ return summary_pb2.SummaryMetadata(
35
+ display_name=display_name,
36
+ summary_description=description,
37
+ plugin_data=summary_pb2.SummaryMetadata.PluginData(
38
+ plugin_name=PLUGIN_NAME, content=content.SerializeToString()
39
+ ),
40
+ )
41
+
42
+
43
+ def parse_plugin_metadata(content):
44
+ """Parse summary metadata to a Python object.
45
+
46
+ Arguments:
47
+ content: The `content` field of a `SummaryMetadata` proto
48
+ corresponding to the histogram plugin.
49
+
50
+ Returns:
51
+ A `HistogramPluginData` protobuf object.
52
+ """
53
+ if not isinstance(content, bytes):
54
+ raise TypeError("Content type must be bytes")
55
+ if content == b"{}":
56
+ # Old-style JSON format. Equivalent to an all-default proto.
57
+ return plugin_data_pb2.HistogramPluginData()
58
+ else:
59
+ result = plugin_data_pb2.HistogramPluginData.FromString(content)
60
+ if result.version == 0:
61
+ return result
62
+ # No other versions known at this time, so no migrations to do.
63
+ return result
@@ -0,0 +1,34 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # source: tensorbored/plugins/histogram/plugin_data.proto
4
+ """Generated protocol buffer code."""
5
+ from google.protobuf import descriptor as _descriptor
6
+ from google.protobuf import descriptor_pool as _descriptor_pool
7
+ from google.protobuf import message as _message
8
+ from google.protobuf import reflection as _reflection
9
+ from google.protobuf import symbol_database as _symbol_database
10
+ # @@protoc_insertion_point(imports)
11
+
12
+ _sym_db = _symbol_database.Default()
13
+
14
+
15
+
16
+
17
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/tensorbored/plugins/histogram/plugin_data.proto\x12\x0btensorbored\"&\n\x13HistogramPluginData\x12\x0f\n\x07version\x18\x01 \x01(\x05\x62\x06proto3')
18
+
19
+
20
+
21
+ _HISTOGRAMPLUGINDATA = DESCRIPTOR.message_types_by_name['HistogramPluginData']
22
+ HistogramPluginData = _reflection.GeneratedProtocolMessageType('HistogramPluginData', (_message.Message,), {
23
+ 'DESCRIPTOR' : _HISTOGRAMPLUGINDATA,
24
+ '__module__' : 'tensorbored.plugins.histogram.plugin_data_pb2'
25
+ # @@protoc_insertion_point(class_scope:tensorbored.HistogramPluginData)
26
+ })
27
+ _sym_db.RegisterMessage(HistogramPluginData)
28
+
29
+ if _descriptor._USE_C_DESCRIPTORS == False:
30
+
31
+ DESCRIPTOR._options = None
32
+ _HISTOGRAMPLUGINDATA._serialized_start=64
33
+ _HISTOGRAMPLUGINDATA._serialized_end=102
34
+ # @@protoc_insertion_point(module_scope)