Coder Social home page Coder Social logo

iba's Introduction

IBA: Informational Bottlenecks for Attribution

[Paper Arxiv] | [Paper Code] | [Reviews] | [API Documentation] | [Examples] | [Installation]

Build Status Documentation Status

Example GIF
Iterations of the Per-Sample Bottleneck

This repository contains an easy-to-use implementation for the IBA attribution method. Our methods minimizes the amount of transmitted information while retaining a high classifier score for the explained class. In our paper, we run this optimization per single sample (Per-Sample Bottleneck) and trained a neural network to predict the relevant areas (Readout Bottleneck). See our paper for a in-depth description: "Restricting the Flow: Information Bottlenecks for Attribution".

Generally, we advise using the Per-Sample Bottleneck over the Readout Bottleneck. We saw it to perform better and is more flexible as it only requires to estimate the mean and variance of the feature map. The Readout Bottleneck has the advantage of producing attribution maps with a single forward pass once trained.

For the code to reproduce our paper, see IBA-paper-code.

This library provides a TensorFlow v1 and a PyTorch implementation.

PyTorch

Examplary usage for the Per-Sample Bottleneck:

from IBA.pytorch import IBA, tensor_to_np_img, get_imagenet_folder, imagenet_transform
from IBA.utils import plot_saliency_map, to_unit_interval, load_monkeys

from torch.utils.data import DataLoader
from torchvision.models import vgg16
import torch

# imagenet_dir = /path/to/imagenet/validation

# Load model
dev = 'cuda:0' if  torch.cuda.is_available() else 'cpu'
model = vgg16(pretrained=True)
model.to(dev)

# Add a Per-Sample Bottleneck at layer conv4_1
iba = IBA(model.features[17])

# Estimate the mean and variance of the feature map at this layer.
val_set = get_imagenet_folder(imagenet_dir)
val_loader = DataLoader(val_set, batch_size=64, shuffle=True, num_workers=4)
iba.estimate(model, val_loader, n_samples=5000, progbar=True)

# Load Image
monkeys, target = load_monkeys(pil=True)
monkeys_transform = imagenet_transform()(monkeys)

# Closure that returns the loss for one batch
model_loss_closure = lambda x: -torch.log_softmax(model(x), dim=1)[:, target].mean()

# Explain class target for the given image
saliency_map = iba.analyze(monkeys_transform.unsqueeze(0).to(dev), model_loss_closure, beta=10)

# display result
model_loss_closure = lambda x: -torch.log_softmax(model(x), 1)[:, target].mean()
heatmap = iba.analyze(monkeys_transform[None].to(dev), model_loss_closure )
plot_saliency_map(heatmap, tensor_to_np_img(monkeys_transform))

We provide a notebook with the Per-Sample Bottleneck and the Readout Bottleneck.

Tensorflow

from IBA.tensorflow_v1 import IBACopyInnvestigate, model_wo_softmax, get_imagenet_generator
from IBA.utils import load_monkeys, plot_saliency_map
from keras.applications.vgg16 import VGG16, preprocess_input

# imagenet_dir = /path/to/imagenet/validation

# load model & remove the final softmax layer
model_softmax = VGG16(weights='imagenet')
model = model_wo_softmax(model_softmax)

# after layer block4_conv1 the bottleneck will be added
feat_layer = model.get_layer(name='block4_conv1')

# add the bottleneck by coping the model
iba = IBACopyInnvestigate(
    model,
    neuron_selection_mode='index',
    feature_name=feat_layer.output.name,
)

# estimate feature mean and std
val_gen = get_imagenet_generator(imagenet_dir)
iba.fit_generator(val_gen, steps_per_epoch=50)

# load image
monkeys, target = load_monkeys()
monkeys_scaled =  preprocess_input(monkeys)

# get the saliency map and plot
saliency_map = iba.analyze(monkeys_scaled[None], neuron_selection=target)
plot_saliency_map(saliency_map, img=monkeys)

