@@ -97,7 +97,6 @@ def _expand_paths(self, activations, original_paths):
9797 index = [argsort_indices [i ] for i in sorted_index ]
9898 return activations [{'stimulus_path' : index }]
9999
100-
101100 def register_batch_activations_hook (self , hook ):
102101 r"""
103102 The hook will be called every time a batch of activations is retrieved.
@@ -195,26 +194,32 @@ def _package(self, layer_activations, stimuli_paths):
195194 def _package_layer (self , layer_activations , layer , stimuli_paths ):
196195 assert layer_activations .shape [0 ] == len (stimuli_paths )
197196 activations , flatten_indices = flatten (layer_activations , return_index = True ) # collapse for single neuroid dim
198- assert flatten_indices . shape [ 1 ] in [ 1 , 2 , 3 ]
199- # see comment in _package for an explanation why we cannot simply have 'channel' for the FC layer
200- if flatten_indices . shape [ 1 ] == 1 : # FC
197+ flatten_coord_names = None
198+ if flatten_indices . shape [ 1 ] == 1 : # fully connected, e.g. classifier
199+ # see comment in _package for an explanation why we cannot simply have 'channel' for the FC layer
201200 flatten_coord_names = ['channel' , 'channel_x' , 'channel_y' ]
202- elif flatten_indices .shape [1 ] == 2 : # Transformer
201+ elif flatten_indices .shape [1 ] == 2 : # Transformer, e.g. ViT
203202 flatten_coord_names = ['channel' , 'embedding' ]
204- elif flatten_indices .shape [1 ] == 3 : # 2DConv
203+ elif flatten_indices .shape [1 ] == 3 : # 2DConv, e.g. resnet
205204 flatten_coord_names = ['channel' , 'channel_x' , 'channel_y' ]
206- flatten_coords = {flatten_coord_names [i ]: [sample_index [i ] if i < flatten_indices .shape [1 ] else np .nan for sample_index in flatten_indices ]
207- for i in range (len (flatten_coord_names ))}
208- layer_assembly = NeuroidAssembly (
209- activations ,
210- coords = {** {'stimulus_path' : stimuli_paths ,
211- 'neuroid_num' : ('neuroid' , list (range (activations .shape [1 ]))),
212- 'model' : ('neuroid' , [self .identifier ] * activations .shape [1 ]),
213- 'layer' : ('neuroid' , [layer ] * activations .shape [1 ]),
214- },
215- ** {coord : ('neuroid' , values ) for coord , values in flatten_coords .items ()}},
216- dims = ['stimulus_path' , 'neuroid' ]
217- )
205+ elif flatten_indices .shape [1 ] == 4 : # temporal sliding window, e.g. omnivron
206+ flatten_coord_names = ['channel_temporal' , 'channel_x' , 'channel_y' , 'channel' ]
207+ else :
208+ # we still package the activations, but are unable to provide channel information
209+ self ._logger .debug (f"Unknown layer activations shape { layer_activations .shape } , not inferring channels" )
210+
211+ # build assembly
212+ coords = {'stimulus_path' : stimuli_paths ,
213+ 'neuroid_num' : ('neuroid' , list (range (activations .shape [1 ]))),
214+ 'model' : ('neuroid' , [self .identifier ] * activations .shape [1 ]),
215+ 'layer' : ('neuroid' , [layer ] * activations .shape [1 ]),
216+ }
217+ if flatten_coord_names :
218+ flatten_coords = {flatten_coord_names [i ]: [sample_index [i ] if i < flatten_indices .shape [1 ] else np .nan
219+ for sample_index in flatten_indices ]
220+ for i in range (len (flatten_coord_names ))}
221+ coords = {** coords , ** {coord : ('neuroid' , values ) for coord , values in flatten_coords .items ()}}
222+ layer_assembly = NeuroidAssembly (activations , coords = coords , dims = ['stimulus_path' , 'neuroid' ])
218223 neuroid_id = ["." .join ([f"{ value } " for value in values ]) for values in zip (* [
219224 layer_assembly [coord ].values for coord in ['model' , 'layer' , 'neuroid_num' ]])]
220225 layer_assembly ['neuroid_id' ] = 'neuroid' , neuroid_id
0 commit comments