signal-grad-cam 0.1.2__tar.gz → 0.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of signal-grad-cam might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: signal_grad_cam
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: SignalGrad-CAM aims at generalising Grad-CAM to one-dimensional applications, while enhancing usability and efficiency.
5
5
  Home-page: https://github.com/samuelepe11/signal_grad_cam
6
6
  Author: Samuele Pe
@@ -5,7 +5,7 @@ with open("README.md", "r") as f:
5
5
 
6
6
  setup(
7
7
  name="signal_grad_cam",
8
- version="0.1.2",
8
+ version="0.1.3",
9
9
  description="SignalGrad-CAM aims at generalising Grad-CAM to one-dimensional applications, while enhancing usability"
10
10
  " and efficiency.",
11
11
  keywords="XAI, class activation maps, CNN, time series",
@@ -23,8 +23,8 @@ class CamBuilder:
23
23
  def __init__(self, model: torch.nn.Module | tf.keras.Model | Any,
24
24
  transform_fn: Callable[[np.ndarray, *tuple[Any, ...]], torch.Tensor | tf.Tensor] = None,
25
25
  class_names: List[str] = None, time_axs: int = 1, input_transposed: bool = False,
26
- ignore_channel_dim: bool = False, model_output_index: int = None, extend_search: bool = False,
27
- padding_dim: int = None, seed: int = 11):
26
+ ignore_channel_dim: bool = False, is_regression_network: bool = False, model_output_index: int = None,
27
+ extend_search: bool = False, padding_dim: int = None, seed: int = 11):
28
28
  """
29
29
  Initializes the CamBuilder class. The constructor also displays, if present and retrievable, the 1D- and
30
30
  2D-convolutional layers in the network, as well as the final Sigmoid/Softmax activation. Additionally, the CAM
@@ -44,6 +44,10 @@ class CamBuilder:
44
44
  during model inference, either by the model itself or by the preprocessing function.
45
45
  :param ignore_channel_dim: (optional, default is False) A boolean indicating whether to ignore the channel
46
46
  dimension. This is useful when the model expects inputs without a singleton channel dimension.
47
+ :param is_regression_network: (optional, default is False) A boolean indicating whether the network is designed
48
+ for a regression task. If set to True, the CAM will highlight both positive and negative contributions.
49
+ While negative contributions are typically irrelevant for classification-based saliency maps, they can be
50
+ meaningful in regression settings, as they may represent features that decrease the predicted value.
47
51
  :param model_output_index: (optional, default is None) An integer index specifying which of the model's outputs
48
52
  represents output scores (or probabilities). If there is only one output, this argument can be ignored.
49
53
  :param extend_search: (optional, default is False) A boolean flag indicating whether to deepend the search for
@@ -67,6 +71,7 @@ class CamBuilder:
67
71
  self.time_axs = time_axs
68
72
  self.input_transposed = input_transposed
69
73
  self.ignore_channel_dim = ignore_channel_dim
74
+ self.is_regression_network = is_regression_network
70
75
  self.model_output_index = model_output_index
71
76
  self.padding_dim = padding_dim
72
77
  self.original_dims = []
@@ -136,7 +141,8 @@ class CamBuilder:
136
141
  :param results_dir_path: (optional, default is None) A string representing the relative path to the directory
137
142
  for storing results. If None, the output will be displayed in a figure.
138
143
  :param aspect_factor: (optional, default is 100) A numerical value to set the aspect ratio of the output signal
139
- one-dimensional CAM.
144
+ one-dimensional CAM. Note that this value should be grater than the length of the input signal considered,
145
+ otherwise it is set to the length of the considered signal.
140
146
  :param data_shape_list: (optional, default is None) A list of integer tuples storing the original input sizes,
141
147
  used to set the CAM shape after resizing during preprocessing. The expected format is number of rows x
142
148
  number of columns.
@@ -648,7 +654,8 @@ class CamBuilder:
648
654
  :param dt: (optional, default is 10) A numerical value representing the granularity of the time axis in seconds
649
655
  in the output display.
650
656
  :param aspect_factor: (optional, default is 100) A numerical value to set the aspect ratio of the output signal
651
- one-dimensional CAM.
657
+ one-dimensional CAM. Note that this value should be grater than the length of the input signal considered,
658
+ otherwise it is set to the length of the considered signal.
652
659
  :param bar_ranges: A tuple containing two np.ndarrays, corresponding to the minimum and maximum importance scores
653
660
  per CAM for each item in the input data list, based on a given setting (defined by algorithm, target
654
661
  layer, and target class).
@@ -674,7 +681,7 @@ class CamBuilder:
674
681
  norm = self.__get_norm(map)
675
682
 
676
683
  if map.shape[1] == 1:
677
- aspect = int(map.shape[0] / aspect_factor)
684
+ aspect = int(map.shape[0] / aspect_factor) if map.shape[0] <= aspect_factor else 1
678
685
  map = np.transpose(map)
679
686
  else:
680
687
  if is_2d_layer:
@@ -15,8 +15,8 @@ class TorchCamBuilder(CamBuilder):
15
15
 
16
16
  def __init__(self, model: nn.Module | Any, transform_fn: Callable[[np.ndarray, *tuple[Any, ...]], torch.Tensor]
17
17
  = None, class_names: List[str] = None, time_axs: int = 1, input_transposed: bool = False,
18
- ignore_channel_dim: bool = False, model_output_index: int = None, extend_search: bool = False,
19
- use_gpu: bool = False, padding_dim: int = None, seed: int = 11):
18
+ ignore_channel_dim: bool = False, is_regression_network: bool = False, model_output_index: int = None,
19
+ extend_search: bool = False, use_gpu: bool = False, padding_dim: int = None, seed: int = 11):
20
20
  """
