def explain(self, validation_data, model, class_index, patch_size): """ Compute Occlusion Sensitivity maps for a specific class index. Args: validation_data (Tuple[np.ndarray, Optional[np.ndarray]]): Validation data to perform the method on. Tuple containing (x, y). model (tf.keras.Model): tf.keras model to inspect class_index (int): Index of targeted class patch_size (int): Size of patch to apply on the image Returns: np.ndarray: Grid of all the sensitivity maps with shape (batch_size, H, W, 3) """ images, _ = validation_data sensitivity_maps = np.array([ self.get_sensitivity_map(model, image, class_index, patch_size) for image in images ]) heatmaps = np.array([ heatmap_display(heatmap, image) for heatmap, image in zip(sensitivity_maps, images) ]) grid = grid_display(heatmaps) return grid
def explain(self, validation_data, model, layer_name, class_index): """ Compute GradCAM for a specific class index. Args: validation_data (Tuple[np.ndarray, Optional[np.ndarray]]): Validation data to perform the method on. Tuple containing (x, y). model (tf.keras.Model): tf.keras model to inspect layer_name (str): Targeted layer for GradCAM class_index (int): Index of targeted class Returns: numpy.ndarray: Grid of all the GradCAM """ images, _ = validation_data outputs, guided_grads = GradCAM.get_gradients_and_filters( model, images, layer_name, class_index ) cams = GradCAM.generate_ponderated_output(outputs, guided_grads) heatmaps = np.array( [heatmap_display(cam.numpy(), image) for cam, image in zip(cams, images)] ) grid = grid_display(heatmaps) return grid
def explain( self, validation_data, model, class_index, layer_name=None, use_guided_grads=True, colormap=cv2.COLORMAP_VIRIDIS, image_weight=0.7, mean_transform=None, std_dev_transform=None, ): """ Compute GradCAM for a specific class index. Args: validation_data (Tuple[np.ndarray, Optional[np.ndarray]]): Validation data to perform the method on. Tuple containing (x, y). model (tf.keras.Model): tf.keras model to inspect class_index (int): Index of targeted class layer_name (str): Targeted layer for GradCAM. If no layer is provided, it is automatically infered from the model architecture. colormap (int): OpenCV Colormap to use for heatmap visualization image_weight (float): An optional `float` value in range [0,1] indicating the weight of the input image to be overlaying the calculated attribution maps. Defaults to `0.7`. use_guided_grads (boolean): Whether to use guided grads or raw gradients Returns: numpy.ndarray: Grid of all the GradCAM """ images, _ = validation_data if layer_name is None: layer_name = self.infer_grad_cam_target_layer(model) outputs, grads = GradCAM.get_gradients_and_filters( model, images, layer_name, class_index, use_guided_grads ) cams = GradCAM.generate_ponderated_output(outputs, grads) heatmaps = np.array( [ # not showing the actual image if image_weight=0 heatmap_display( cam.numpy(), image, colormap, image_weight, mean_transform, std_dev_transform, ) for cam, image in zip(cams, images) ] ) grid = grid_display(heatmaps) return grid
def test_should_display_heatmap(mocker): mock_add_weighted = mocker.patch( "tf_explain.utils.display.cv2.addWeighted") mock_apply_color_map = mocker.patch( "tf_explain.utils.display.cv2.applyColorMap") mock_cvt_color = mocker.patch("tf_explain.utils.display.cv2.cvtColor", return_value=mocker.sentinel.heatmap) heatmap = np.random.random((3, 3)) original_image = np.zeros((10, 10, 3)) output = heatmap_display(heatmap, original_image) assert output == mocker.sentinel.heatmap assert mock_add_weighted.call_count == 1 assert mock_apply_color_map.call_count == 1 assert mock_cvt_color.call_count == 3
def explain(self, model_input, model, layer_name, class_index, colormap=cv2.COLORMAP_INFERNO): """ Compute GradCAM for a specific class index. Args: model_input (tf.tensor): Data to perform the evaluation on. model (tf.keras.Model): tf.keras model to inspect layer_name (str): Targeted layer for GradCAM class_index (int, None): Index of targeted class colormap (int): Used in parent method signature, but ignored here Returns: tf.cams: The gradcams """ outputs, guided_grads, predictions = FEGradCAM.get_gradients_and_filters( model, model_input, layer_name, class_index) cams = GradCAM.generate_ponderated_output(outputs, guided_grads) input_min = tf.reduce_min(model_input) input_max = tf.reduce_max(model_input) # Need to move input image into the 0-255 range adjust_sum = 0.0 adjust_factor = 1.0 if input_min < 0: adjust_sum = 1.0 adjust_factor /= 2.0 if input_max <= 1: adjust_factor *= 255.0 heatmaps = [ heatmap_display(cam.numpy(), (inp.numpy() + adjust_sum) * adjust_factor, colormap) for cam, inp in zip(cams, model_input) ] return heatmaps, predictions
def explain( self, validation_data, model, class_index, layer_name=None, colormap=cv2.COLORMAP_VIRIDIS, ): """ Compute GradCAM for a specific class index. Args: validation_data (Tuple[np.ndarray, Optional[np.ndarray]]): Validation data to perform the method on. Tuple containing (x, y). model (tf.keras.Model): tf.keras model to inspect class_index (int): Index of targeted class layer_name (str): Targeted layer for GradCAM. If no layer is provided, it is automatically infered from the model architecture. colormap (int): OpenCV Colormap to use for heatmap visualization Returns: numpy.ndarray: Grid of all the GradCAM """ images, _ = validation_data if layer_name is None: layer_name = self.infer_grad_cam_target_layer(model) outputs, guided_grads = GradCAM.get_gradients_and_filters( model, images, layer_name, class_index) cams = GradCAM.generate_ponderated_output(outputs, guided_grads) heatmaps = np.array([ heatmap_display(cam.numpy(), image, colormap) for cam, image in zip(cams, images) ]) grid = grid_display(heatmaps) return grid, outputs, guided_grads