@@ -343,21 +343,22 @@ def activations_keras(model, X, fmt='longform', plot='boxplot'):
343343 # return summary statistics for matplotlib.axes.Axes.bxp
344344 # or histogram bin edges and heights
345345 data = []
346-
347- for layer in model .layers :
348- print (f" { layer .name } " )
349- if not isinstance (layer , keras .layers .InputLayer ):
350- y = _get_output (layer , X , model .input ).flatten ()
351- y = abs (y [y != 0 ])
352- if len (y ) == 0 :
353- print (f'Activations for { layer .name } are only zeros, ignoring.' )
354- continue
355- if fmt == 'longform' :
356- data ['x' ].extend (y .tolist ())
357- data ['weight' ].extend ([layer .name for i in range (len (y ))])
358- elif fmt == 'summary' :
359- data .append (array_to_summary (y , fmt = plot ))
360- data [- 1 ]['weight' ] = layer .name
346+ outputs = _get_outputs (
347+ [layer for layer in model .layers if not isinstance (layer , keras .layers .InputLayer )], X , model .input
348+ )
349+ for layer_name , y in outputs .items ():
350+ print (f" { layer_name } " )
351+ y = y .flatten ()
352+ y = abs (y [y != 0 ])
353+ if len (y ) == 0 :
354+ print (f'Activations for { layer_name } are only zeros, ignoring.' )
355+ continue
356+ if fmt == 'longform' :
357+ data ['x' ].extend (y .tolist ())
358+ data ['weight' ].extend ([layer_name for i in range (len (y ))])
359+ elif fmt == 'summary' :
360+ data .append (array_to_summary (y , fmt = plot ))
361+ data [- 1 ]['weight' ] = layer_name
361362
362363 if fmt == 'longform' :
363364 data = pandas .DataFrame (data )
@@ -544,10 +545,10 @@ def _is_ignored_layer(layer):
544545 return False
545546
546547
547- def _get_output ( layer , X , model_input ):
548- """Get output of partial model """
549- partial_model = keras .models .Model (inputs = model_input , outputs = layer .output )
550- y = partial_model .predict (X )
548+ def _get_outputs ( layers , X , model_input ):
549+ """Get outputs of intermediate layers """
550+ partial_models = keras .models .Model (inputs = model_input , outputs = [ layer .output for layer in layers ] )
551+ y = partial_models .predict (X )
551552 return y
552553
553554
@@ -562,37 +563,30 @@ def get_ymodel_keras(keras_model, X):
562563 Returns:
563564 dict: A dictionary in the form {"layer_name": ouput array of layer}.
564565 """
565-
566566 ymodel = {}
567-
567+ traced_layers = []
568+ layer_names = []
568569 for layer in keras_model .layers :
569- print (f"Processing { layer .name } in Keras model..." )
570- if not _is_ignored_layer (layer ):
571- # If the layer has activation integrated then separate them
572- # Note that if the layer is a standalone activation layer then skip this
573- if hasattr (layer , 'activation' ) and not (
574- isinstance (layer , keras .layers .Activation ) or isinstance (layer , qkeras .qlayers .QActivation )
575- ):
576- if layer .activation :
577- if layer .activation .__class__ .__name__ == "linear" :
578- ymodel [layer .name ] = _get_output (layer , X , keras_model .input )
579-
580- else :
581- temp_activation = layer .activation
582- layer .activation = None
583- # Get output for layer without activation
584- ymodel [layer .name ] = _get_output (layer , X , keras_model .input )
585-
586- # Add the activation back
587- layer .activation = temp_activation
588- # Get ouput for activation
589- ymodel [layer .name + f"_{ temp_activation .__class__ .__name__ } " ] = _get_output (
590- layer , X , keras_model .input
591- )
592- else :
593- ymodel [layer .name ] = _get_output (layer , X , keras_model .input )
594- else :
595- ymodel [layer .name ] = _get_output (layer , X , keras_model .input )
570+ if _is_ignored_layer (layer ):
571+ continue
572+ # If the layer has activation integrated then separate them
573+ # Note that if the layer is a standalone activation layer then skip this
574+ name = layer .name
575+ if (
576+ hasattr (layer , "activation" )
577+ and layer .activation .__name__ != "linear"
578+ and not isinstance (layer , (keras .layers .Activation , qkeras .qlayers .QActivation ))
579+ ):
580+ tmp_activation = layer .activation
581+ layer .activation = None
582+ ymodel .update ({layer .name : _get_outputs ([layer ], X , keras_model .input )})
583+ layer .activation = tmp_activation
584+ name = layer .name + f"_{ tmp_activation .__name__ } "
585+ traced_layers .append (layer )
586+ layer_names .append (name )
587+ outputs = _get_outputs (traced_layers , X , keras_model .input )
588+ for name , output in zip (layer_names , outputs ):
589+ ymodel [name ] = output
596590 print ("Done taking outputs for Keras model." )
597591 return ymodel
598592
0 commit comments