7
7
import copy
8
8
import os
9
9
from collections import defaultdict
10
+ from types import ModuleType
10
11
from typing import Any , Dict , List , Optional , Set , Tuple , Union , cast
11
12
12
13
import numpy as np
13
14
import pandas as pd
14
- import tensorflow as tf
15
15
from tensorboard .backend .event_processing .event_accumulator import (
16
16
AUDIO , COMPRESSED_HISTOGRAMS , HISTOGRAMS , IMAGES , SCALARS ,
17
17
STORE_EVERYTHING_SIZE_GUIDANCE , TENSORS , AudioEvent , EventAccumulator ,
18
18
HistogramEvent , ImageEvent , ScalarEvent , TensorEvent )
19
19
from tensorboard .plugins .hparams .plugin_data_pb2 import HParamsPluginData
20
+ try :
21
+ import tensorflow
22
+ except ImportError :
23
+ tensorflow = None
20
24
21
25
# pylint: disable=W0105
22
26
"""
47
51
}
48
52
49
53
ALL_EVENT_TYPES = {SCALARS , TENSORS , HISTOGRAMS , IMAGES , AUDIO , HPARAMS , TEXT }
54
+ REDUCED_EVENT_TYPES = {SCALARS , HISTOGRAMS , HPARAMS }
50
55
ALL_EXTRA_COLUMNS = {'dir_name' , 'file_name' , 'wall_time' , 'min' , 'max' , 'num' ,
51
56
'sum' , 'sum_squares' , 'width' , 'height' , 'content_type' ,
52
57
'length_frames' , 'sample_rate' }
@@ -98,7 +103,7 @@ def __init__(self, log_path: str, *, pivot=False, extra_columns=None,
98
103
:param event_types: Specifies the event types to parse, \
99
104
defaults to all event types.
100
105
:type event_types: Set[{'scalars', 'tensors', 'histograms', 'images', \
101
- 'audio'}]
106
+ 'audio', 'hparams', 'text' }]
102
107
"""
103
108
self ._log_path : str = log_path
104
109
"""Load directory location, or load file location."""
@@ -114,6 +119,8 @@ def __init__(self, log_path: str, *, pivot=False, extra_columns=None,
114
119
"""Determines whether the DataFrame is stored in wide format."""
115
120
self ._event_types : Set [str ] = (event_types or ALL_EVENT_TYPES ).copy ()
116
121
"""Specifies the event types to parse."""
122
+ if tensorflow is None :
123
+ self ._event_types = (event_types or REDUCED_EVENT_TYPES ).copy ()
117
124
if not isinstance (self ._event_types , set ):
118
125
raise ValueError (f"`event_types` should be a { set } instead of \
119
126
{ str (type (self ._event_types ))} " )
@@ -148,7 +155,8 @@ def __init__(self, log_path: str, *, pivot=False, extra_columns=None,
148
155
filepath = os .path .join (self .log_path , filename )
149
156
r = SummaryReader (filepath ,
150
157
pivot = self ._pivot ,
151
- extra_columns = self ._extra_columns )
158
+ extra_columns = self ._extra_columns ,
159
+ event_types = self ._event_types )
152
160
self ._children [filename ] = r
153
161
154
162
@property
@@ -250,6 +258,10 @@ def get_events(self, event_type: str) -> pd.DataFrame:
250
258
"""
251
259
if event_type not in ALL_EVENT_TYPES :
252
260
raise ValueError (f"Unknown event_type: { event_type } " )
261
+ if event_type not in REDUCED_EVENT_TYPES and tensorflow is None :
262
+ self ._get_tensorflow () # raise error
263
+ if event_type not in self ._event_types :
264
+ raise ValueError (f"event_type is ignored by user: { event_type } " )
253
265
group_columns : List [Any ] = list (filter (
254
266
lambda x : x in self ._extra_columns , ['dir_name' , 'file_name' ]))
255
267
dfs = []
@@ -425,6 +437,13 @@ def buckets_to_histogram_dict(lst: np.ndarray) -> Dict[str, Any]:
425
437
"""
426
438
return SummaryReader .tensor_to_histogram (lst )
427
439
440
+ @staticmethod
441
+ def _get_tensorflow () -> ModuleType :
442
+ if tensorflow is not None :
443
+ return tensorflow
444
+ raise ModuleNotFoundError ("No module named 'tensorflow'. " +
445
+ "Please install 'tensorflow' or 'tensorflow-cpu'." )
446
+
428
447
@staticmethod
429
448
def tensor_to_image (tensor : np .ndarray ) -> Dict [str , Any ]:
430
449
"""Convert a tensor to image dictionary.
@@ -434,6 +453,8 @@ def tensor_to_image(tensor: np.ndarray) -> Dict[str, Any]:
434
453
:return: A `{image_data_name: image_data}` dictionary.
435
454
:rtype: Dict[str, Any]
436
455
"""
456
+ # pylint: disable=C0103
457
+ tf = SummaryReader ._get_tensorflow ()
437
458
lst = list (map (tf .image .decode_image , tensor [2 :]))
438
459
lst = list (map (lambda x : x .numpy (), lst ))
439
460
image = np .stack (lst , axis = 0 )
@@ -455,6 +476,8 @@ def tensor_to_audio(tensor: np.ndarray) -> Dict[str, Any]:
455
476
:return: A `{audio_data_name: audio_data}` dictionary.
456
477
:rtype: Dict[str, Any]
457
478
"""
479
+ # pylint: disable=C0103
480
+ tf = SummaryReader ._get_tensorflow ()
458
481
assert tensor [:, 1 ].tolist () == [b'' ] * tensor .shape [0 ]
459
482
lst = list (map (tf .audio .decode_wav , tensor [:, 0 ]))
460
483
audio_lst = list (map (lambda x : x [0 ].numpy (), lst ))
@@ -650,6 +673,10 @@ def _get_tensor_cols(self, tag_to_events: Dict[str, TensorEvent]) -> \
650
673
Dict [str , List [Any ]]:
651
674
"""Return a dict of lists based on the tags and TensorEvents."""
652
675
cols = self ._get_default_cols (tag_to_events )
676
+ if len (tag_to_events ) == 0 :
677
+ return cols
678
+ # pylint: disable=C0103
679
+ tf = SummaryReader ._get_tensorflow ()
653
680
idx = 0
654
681
for tag , events in tag_to_events .items ():
655
682
for e in events :
@@ -700,8 +727,11 @@ def _get_histogram_cols(self, tag_to_events: Dict[str, HistogramEvent]) \
700
727
def _get_image_cols (self , tag_to_events : Dict [str , ImageEvent ]) -> \
701
728
Dict [str , List [Any ]]:
702
729
"""Return a dict of lists based on the tags and ImageEvent."""
703
-
704
730
cols = self ._get_default_cols (tag_to_events )
731
+ if len (tag_to_events ) == 0 :
732
+ return cols
733
+ # pylint: disable=C0103
734
+ tf = SummaryReader ._get_tensorflow ()
705
735
idx = 0
706
736
for tag , events in tag_to_events .items ():
707
737
for e in events :
@@ -728,6 +758,10 @@ def _get_audio_cols(self, tag_to_events: Dict[str, AudioEvent]) -> \
728
758
Dict [str , List [Any ]]:
729
759
"""Return a dict of lists based on the tags and AudioEvent."""
730
760
cols = self ._get_default_cols (tag_to_events )
761
+ if len (tag_to_events ) == 0 :
762
+ return cols
763
+ # pylint: disable=C0103
764
+ tf = SummaryReader ._get_tensorflow ()
731
765
idx = 0
732
766
for tag , events in tag_to_events .items ():
733
767
for e in events :
@@ -770,6 +804,10 @@ def _get_text_cols(self, tag_to_events: Dict[str, TensorEvent]) -> \
770
804
Dict [str , List [Any ]]:
771
805
"""Return a dict of lists based on the tags and TensorEvent."""
772
806
cols = self ._get_default_cols (tag_to_events )
807
+ if len (tag_to_events ) == 0 :
808
+ return cols
809
+ # pylint: disable=C0103
810
+ tf = SummaryReader ._get_tensorflow ()
773
811
idx = 0
774
812
for tag , events in tag_to_events .items ():
775
813
for e in events :
@@ -894,8 +932,9 @@ def children(self) -> Dict[str, 'SummaryReader']:
894
932
895
933
@property
896
934
def raw_tags (self ) -> Dict [str , List [str ]]:
897
- """Returns a dictionary containing a list of raw tags for each raw event type.
898
- This property is only supported when `log_path` is a event file.
935
+ """Returns a dictionary containing a list of raw tags for each raw
936
+ event type. This property is only supported when `log_path` is a
937
+ event file.
899
938
900
939
:return: A `{eventType: ['list', 'of', 'tags']}` dictionary.
901
940
:rtype: Dict[str, List[str]]
@@ -1013,17 +1052,17 @@ def _make_empty_dict(data) -> Dict[str, Any]:
1013
1052
:rtype: Dict[str, Any]
1014
1053
"""
1015
1054
return {
1016
- IMAGES : [] ,
1017
- AUDIO : [] ,
1055
+ IMAGES : copy . deepcopy ( data ) ,
1056
+ AUDIO : copy . deepcopy ( data ) ,
1018
1057
HISTOGRAMS : copy .deepcopy (data ),
1019
1058
SCALARS : copy .deepcopy (data ),
1020
1059
# COMPRESSED_HISTOGRAMS: [],
1021
1060
TENSORS : copy .deepcopy (data ),
1022
1061
# GRAPH: [],
1023
1062
# META_GRAPH: [],
1024
1063
# RUN_METADATA: [],
1025
- HPARAMS : [] ,
1026
- TEXT : [] ,
1064
+ HPARAMS : copy . deepcopy ( data ) ,
1065
+ TEXT : copy . deepcopy ( data ) ,
1027
1066
}
1028
1067
1029
1068
def __repr__ (self ) -> str :
0 commit comments