Source code for image_segmentation.class_activation_maps.average
"""
=========================================
Average Drop and Average Increase Metrics
=========================================
"""
from typing import Callable
import numpy as np
import tensorflow as tf
from tensorflow.keras.backend import epsilon
[docs]def avg_drop(Y_c, O_c):
return np.mean(np.maximum(0,(Y_c-O_c))/(Y_c+epsilon()))*100
[docs]def avg_increase(Y_c, O_c):
return 100*np.mean(Y_c < O_c)
[docs]class AveragesCam:
"""
Set of metrics to measure influence of CAM in the ouput model score.
Attributes
----------
model : tensorflow.keras.Model
Already trained model.
inputs : tf.Tensor
Instances to predict scores.
"""
[docs] def __init__(self, model: tf.keras.Model , inputs: tf.Tensor) -> None:
"""
Parameters
----------
model :
Already trained model.
inputs :
Instances to predict scores.
"""
self.model = model
self.inputs = inputs
self.Y_c = model.predict(inputs)
[docs] def _get_scores(self, cams: tf.Tensor, score_function: Callable) -> tuple:
""" Calculate scores over inputs and masked inputs with cams.
Parameters
----------
cams :
Normalized ouput of CAM methods using the model and the inputs
score_function :
Same score function used to calculate the CAMs in tf-keras-vis
Returns
-------
tuple
The fisrt is the scores of the model over the inputs and the second
is the scores over the masked input with the cams.
"""
if type(cams) is list:
cams = [cam[...,None] for cam in cams]
inputs = [input_*cam for input_,cam in zip(self.inputs,cams)]
else:
cams = cams[...,None]
inputs = self.inputs*cams
O_c = self.model.predict(inputs)
O_c = np.array(score_function(O_c))
Y_c = np.array(score_function(self.Y_c))
return Y_c, O_c
[docs] def average_drop(self, cams: tf.Tensor, score_function: Callable,
return_vector: bool = False) -> float:
""" Calculate average drop.
Parameters
----------
cams :
Normalized ouput of CAM methods using the model and the inputs
score_function :
Same score function used to calculate the CAMs in tf-keras-vis
Returns
-------
float
average drop
Note
----
The equation used is
.. math::
100\\frac{1}{N} \sum_{i=1}^N \\frac{max(0,Y_i^c - O_i^c)}{Y_i^c}
"""
Y_c, O_c = self._get_scores(cams, score_function)
a_drop = avg_drop(Y_c, O_c)
if return_vector:
return a_drop,Y_c,O_c
else:
return a_drop
[docs] def average_increase(self, cams: tf.Tensor, score_function: Callable,
return_vector: bool = False) -> float:
""" Calculate average increase.
Parameters
----------
cams :
Normalized ouput of CAM methods using the model and the inputs
score_function :
Same score function used to calculate the CAMs in tf-keras-vis
Returns
-------
float
average increase
Note
----
The equation used is
.. math::
100\\frac{1}{N} \sum_{i=1}^N Sign(Y_i^c < O_i^c)
"""
Y_c, O_c = self._get_scores(cams, score_function)
a_increase = avg_increase(Y_c,O_c)
if return_vector:
return a_increase, Y_c, O_c
else:
return a_increase