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,116 @@
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 Distributions (a.k.a. compressed 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 plugin_util
24
+ from tensorbored.backend import http_util
25
+ from tensorbored.plugins import base_plugin
26
+ from tensorbored.plugins.distribution import compressor
27
+ from tensorbored.plugins.distribution import metadata
28
+ from tensorbored.plugins.histogram import histograms_plugin
29
+
30
+
31
+ class DistributionsPlugin(base_plugin.TBPlugin):
32
+ """Distributions Plugin for TensorBoard.
33
+
34
+ This supports both old-style summaries (created with TensorFlow ops
35
+ that output directly to the `histo` field of the proto) and new-
36
+ style summaries (as created by the
37
+ `tensorboard.plugins.histogram.summary` module).
38
+ """
39
+
40
+ plugin_name = metadata.PLUGIN_NAME
41
+
42
+ # Use a round number + 1 since sampling includes both start and end steps,
43
+ # so N+1 samples corresponds to dividing the step sequence into N intervals.
44
+ SAMPLE_SIZE = 501
45
+
46
+ def __init__(self, context):
47
+ """Instantiates DistributionsPlugin via TensorBoard core.
48
+
49
+ Args:
50
+ context: A base_plugin.TBContext instance.
51
+ """
52
+ self._histograms_plugin = histograms_plugin.HistogramsPlugin(context)
53
+
54
+ def get_plugin_apps(self):
55
+ return {
56
+ "/distributions": self.distributions_route,
57
+ "/tags": self.tags_route,
58
+ }
59
+
60
+ def is_active(self):
61
+ """This plugin is active iff any run has at least one histogram tag.
62
+
63
+ (The distributions plugin uses the same data source as the
64
+ histogram plugin.)
65
+ """
66
+ return self._histograms_plugin.is_active()
67
+
68
+ def data_plugin_names(self):
69
+ return (self._histograms_plugin.plugin_name,)
70
+
71
+ def frontend_metadata(self):
72
+ return base_plugin.FrontendMetadata(
73
+ element_name="tf-distribution-dashboard",
74
+ )
75
+
76
+ def distributions_impl(self, ctx, tag, run, experiment):
77
+ """Result of the form `(body, mime_type)`.
78
+
79
+ Raises:
80
+ tensorboard.errors.PublicError: On invalid request.
81
+ """
82
+ histograms, mime_type = self._histograms_plugin.histograms_impl(
83
+ ctx, tag, run, experiment=experiment, downsample_to=self.SAMPLE_SIZE
84
+ )
85
+ return (
86
+ [self._compress(histogram) for histogram in histograms],
87
+ mime_type,
88
+ )
89
+
90
+ def _compress(self, histogram):
91
+ wall_time, step, buckets = histogram
92
+ converted_buckets = compressor.compress_histogram(buckets)
93
+ return [wall_time, step, converted_buckets]
94
+
95
+ def index_impl(self, ctx, experiment):
96
+ return self._histograms_plugin.index_impl(ctx, experiment=experiment)
97
+
98
+ @wrappers.Request.application
99
+ def tags_route(self, request):
100
+ ctx = plugin_util.context(request.environ)
101
+ experiment = plugin_util.experiment_id(request.environ)
102
+ index = self.index_impl(ctx, experiment=experiment)
103
+ return http_util.Respond(request, index, "application/json")
104
+
105
+ @wrappers.Request.application
106
+ def distributions_route(self, request):
107
+ """Given a tag and single run, return an array of compressed
108
+ histograms."""
109
+ ctx = plugin_util.context(request.environ)
110
+ experiment = plugin_util.experiment_id(request.environ)
111
+ tag = request.args.get("tag")
112
+ run = request.args.get("run")
113
+ body, mime_type = self.distributions_impl(
114
+ ctx, tag, run, experiment=experiment
115
+ )
116
+ return http_util.Respond(request, body, mime_type)
@@ -0,0 +1,19 @@
1
+ # Copyright 2020 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 distributions plugin."""
16
+
17
+ # This name is used as the plugin prefix route and to identify this plugin
18
+ # generally.
19
+ PLUGIN_NAME = "distributions"
File without changes
@@ -0,0 +1,129 @@
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
+ """Utilities for graph plugin."""
16
+
17
+ from tensorbored.compat.proto import graph_pb2
18
+
19
+
20
+ def _prefixed_op_name(prefix, op_name):
21
+ return "%s/%s" % (prefix, op_name)
22
+
23
+
24
+ def _prefixed_func_name(prefix, func_name):
25
+ """Returns function name prefixed with `prefix`.
26
+
27
+ For function libraries, which are often created out of autographed Python
28
+ function, are factored out in the graph vis. They are grouped under a
29
+ function name which often has a shape of
30
+ `__inference_[py_func_name]_[numeric_suffix]`.
31
+
32
+ While it does not have some unique information about which graph it is from,
33
+ creating another wrapping structure with graph prefix and "/" is less than
34
+ ideal so we join the prefix and func_name using underscore.
35
+
36
+ TODO(stephanwlee): add business logic to strip "__inference_" for more user
37
+ friendlier name
38
+ """
39
+ return "%s_%s" % (prefix, func_name)
40
+
41
+
42
+ def _add_with_prepended_names(prefix, graph_to_add, destination_graph):
43
+ for node in graph_to_add.node:
44
+ new_node = destination_graph.node.add()
45
+ new_node.CopyFrom(node)
46
+ new_node.name = _prefixed_op_name(prefix, node.name)
47
+ new_node.input[:] = [
48
+ _prefixed_op_name(prefix, input_name) for input_name in node.input
49
+ ]
50
+
51
+ # Remap tf.function method name in the PartitionedCall. 'f' is short for
52
+ # function.
53
+ if new_node.op == "PartitionedCall" and new_node.attr["f"]:
54
+
55
+ new_node.attr["f"].func.name = _prefixed_func_name(
56
+ prefix,
57
+ new_node.attr["f"].func.name,
58
+ )
59
+
60
+ for func in graph_to_add.library.function:
61
+ new_func = destination_graph.library.function.add()
62
+ new_func.CopyFrom(func)
63
+ new_func.signature.name = _prefixed_func_name(
64
+ prefix, new_func.signature.name
65
+ )
66
+
67
+ for gradient in graph_to_add.library.gradient:
68
+ new_gradient = destination_graph.library.gradient.add()
69
+ new_gradient.CopyFrom(gradient)
70
+ new_gradient.function_name = _prefixed_func_name(
71
+ prefix,
72
+ new_gradient.function_name,
73
+ )
74
+ new_gradient.gradient_func = _prefixed_func_name(
75
+ prefix,
76
+ new_gradient.gradient_func,
77
+ )
78
+
79
+
80
+ def merge_graph_defs(graph_defs):
81
+ """Merges GraphDefs by adding unique prefix, `graph_{ind}`, to names.
82
+
83
+ All GraphDefs are expected to be of TensorBoard's.
84
+
85
+ When collecting graphs using the `tf.summary.trace` API, node names are not
86
+ guranteed to be unique. When non-unique names are not considered, it can
87
+ lead to graph visualization showing them as one which creates inaccurate
88
+ depiction of the flow of the graph (e.g., if there are A -> B -> C and D ->
89
+ B -> E, you may see {A, D} -> B -> E). To prevent such graph, we checked
90
+ for uniquenss while merging but it resulted in
91
+ https://github.com/tensorflow/tensorboard/issues/1929.
92
+
93
+ To remedy these issues, we simply "apply name scope" on each graph by
94
+ prefixing it with unique name (with a chance of collision) to create
95
+ unconnected group of graphs.
96
+
97
+ In case there is only one graph def passed, it returns the original
98
+ graph_def. In case no graph defs are passed, it returns an empty GraphDef.
99
+
100
+ Args:
101
+ graph_defs: TensorBoard GraphDefs to merge.
102
+
103
+ Returns:
104
+ TensorBoard GraphDef that merges all graph_defs with unique prefixes.
105
+
106
+ Raises:
107
+ ValueError in case GraphDef versions mismatch.
108
+ """
109
+ if len(graph_defs) == 1:
110
+ return graph_defs[0]
111
+ elif len(graph_defs) == 0:
112
+ return graph_pb2.GraphDef()
113
+
114
+ dst_graph_def = graph_pb2.GraphDef()
115
+
116
+ if graph_defs[0].versions.producer:
117
+ dst_graph_def.versions.CopyFrom(graph_defs[0].versions)
118
+
119
+ for index, graph_def in enumerate(graph_defs):
120
+ if dst_graph_def.versions.producer != graph_def.versions.producer:
121
+ raise ValueError("Cannot combine GraphDefs of different versions.")
122
+
123
+ _add_with_prepended_names(
124
+ "graph_%d" % (index + 1),
125
+ graph_def,
126
+ dst_graph_def,
127
+ )
128
+
129
+ return dst_graph_def
@@ -0,0 +1,336 @@
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 Graphs plugin."""
16
+
17
+ import json
18
+ from werkzeug import wrappers
19
+
20
+ from tensorbored import errors
21
+ from tensorbored import plugin_util
22
+ from tensorbored.backend import http_util
23
+ from tensorbored.backend import process_graph
24
+ from tensorbored.compat.proto import config_pb2
25
+ from tensorbored.compat.proto import graph_pb2
26
+ from tensorbored.data import provider
27
+ from tensorbored.plugins import base_plugin
28
+ from tensorbored.plugins.graph import graph_util
29
+ from tensorbored.plugins.graph import keras_util
30
+ from tensorbored.plugins.graph import metadata
31
+ from tensorbored.util import tb_logging
32
+
33
+ logger = tb_logging.get_logger()
34
+
35
+
36
+ class GraphsPlugin(base_plugin.TBPlugin):
37
+ """Graphs Plugin for TensorBoard."""
38
+
39
+ plugin_name = metadata.PLUGIN_NAME
40
+
41
+ def __init__(self, context):
42
+ """Instantiates GraphsPlugin via TensorBoard core.
43
+
44
+ Args:
45
+ context: A base_plugin.TBContext instance.
46
+ """
47
+ self._data_provider = context.data_provider
48
+
49
+ def get_plugin_apps(self):
50
+ return {
51
+ "/graph": self.graph_route,
52
+ "/info": self.info_route,
53
+ "/run_metadata": self.run_metadata_route,
54
+ }
55
+
56
+ def is_active(self):
57
+ """The graphs plugin is active iff any run has a graph or metadata."""
58
+ return False # `list_plugins` as called by TB core suffices
59
+
60
+ def data_plugin_names(self):
61
+ return (
62
+ metadata.PLUGIN_NAME,
63
+ metadata.PLUGIN_NAME_RUN_METADATA,
64
+ metadata.PLUGIN_NAME_RUN_METADATA_WITH_GRAPH,
65
+ metadata.PLUGIN_NAME_KERAS_MODEL,
66
+ metadata.PLUGIN_NAME_TAGGED_RUN_METADATA,
67
+ )
68
+
69
+ def frontend_metadata(self):
70
+ return base_plugin.FrontendMetadata(
71
+ element_name="tf-graph-dashboard",
72
+ # TODO(@chihuahua): Reconcile this setting with Health Pills.
73
+ disable_reload=True,
74
+ )
75
+
76
+ def info_impl(self, ctx, experiment=None):
77
+ """Returns a dict of all runs and their data availabilities."""
78
+ result = {}
79
+
80
+ def add_row_item(run, tag=None):
81
+ run_item = result.setdefault(
82
+ run,
83
+ {
84
+ "run": run,
85
+ "tags": {},
86
+ # A run-wide GraphDef of ops.
87
+ "run_graph": False,
88
+ },
89
+ )
90
+
91
+ tag_item = None
92
+ if tag:
93
+ tag_item = run_item.get("tags").setdefault(
94
+ tag,
95
+ {
96
+ "tag": tag,
97
+ "conceptual_graph": False,
98
+ # A tagged GraphDef of ops.
99
+ "op_graph": False,
100
+ "profile": False,
101
+ },
102
+ )
103
+ return (run_item, tag_item)
104
+
105
+ mapping = self._data_provider.list_blob_sequences(
106
+ ctx,
107
+ experiment_id=experiment,
108
+ plugin_name=metadata.PLUGIN_NAME_RUN_METADATA_WITH_GRAPH,
109
+ )
110
+ for run_name, tags in mapping.items():
111
+ for tag, tag_data in tags.items():
112
+ # The Summary op is defined in TensorFlow and does not use a stringified proto
113
+ # as a content of plugin data. It contains single string that denotes a version.
114
+ # https://github.com/tensorflow/tensorflow/blob/11f4ecb54708865ec757ca64e4805957b05d7570/tensorflow/python/ops/summary_ops_v2.py#L789-L790
115
+ if tag_data.plugin_content != b"1":
116
+ logger.warning(
117
+ "Ignoring unrecognizable version of RunMetadata."
118
+ )
119
+ continue
120
+ _, tag_item = add_row_item(run_name, tag)
121
+ tag_item["op_graph"] = True
122
+
123
+ # Tensors associated with plugin name metadata.PLUGIN_NAME_RUN_METADATA
124
+ # contain both op graph and profile information.
125
+ mapping = self._data_provider.list_blob_sequences(
126
+ ctx,
127
+ experiment_id=experiment,
128
+ plugin_name=metadata.PLUGIN_NAME_RUN_METADATA,
129
+ )
130
+ for run_name, tags in mapping.items():
131
+ for tag, tag_data in tags.items():
132
+ if tag_data.plugin_content != b"1":
133
+ logger.warning(
134
+ "Ignoring unrecognizable version of RunMetadata."
135
+ )
136
+ continue
137
+ _, tag_item = add_row_item(run_name, tag)
138
+ tag_item["profile"] = True
139
+ tag_item["op_graph"] = True
140
+
141
+ # Tensors associated with plugin name metadata.PLUGIN_NAME_KERAS_MODEL
142
+ # contain serialized Keras model in JSON format.
143
+ mapping = self._data_provider.list_blob_sequences(
144
+ ctx,
145
+ experiment_id=experiment,
146
+ plugin_name=metadata.PLUGIN_NAME_KERAS_MODEL,
147
+ )
148
+ for run_name, tags in mapping.items():
149
+ for tag, tag_data in tags.items():
150
+ if tag_data.plugin_content != b"1":
151
+ logger.warning(
152
+ "Ignoring unrecognizable version of RunMetadata."
153
+ )
154
+ continue
155
+ _, tag_item = add_row_item(run_name, tag)
156
+ tag_item["conceptual_graph"] = True
157
+
158
+ mapping = self._data_provider.list_blob_sequences(
159
+ ctx,
160
+ experiment_id=experiment,
161
+ plugin_name=metadata.PLUGIN_NAME,
162
+ )
163
+ for run_name, tags in mapping.items():
164
+ if metadata.RUN_GRAPH_NAME in tags:
165
+ run_item, _ = add_row_item(run_name, None)
166
+ run_item["run_graph"] = True
167
+
168
+ # Top level `Event.tagged_run_metadata` represents profile data only.
169
+ mapping = self._data_provider.list_blob_sequences(
170
+ ctx,
171
+ experiment_id=experiment,
172
+ plugin_name=metadata.PLUGIN_NAME_TAGGED_RUN_METADATA,
173
+ )
174
+ for run_name, tags in mapping.items():
175
+ for tag in tags:
176
+ _, tag_item = add_row_item(run_name, tag)
177
+ tag_item["profile"] = True
178
+
179
+ return result
180
+
181
+ def _read_blob(self, ctx, experiment, plugin_names, run, tag):
182
+ for plugin_name in plugin_names:
183
+ blob_sequences = self._data_provider.read_blob_sequences(
184
+ ctx,
185
+ experiment_id=experiment,
186
+ plugin_name=plugin_name,
187
+ run_tag_filter=provider.RunTagFilter(runs=[run], tags=[tag]),
188
+ downsample=1,
189
+ )
190
+ blob_sequence_data = blob_sequences.get(run, {}).get(tag, ())
191
+ try:
192
+ blob_ref = blob_sequence_data[0].values[0]
193
+ except IndexError:
194
+ continue
195
+ return self._data_provider.read_blob(
196
+ ctx, blob_key=blob_ref.blob_key
197
+ )
198
+ raise errors.NotFoundError()
199
+
200
+ def graph_impl(
201
+ self,
202
+ ctx,
203
+ run,
204
+ tag,
205
+ is_conceptual,
206
+ experiment=None,
207
+ limit_attr_size=None,
208
+ large_attrs_key=None,
209
+ ):
210
+ """Result of the form `(body, mime_type)`; may raise `NotFound`."""
211
+ if is_conceptual:
212
+ keras_model_config = json.loads(
213
+ self._read_blob(
214
+ ctx,
215
+ experiment,
216
+ [metadata.PLUGIN_NAME_KERAS_MODEL],
217
+ run,
218
+ tag,
219
+ )
220
+ )
221
+ graph = keras_util.keras_model_to_graph_def(keras_model_config)
222
+
223
+ elif tag is None:
224
+ graph_raw = self._read_blob(
225
+ ctx,
226
+ experiment,
227
+ [metadata.PLUGIN_NAME],
228
+ run,
229
+ metadata.RUN_GRAPH_NAME,
230
+ )
231
+ graph = graph_pb2.GraphDef.FromString(graph_raw)
232
+
233
+ else:
234
+ # Op graph: could be either of two plugins. (Cf. `info_impl`.)
235
+ plugins = [
236
+ metadata.PLUGIN_NAME_RUN_METADATA,
237
+ metadata.PLUGIN_NAME_RUN_METADATA_WITH_GRAPH,
238
+ ]
239
+ raw_run_metadata = self._read_blob(
240
+ ctx, experiment, plugins, run, tag
241
+ )
242
+ run_metadata = config_pb2.RunMetadata.FromString(raw_run_metadata)
243
+ graph = graph_util.merge_graph_defs(
244
+ [
245
+ func_graph.pre_optimization_graph
246
+ for func_graph in run_metadata.function_graphs
247
+ ]
248
+ )
249
+
250
+ # This next line might raise a ValueError if the limit parameters
251
+ # are invalid (size is negative, size present but key absent, etc.).
252
+ process_graph.prepare_graph_for_ui(
253
+ graph, limit_attr_size, large_attrs_key
254
+ )
255
+ return (str(graph), "text/x-protobuf") # pbtxt
256
+
257
+ def run_metadata_impl(self, ctx, experiment, run, tag):
258
+ """Result of the form `(body, mime_type)`; may raise `NotFound`."""
259
+ # Profile graph: could be either of two plugins. (Cf. `info_impl`.)
260
+ plugins = [
261
+ metadata.PLUGIN_NAME_TAGGED_RUN_METADATA,
262
+ metadata.PLUGIN_NAME_RUN_METADATA,
263
+ ]
264
+ raw_run_metadata = self._read_blob(ctx, experiment, plugins, run, tag)
265
+ run_metadata = config_pb2.RunMetadata.FromString(raw_run_metadata)
266
+ return (str(run_metadata), "text/x-protobuf") # pbtxt
267
+
268
+ @wrappers.Request.application
269
+ def info_route(self, request):
270
+ ctx = plugin_util.context(request.environ)
271
+ experiment = plugin_util.experiment_id(request.environ)
272
+ info = self.info_impl(ctx, experiment)
273
+ return http_util.Respond(request, info, "application/json")
274
+
275
+ @wrappers.Request.application
276
+ def graph_route(self, request):
277
+ """Given a single run, return the graph definition in protobuf
278
+ format."""
279
+ ctx = plugin_util.context(request.environ)
280
+ experiment = plugin_util.experiment_id(request.environ)
281
+ run = request.args.get("run")
282
+ tag = request.args.get("tag")
283
+ conceptual_arg = request.args.get("conceptual", False)
284
+ is_conceptual = True if conceptual_arg == "true" else False
285
+
286
+ if run is None:
287
+ return http_util.Respond(
288
+ request, 'query parameter "run" is required', "text/plain", 400
289
+ )
290
+
291
+ limit_attr_size = request.args.get("limit_attr_size", None)
292
+ if limit_attr_size is not None:
293
+ try:
294
+ limit_attr_size = int(limit_attr_size)
295
+ except ValueError:
296
+ return http_util.Respond(
297
+ request,
298
+ "query parameter `limit_attr_size` must be an integer",
299
+ "text/plain",
300
+ 400,
301
+ )
302
+
303
+ large_attrs_key = request.args.get("large_attrs_key", None)
304
+
305
+ try:
306
+ result = self.graph_impl(
307
+ ctx,
308
+ run,
309
+ tag,
310
+ is_conceptual,
311
+ experiment,
312
+ limit_attr_size,
313
+ large_attrs_key,
314
+ )
315
+ except ValueError as e:
316
+ return http_util.Respond(request, e.message, "text/plain", code=400)
317
+ body, mime_type = result
318
+ return http_util.Respond(request, body, mime_type)
319
+
320
+ @wrappers.Request.application
321
+ def run_metadata_route(self, request):
322
+ """Given a tag and a run, return the session.run() metadata."""
323
+ ctx = plugin_util.context(request.environ)
324
+ experiment = plugin_util.experiment_id(request.environ)
325
+ tag = request.args.get("tag")
326
+ run = request.args.get("run")
327
+ if tag is None:
328
+ return http_util.Respond(
329
+ request, 'query parameter "tag" is required', "text/plain", 400
330
+ )
331
+ if run is None:
332
+ return http_util.Respond(
333
+ request, 'query parameter "run" is required', "text/plain", 400
334
+ )
335
+ body, mime_type = self.run_metadata_impl(ctx, experiment, run, tag)
336
+ return http_util.Respond(request, body, mime_type)