Table: Overview over the different tensorflow classes. (Task) type of task (i.e. regression, classification, unsupervised). (Layer) requires you to add a layer to the explained model. (Copy) copies the tensorflow graph.

Class Task Layer Copy Remarks
IBALayer Any Recommended
IBACopy Any Very flexible
IBACopy Classification Nice API for classification

Documentation

[PyTorch API] | [TensorFlow API]

The API documentation is hosted here.

Table: Examplary jupyter notebooks

Notebook Description
pytorch_IBA_per_sample.ipynb Per-Sample Bottleneck
pytorch_IBA_train_readout.ipynb Train a Readout Bottleneck
tensorflow_IBALayer_cifar.ipynb Train a CIFAR model containing an IBALayer
tensorflow_IBACopy_imagenet.ipynb Explains a ImageNet model
tensorflow_IBACopyInnvestigate_imagenet.ipynb innvestigate api wrapper

Installation

You can install it directly from git:

$ pip install git+https://github.com/BioroboticsLab/IBA

To install the dependencies for torch, tensorflow, tensorflow-gpu or developement dev, use the following syntax:

$ pip install git+https://github.com/BioroboticsLab/IBA[torch, dev]

For development, you can also clone the repository locally and then install in development mode:

$ git clone https://github.com/BioroboticsLab/IBA
$ cd per-sample-bottlneck
$ pip install -e .

Table: Supported versions

Package From To
TensorFlow 1.12.0 1.15.0
PyTorch 1.1.0 1.4.0

Reference

If you use this software for a scientific publication, please cite our paper:

@inproceedings{
Schulz2020Restricting,
title={Restricting the Flow: Information Bottlenecks for Attribution},
author={Karl Schulz and Leon Sixt and Federico Tombari and Tim Landgraf},
booktitle={International Conference on Learning Representations},
year={2020},
url={https://openreview.net/forum?id=S1xWh1rYwB}
}

iba's People

Contributors

berleon avatar dependabot[bot] avatar karl-schulz avatar mungooooo avatar nebw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

iba's Issues

add tensorflow implementation & update api

the idea is to have both tensorflow and pytorch implementation in this repo. a possible api could be:

iba.tensorflow.*
iba.pytorch.* 
iba.common.*

where common would host all shared things (e.g. visualization).

training readout does not work

Hi,

I meet two problems when training the readout network.

return self._do_restrict_information(x, alpha)

does not work now, since
def _do_restrict_information(self, x):

accepts one argument now.
(Currently, I checkout to the previous commit)

alpha.clamp(-self._alpha_bound, self._alpha_bound)

should be alpha = alpha.clamp(....
(The alpha become -infinite)

Could you check the current code can train the readout network?
Thanks!

PyTorch: The size of tensor a (28) must match the size of tensor b (4) at non-singleton dimension 3

Hi All,

I'm facing this issue:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-37-aec96d2a94f8> in <module>
     31 
     32 # Explain class target for the given image
---> 33 saliency_map = iba.analyze(monkeys_transform.unsqueeze(0).to(dev), model_loss_closure, beta=10)
     34 
     35 # display result

~/anaconda3/lib/python3.7/site-packages/IBA/pytorch.py in analyze(self, input_t, model_loss_fn, mode, beta, optimization_steps, min_std, lr, batch_size, active_neurons_threshold)
    616             for _ in opt_range:
    617                 optimizer.zero_grad()
--> 618                 model_loss = model_loss_fn(batch)
    619                 # Taking the mean is equivalent of scaling the sum with 1/K
    620                 information_loss = self.capacity().mean()

<ipython-input-37-aec96d2a94f8> in <lambda>(x)
     28 
     29 # Closure that returns the loss for one batch
---> 30 model_loss_closure = lambda x: -torch.log_softmax(model(x), dim=1)[:, target].mean()
     31 
     32 # Explain class target for the given image

~/anaconda3/lib/python3.7/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
    887             result = self._slow_forward(*input, **kwargs)
    888         else:
--> 889             result = self.forward(*input, **kwargs)
    890         for hook in itertools.chain(
    891                 _global_forward_hooks.values(),

~/anaconda3/lib/python3.7/site-packages/torchvision/models/resnet.py in forward(self, x)
    247 
    248     def forward(self, x: Tensor) -> Tensor:
--> 249         return self._forward_impl(x)
    250 
    251 

~/anaconda3/lib/python3.7/site-packages/torchvision/models/resnet.py in _forward_impl(self, x)
    236 
    237         x = self.layer1(x)
--> 238         x = self.layer2(x)
    239         x = self.layer3(x)
    240         x = self.layer4(x)

~/anaconda3/lib/python3.7/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
    891                 _global_forward_hooks.values(),
    892                 self._forward_hooks.values()):
--> 893             hook_result = hook(self, input, result)
    894             if hook_result is not None:
    895                 result = hook_result

~/anaconda3/lib/python3.7/site-packages/IBA/pytorch.py in __call__(self, m, inputs, outputs)
    215             return self.iba(inputs)
    216         elif self.input_or_output == "output":
--> 217             return self.iba(outputs)
    218 
    219 

~/anaconda3/lib/python3.7/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
    887             result = self._slow_forward(*input, **kwargs)
    888         else:
--> 889             result = self.forward(*input, **kwargs)
    890         for hook in itertools.chain(
    891                 _global_forward_hooks.values(),

~/anaconda3/lib/python3.7/site-packages/IBA/pytorch.py in forward(self, x)
    364         """
    365         if self._restrict_flow:
--> 366             return self._do_restrict_information(x)
    367         if self._estimate:
    368             self.estimator(x)

~/anaconda3/lib/python3.7/site-packages/IBA/pytorch.py in _do_restrict_information(self, x, alpha)
    452         lamb = self.smooth(lamb) if self.smooth is not None else lamb
    453 
--> 454         self._buffer_capacity = self._kl_div(x, lamb, self._mean, self._std) * self._active_neurons
    455 
    456         eps = x.data.new(x.size()).normal_()

~/anaconda3/lib/python3.7/site-packages/IBA/pytorch.py in _kl_div(r, lambda_, mean_r, std_r)
    418 
    419         # Normalizing [1]
--> 420         r_norm = (r - mean_r) / std_r
    421 
    422         # Computing mean and var Z'|R' [2,3]

RuntimeError: The size of tensor a (28) must match the size of tensor b (4) at non-singleton dimension 3

My code:

from IBA.pytorch import IBA, tensor_to_np_img, get_imagenet_folder, imagenet_transform
from IBA.utils import plot_saliency_map, to_unit_interval, load_monkeys

from torch.utils.data import DataLoader
from torchvision.models import vgg16, resnet34
import torch

# imagenet_dir = /path/to/imagenet/validation

# Load model
dev = 'cuda:0' if  torch.cuda.is_available() else 'cpu'
model = resnet34(pretrained=True)
model.fc = nn.Linear(512,10)
model.to(dev)
model.eval()

# Add a Per-Sample Bottleneck at layer conv4_1
iba = IBA(model.layer2)

# Estimate the mean and variance of the feature map at this layer.
#val_set = get_imagenet_folder(imagenet_dir)
val_loader = DataLoader(trainset, batch_size=1024, shuffle=True, num_workers=4)
iba.estimate(model, val_loader, n_samples=5000, progbar=True)

# Load Image
monkeys, target = load_monkeys(pil=True)
monkeys_transform = imagenet_transform()(monkeys)

# Closure that returns the loss for one batch
model_loss_closure = lambda x: -torch.log_softmax(model(x), dim=1)[:, target].mean()

# Explain class target for the given image
saliency_map = iba.analyze(monkeys_transform.unsqueeze(0).to(dev), model_loss_closure, beta=10)

# display result
model_loss_closure = lambda x: -torch.log_softmax(model(x), 1)[:, target].mean()
heatmap = iba.analyze(monkeys_transform[None].to(dev), model_loss_closure )
plot_saliency_map(heatmap, tensor_to_np_img(monkeys_transform))

Any idea how to solve that?

improve readme

  • fix bibtex
  • fix pytorch example
  • fix installation instruction
  • add tensorflow example
  • link documentation
  • include GIF
  • add a short overview readme to the notebook directory
  • write FAQ
  • fix GIF text

Use of k=hwc for selecting beta

Hi! The paper is really great, and thank you for sharing the code here.

I have a quick question about how you calculate k. In the paper, it is said that k = hwc, where h is height, w is width and c is channels. However, when I referred to Appendix C for VGG-16, it seems that k needs to equal 1. Would you mind explaining the calculation of k and its use?

Thanks a lot!

Add PyTorch test

add similar tests as for tensorflow for pytorch. It would also be nice to run them on travis.

  • pytorch.py
  • setup pytorch on travis

Installing IBA on Win10 throws codec error

When installing the package on a windows system I get the following error:

Traceback (most recent call last):
      [...]
      File "setup.py", line 12, in <module>
        long_description=open("README.md").read(),
    [...]  
    UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d in position 5249: character maps to <undefined>

So line 12 of setup.py should state the expected enconding:
long_description=open("README.md", 'r', encoding='utf8').read(),.
Otherwise, Win10 expects 1252 encoding.

I simply changed that one line after cloning the repo and installed it as suggested to make it work.
Hence the standard character encoding on linux is in UTF8, it should work on these systems too, even though I am not sure, if this solution is generally correct.

When training readout, loss is Nan

First of all, thank you very much for your open source code! Your work is great!
But when I ran the code in "pytorch_IBA_train_readout.ipynb", I found information_ Loss is all Nan after the first epoch. Is there something wrong with me? Could you give me some advice?

IBA for different input dimensions

Hey, I would like to know how can one adjust the code for different input dimensions.

It is working for (3,W,H) images; I would like to use IBA for inputs of dimension (4,3,W,H).

So the input to my model are 4 different images with 3 color channels.

One obvious thing is to expand batch to input_t.expand(batch_size, -1, -1, -1, -1) instead of (batch_size, -1,-1,-1). What else should be adapted?

Thanks for your help and great interpretability method!

Question about estimated values provided in IBA-paper-code

Thank you for sharing your excellent project!

While running both repositories: IBA and IBA-paper-code,
I realized that the estimated mean and std values (pytorch_IBA_per_sample.ipynb) differ from the values provided in your IBA-paper-code repository.

Can you provide some guidance for estimating the same value provided in the IBA-paper-code repository?

Question about KL-div

Hello, got many inspiration from your work and thank you for sharing the codes.
I got confused of information-loss codes below:

IBA/IBA/pytorch.py

Lines 401 to 410 in 34baed6

def _kl_div(r, lambda_, mean_r, std_r):
r_norm = (r - mean_r) / std_r
var_z = (1 - lambda_) ** 2
log_var_z = torch.log(var_z)
mu_z = r_norm * lambda_
capacity = -0.5 * (1 + log_var_z - mu_z**2 - var_z)
return capacity

Q1. Why mean and variance employed in codes are different with ones in paper: appendix E?
Q2. Why Z is normalized? I guess there's no such normalization part included.
image

Thank you

Some changes for the PyTorch IBA API

A few remarks to the PyTorch IBA API:

  • IBA.heatmap rename to IBA.analyze. Add flag to switch between saliency_map (in bits, channels summed, scaled to input image) or capacity (in bits, not summed, not scaled)
  • IBA.supress_information rename to IBA.restrict_flow
  • IBA.__init__ add estimator=None parameter
  • IBA.__init__ add feature_mean_std=None parameter which takes a tuple(mean, std)
  • IBA._init rename to IBA._build: make clear that it is different to __init__

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.