21
21
  Initializes the TorchCamBuilder class. The constructor also displays, if present and retrievable, the 1D- and
22
22
  2D-convolutional layers in the network, as well as the final Sigmoid/Softmax activation. Additionally, the CAM
@@ -36,6 +36,10 @@ class TorchCamBuilder(CamBuilder):
36
36
  during model inference, either by the model itself or by the preprocessing function.
37
37
  :param ignore_channel_dim: (optional, default is False) A boolean indicating whether to ignore the channel
38
38
  dimension. This is useful when the model expects inputs without a singleton channel dimension.
39
+ :param is_regression_network: (optional, default is False) A boolean indicating whether the network is designed
40
+ for a regression task. If set to True, the CAM will highlight both positive and negative contributions.
41
+ While negative contributions are typically irrelevant for classification-based saliency maps, they can be
42
+ meaningful in regression settings, as they may represent features that decrease the predicted value.
39
43
  :param model_output_index: (optional, default is None) An integer index specifying which of the model's outputs
40
44
  represents output scores (or probabilities). If there is only one output, this argument can be ignored.
41
45
  :param extend_search: (optional, default is False) A boolean flag indicating whether to deepend the search for
@@ -52,6 +56,7 @@ class TorchCamBuilder(CamBuilder):
52
56
  super(TorchCamBuilder, self).__init__(model=model, transform_fn=transform_fn, class_names=class_names,
53
57
  time_axs=time_axs, input_transposed=input_transposed,
54
58
  ignore_channel_dim=ignore_channel_dim,
59
+ is_regression_network=is_regression_network,
55
60
  model_output_index=model_output_index, extend_search=extend_search,
56
61
  padding_dim=padding_dim, seed=seed)
57
62
 
@@ -180,8 +185,8 @@ class TorchCamBuilder(CamBuilder):
180
185
 
181
186
  if softmax_final:
182
187
  # Approximate Softmax inversion formula logit = log(prob) + constant, as the constant is negligible
183
- # during derivation
184
- target_scores = torch.log(outputs)
188
+ # during derivation. Clamp probabilities before log application to avoid null maps for maximum confidence.
189
+ target_scores = torch.log(torch.clamp(outputs, min=0, max=1 - 1e-6))
185
190
  target_probs = outputs
186
191
 
187
192
  # Adjust results for binary network
@@ -246,7 +251,8 @@ class TorchCamBuilder(CamBuilder):
246
251
  activations[i, :] *= weights[i]
247
252
 
248
253
  cam = torch.sum(activations, dim=0)
249
- cam = torch.relu(cam)
254
+ if not self.is_regression_network:
255
+ cam = torch.relu(cam)
250
256
  return cam
251
257
 
252
258
  def _get_hirescam_map(self, is_2d_layer: bool, batch_idx: int) -> torch.Tensor:
@@ -271,7 +277,8 @@ class TorchCamBuilder(CamBuilder):
271
277
  activations[i, :] *= gradients[i, :]
272
278
 
273
279
  cam = torch.sum(activations, dim=0)
274
- cam = torch.relu(cam)
280
+ if not self.is_regression_network:
281
+ cam = torch.relu(cam)
275
282
  return cam
276
283
 
277
284
  def __get_activation_forward_hook(self, layer: nn.Module, inputs: Tuple[torch.Tensor, ...], outputs: torch.Tensor) \
