Skip to content

Commit fb3be81

Browse files
authored
docs: Added detailed explanation on CAM computation (#8)
* docs: Added installation instructions * docs: Fixed typo * docs: Added detailed explanations for each CAM method * docs: Clarified explanations of Score-CAM
1 parent 9a45c93 commit fb3be81

File tree

5 files changed

+158
-10
lines changed

5 files changed

+158
-10
lines changed

docs/source/cams.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ torchcam.cams
77

88
CAM
99
--------
10-
Related to activation-based class activation maps.
10+
Methods related to activation-based class activation maps.
1111

1212

1313
.. autoclass:: CAM
@@ -17,12 +17,11 @@ Related to activation-based class activation maps.
1717

1818
Grad-CAM
1919
--------
20-
Related to gradient-based class activation maps.
20+
Methods related to gradient-based class activation maps.
2121

2222

2323
.. autoclass:: GradCAM
2424

25-
2625
.. autoclass:: GradCAMpp
2726

2827
.. autoclass:: SmoothGradCAMpp

docs/source/index.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,15 @@ Torchcam documentation
33

44
The :mod:`torchcam` package gives PyTorch users the possibility to visualize the spatial influence on classification outputs.
55

6+
.. toctree::
7+
:maxdepth: 2
8+
:caption: Getting Started
9+
10+
installing
11+
612
.. toctree::
713
:maxdepth: 1
8-
:caption: Package Reference
14+
:caption: Package Documentation
915

1016
cams
1117
utils

docs/source/installing.rst

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
************
3+
Installation
4+
************
5+
6+
This library requires Python 3.6 or newer.
7+
8+
Via Python Package
9+
==================
10+
11+
Install the last stable release of the package using pip:
12+
13+
.. code:: bash
14+
15+
pip install torchcam
16+
17+
18+
Via Conda
19+
=========
20+
21+
Install the last stable release of the package using conda:
22+
23+
.. code:: bash
24+
25+
conda install -c frgfm torchcam
26+
27+
28+
Via Git
29+
=======
30+
31+
Install the library in developper mode:
32+
33+
.. code:: bash
34+
35+
git clone https://github.com/frgfm/torch-cam.git
36+
pip install -e torch-cam/.

torchcam/cams/cam.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,18 @@ def __repr__(self):
117117

118118

119119
class CAM(_CAM):
120-
"""Implements a class activation map extractor as described in https://arxiv.org/abs/1512.04150
120+
"""Implements a class activation map extractor as described in `"Learning Deep Features for Discriminative
121+
Localization" <https://arxiv.org/pdf/1512.04150.pdf>`_.
122+
123+
The Class Activation Map (CAM) is defined for image classification models that have global pooling at the end
124+
of the visual feature extraction block. The localization map is computed as follows:
125+
126+
.. math::
127+
L^{(c)}_{CAM}(x, y) = ReLU\\Big(\\sum\\limits_k w_k^{(c)} A_k(x, y)\\Big)
128+
129+
where :math:`A_k(x, y)` is the activation of node :math:`k` in the last convolutional layer of the model at
130+
position :math:`(x, y)`,
131+
and :math:`w_k^{(c)}` is the weight corresponding to class :math:`c` for unit :math:`k`.
121132
122133
Example::
123134
>>> from torchvision.models import resnet18
@@ -150,7 +161,29 @@ def _get_weights(self, class_idx, scores=None):
150161

151162

152163
class ScoreCAM(_CAM):
153-
"""Implements a class activation map extractor as described in https://arxiv.org/abs/1910.01279
164+
"""Implements a class activation map extractor as described in `"Score-CAM:
165+
Score-Weighted Visual Explanations for Convolutional Neural Networks" <https://arxiv.org/pdf/1910.01279.pdf>`_.
166+
167+
The localization map is computed as follows:
168+
169+
.. math::
170+
L^{(c)}_{Score-CAM}(x, y) = ReLU\\Big(\\sum\\limits_k w_k^{(c)} A_k(x, y)\\Big)
171+
172+
with the coefficient :math:`w_k^{(c)}` being defined as:
173+
174+
.. math::
175+
w_k^{(c)} = softmax(Y^{(c)}(M) - Y^{(c)}(X_b))
176+
177+
where :math:`A_k(x, y)` is the activation of node :math:`k` in the last convolutional layer of the model at
178+
position :math:`(x, y)`, :math:`Y^{(c)}(X)` is the model output score for class :math:`c` before softmax
179+
for input :math:`X`, :math:`X_b` is a baseline image,
180+
and :math:`M` is defined as follows:
181+
182+
.. math::
183+
M = \\Big(\\frac{M^{(d)} - \\min M^{(d)}}{\\max M^{(d)} - \\min M^{(d)}} \\odot X \\Big)_{1 \\leq d \\leq D}
184+
185+
where :math:`\\odot` refers to the element-wise multiplication, :math:`M^{(d)}` is the upsampled version of
186+
:math:`A_d` on node :math:`d`, and :math:`D` is the number of channels on the target convolutional layer.
154187
155188
Example::
156189
>>> from torchvision.models import resnet18

torchcam/cams/gradcam.py

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,23 @@ def _get_weights(self, class_idx, scores):
5555

5656

5757
class GradCAM(_GradCAM):
58-
"""Implements a class activation map extractor as described in https://arxiv.org/pdf/1710.11063.pdf
58+
"""Implements a class activation map extractor as described in `"Grad-CAM: Visual Explanations from Deep Networks
59+
via Gradient-based Localization" <https://arxiv.org/pdf/1610.02391.pdf>`_.
60+
61+
The localization map is computed as follows:
62+
63+
.. math::
64+
L^{(c)}_{Grad-CAM}(x, y) = ReLU\\Big(\\sum\\limits_k w_k^{(c)} A_k(x, y)\\Big)
65+
66+
with the coefficient :math:`w_k^{(c)}` being defined as:
67+
68+
.. math::
69+
w_k^{(c)} = \\frac{1}{H \\cdot W} \\sum\\limits_{i=1}^H \\sum\\limits_{j=1}^W
70+
\\frac{\\partial Y^{(c)}}{\\partial A_k(i, j)}
71+
72+
where :math:`A_k(x, y)` is the activation of node :math:`k` in the last convolutional layer of the model at
73+
position :math:`(x, y)`,
74+
and :math:`Y^{(c)}` is the model output score for class :math:`c` before softmax.
5975
6076
Example::
6177
>>> from torchvision.models import resnet18
@@ -86,7 +102,32 @@ def _get_weights(self, class_idx, scores):
86102

87103

88104
class GradCAMpp(_GradCAM):
89-
"""Implements a class activation map extractor as described in https://arxiv.org/pdf/1710.11063.pdf
105+
"""Implements a class activation map extractor as described in `"Grad-CAM++: Improved Visual Explanations for
106+
Deep Convolutional Networks" <https://arxiv.org/pdf/1710.11063.pdf>`_.
107+
108+
The localization map is computed as follows:
109+
110+
.. math::
111+
L^{(c)}_{Grad-CAM++}(x, y) = \\sum\\limits_k w_k^{(c)} A_k(x, y)
112+
113+
with the coefficient :math:`w_k^{(c)}` being defined as:
114+
115+
.. math::
116+
w_k^{(c)} = \\sum\\limits_{i=1}^H \\sum\\limits_{j=1}^W \\alpha_k^{(c)}(i, j) \\cdot
117+
ReLU\\Big(\\frac{\\partial Y^{(c)}}{\\partial A_k(i, j)}\\Big)
118+
119+
where :math:`A_k(x, y)` is the activation of node :math:`k` in the last convolutional layer of the model at
120+
position :math:`(x, y)`,
121+
:math:`Y^{(c)}` is the model output score for class :math:`c` before softmax,
122+
and :math:`\\alpha_k^{(c)}(i, j)` being defined as:
123+
124+
.. math::
125+
\\alpha_k^{(c)}(i, j) = \\frac{1}{\\sum\\limits_{i, j} \\frac{\\partial Y^{(c)}}{\\partial A_k(i, j)}}
126+
= \\frac{\\frac{\\partial^2 Y^{(c)}}{(\\partial A_k(i,j))^2}}{2 \\cdot
127+
\\frac{\\partial^2 Y^{(c)}}{(\\partial A_k(i,j))^2} + \\sum\\limits_{a,b} A_k (a,b) \\cdot
128+
\\frac{\\partial^3 Y^{(c)}}{(\\partial A_k(i,j))^3}}
129+
130+
if :math:`\\frac{\\partial Y^{(c)}}{\\partial A_k(i, j)} = 1` else :math:`0`.
90131
91132
Example::
92133
>>> from torchvision.models import resnet18
@@ -122,8 +163,41 @@ def _get_weights(self, class_idx, scores):
122163

123164

124165
class SmoothGradCAMpp(_GradCAM):
125-
"""Implements a class activation map extractor as described in https://arxiv.org/pdf/1908.01224.pdf
126-
with a personal correction to the paper (alpha coefficient numerator)
166+
"""Implements a class activation map extractor as described in `"Smooth Grad-CAM++: An Enhanced Inference Level
167+
Visualization Technique for Deep Convolutional Neural Network Models" <https://arxiv.org/pdf/1908.01224.pdf>`_
168+
with a personal correction to the paper (alpha coefficient numerator).
169+
170+
The localization map is computed as follows:
171+
172+
.. math::
173+
L^{(c)}_{Smooth Grad-CAM++}(x, y) = \\sum\\limits_k w_k^{(c)} A_k(x, y)
174+
175+
with the coefficient :math:`w_k^{(c)}` being defined as:
176+
177+
.. math::
178+
w_k^{(c)} = \\sum\\limits_{i=1}^H \\sum\\limits_{j=1}^W \\alpha_k^{(c)}(i, j) \\cdot
179+
ReLU\\Big(\\frac{\\partial Y^{(c)}}{\\partial A_k(i, j)}\\Big)
180+
181+
where :math:`A_k(x, y)` is the activation of node :math:`k` in the last convolutional layer of the model at
182+
position :math:`(x, y)`,
183+
:math:`Y^{(c)}` is the model output score for class :math:`c` before softmax,
184+
and :math:`\\alpha_k^{(c)}(i, j)` being defined as:
185+
186+
.. math::
187+
\\alpha_k^{(c)}(i, j)
188+
= \\frac{\\frac{\\partial^2 Y^{(c)}}{(\\partial A_k(i,j))^2}}{2 \\cdot
189+
\\frac{\\partial^2 Y^{(c)}}{(\\partial A_k(i,j))^2} + \\sum\\limits_{a,b} A_k (a,b) \\cdot
190+
\\frac{\\partial^3 Y^{(c)}}{(\\partial A_k(i,j))^3}}
191+
= \\frac{\\frac{1}{n} \\sum\\limits_{m=1}^n D^{(c, 2)}_k(i, j)}{
192+
\\frac{2}{n} \\sum\\limits_{m=1}^n D^{(c, 2)}_k(i, j) + \\sum\\limits_{a,b} A_k (a,b) \\cdot
193+
\\frac{1}{n} \\sum\\limits_{m=1}^n D^{(c, 3)}_k(i, j)}
194+
195+
if :math:`\\frac{\\partial Y^{(c)}}{\\partial A_k(i, j)} = 1` else :math:`0`. Here :math:`D^{(c, p)}_k(i, j)`
196+
refers to the p-th partial derivative of the class score of class :math:`c` relatively to the activation in layer
197+
:math:`k` at position :math:`(i, j)`, and :math:`n` is the number of samples used to get the gradient estimate.
198+
199+
Please note the difference in the numerator of :math:`\\alpha_k^{(c)}(i, j)`,
200+
which is actually :math:`\\frac{1}{n} \\sum\\limits_{k=1}^n D^{(c, 1)}_k(i,j)` in the paper.
127201
128202
Example::
129203
>>> from torchvision.models import resnet18

0 commit comments

Comments
 (0)