albermax / albermax/innvestigate
Implementing Contrastive Layer-wise Relevance Propagation
- Dominant language
- Python
- Stars
- 1.3k
- Forks
- 230
- PR merge metrics
- No merged PRs in 30d
Description
I'm trying to implement CLRP[1] for a binary classifier based on VGG using innvestigate, but I'm not getting the expected results.
In case you are unfamiliar with CLRP, it's an adaptation of Layer-wise Relevance Propagation with the goal of make the output saliency map (more) class-discriminative. In order to do this the relevance of the desired class is calculated as follows:
The paper proposes two similar but different ways of defining **R***CLRP*:
1. **R***CLRP* = LRP(X, W_overline, S_y_j) where W_overline is {W_1, W_2, ..., W_(L-1), -1 * W_L_j} or in words, all the weights are the same as for the normal concept except for the output layer where the weight of the node representing the target class is negated.
2. **R***CLRP* = max(0, **R** - **R***dual*)
**R***dual* = LRP(X W_overline, S_y_j). Here W_overline is define as {W_1, W_2, ..., W_(L-1), W_L{-j}} where W_L{-j} means the weights connected to the output layer excluding the j-th neuron.
Since I'm working with binary classification, both methods should be rather easy to implement.
Method 1:
analyzer = innvestigate.create_analyzer(rule, model_wo_sm, neuron_selection_mode="index")
model_wo_sm_clrp0 = keras.models.clone_model(model_wo_sm)
model_wo_sm_clrp1 = keras.models.clone_model(model_wo_sm)
weights = model_wo_sm.get_weights()
for i, m in enumerate([model_wo_sm_clrp0, model_wo_sm_clrp1]):
w = weights.copy()
neg = np.ones(len(w[-1]))
neg[i] *= -1
w[-1] *= neg
m.set_weights(w)
clrp_analyzer = innvestigate.create_analyzer(rule, model_wo_sm_clrp1, neuron_selection_mode="index")
R = analyzer.analyze(X, 0)
R_dual = clrp_analyzer.analyze(X, 1)
R_clrp = np.clip(R - R_dual, a_min = 0, a_max = None)
And method 2:
analyzer = innvestigate.create_analyzer(rule, model_wo_sm, neuron_selection_mode="index")
R = analyzer.analyze(X, 0)
R_dual = analyzer.analyze(X, 1)
R_clrp = np.clip(R - R_dual, a_min = 0, a_max = None)
But for both methods `R_clrp` is very close to zero. When I normalize the values of `R_clrp` between 0 and 1 and plot the result is similar to that of the paper. However if I flip the selected neurons/class I get an all zero output.
Upon further research I noticed that for the second method `R` and `R_dual` are both negative and very small.
min max
R -0.0012369031 -4.169839e-09
R_dual -0.002584224 -8.481891e-09
So my **questions are**: is the returned value of the `analyze` method the relevance or am I mistaken in that assumption? And if that is correct, then why would the relevance be so small and negative?
Cheers!
[1]
@article{gu2018understanding,
title={Understanding Individual Decisions of CNNs via Contrastive Backpropagation},
author={Gu, Jindong and Yang, Yinchong and Tresp, Volker},
journal={arXiv preprint arXiv:1812.02100},
year={2018}
}
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.