@@ -20,8 +20,8 @@ class TfCamBuilder(CamBuilder):
20
20
 
21
21
  def __init__(self, model: tf.keras.Model | Any, transform_fn: Callable[[np.ndarray, *tuple[Any, ...]], tf.Tensor]
22
22
  = None, class_names: List[str] = None, time_axs: int = 1, input_transposed: bool = False,
23
- ignore_channel_dim: bool = False, model_output_index: int = None, extend_search: bool = False,
24
- padding_dim: int = None, seed: int = 11):
23
+ ignore_channel_dim: bool = False, is_regression_network: bool = False, model_output_index: int = None,
24
+ extend_search: bool = False, padding_dim: int = None, seed: int = 11):
25
25
  """
26
26
  Initializes the TfCamBuilder class. The constructor also displays, if present and retrievable, the 1D- and
27
27
  2D-convolutional layers in the network, as well as the final Sigmoid/Softmax activation. Additionally, the CAM
@@ -41,6 +41,10 @@ class TfCamBuilder(CamBuilder):
41
41
  during model inference, either by the model itself or by the preprocessing function.
42
42
  :param ignore_channel_dim: (optional, default is False) A boolean indicating whether to ignore the channel
43
43
  dimension. This is useful when the model expects inputs without a singleton channel dimension.
44
+ :param is_regression_network: (optional, default is False) A boolean indicating whether the network is designed
45
+ for a regression task. If set to True, the CAM will highlight both positive and negative contributions.
46
+ While negative contributions are typically irrelevant for classification-based saliency maps, they can be
47
+ meaningful in regression settings, as they may represent features that decrease the predicted value.
44
48
  :param model_output_index: (optional, default is None) An integer index specifying which of the model's outputs
45
49
  represents output scores (or probabilities). If there is only one output, this argument can be ignored.
46
50
  :param extend_search: (optional, default is False) A boolean flag indicating whether to deepend the search for
@@ -54,7 +58,9 @@ class TfCamBuilder(CamBuilder):
54
58
  # Initialize attributes
55
59
  super(TfCamBuilder, self).__init__(model=model, transform_fn=transform_fn, class_names=class_names,
56
60
  time_axs=time_axs, input_transposed=input_transposed,
57
- ignore_channel_dim=ignore_channel_dim, model_output_index=model_output_index,
61
+ ignore_channel_dim=ignore_channel_dim,
62
+ is_regression_network=is_regression_network,
63
+ model_output_index=model_output_index,
58
64
  extend_search=extend_search, padding_dim=padding_dim, seed=seed)
59
65
 
60
66
  # Set seeds
@@ -194,8 +200,9 @@ class TfCamBuilder(CamBuilder):
194
200
 
195
201
  if softmax_final:
196
202
  # Approximate Softmax inversion formula logit = log(prob) + constant, as the constant is negligible
197
- # during derivation
198
- target_scores = tf.math.log(outputs)
203
+ # during derivation. Clamp probabilities before log application to avoid null maps for maximum
204
+ # confidence.
205
+ target_scores = tf.math.log(tf.clip_by_value(outputs, 0, 1.0 - 1e-6))
199
206
  target_probs = outputs
200
207
 
201
208
  # Adjust results for binary network
@@ -260,7 +267,8 @@ class TfCamBuilder(CamBuilder):
260
267
  activations[:, i] *= weights[i]
261
268
 
262
269
  cam = tf.reduce_sum(tf.convert_to_tensor(activations), axis=-1)
263
- cam = tf.nn.relu(cam)
270
+ if not self.is_regression_network:
271
+ cam = tf.nn.relu(cam)
264
272
  return cam
265
273
 
266
274
  def _get_hirecam_map(self, is_2d_layer: bool, batch_idx: int) -> tf.Tensor:
@@ -285,7 +293,8 @@ class TfCamBuilder(CamBuilder):
285
293
  activations[:, i] *= gradients[:, i]
286
294
 
287
295
  cam = tf.reduce_sum(tf.convert_to_tensor(activations), axis=-1)
288
- cam = tf.nn.relu(cam)
296
+ if not self.is_regression_network:
297
+ cam = tf.nn.relu(cam)
289
298
  return cam
290
299
 
291
300
  @staticmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: signal-grad-cam
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: SignalGrad-CAM aims at generalising Grad-CAM to one-dimensional applications, while enhancing usability and efficiency.
5
5
  Home-page: https://github.com/samuelepe11/signal_grad_cam
6
6
  Author: Samuele Pe
File without changes