BioroboticsLab / IBA

Information Bottlenecks for Attribution
MIT License
74 stars 9 forks source link

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

Closed unnir closed 3 years ago

unnir commented 3 years ago

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?

berleon commented 3 years ago

Hi unnir,

I was not able to reproduce your error from your snippet. I adapted your snippet to use the CIFAR10 dataset (just for sanity checking and I did not had an ImageNet copy arround). It now runs through without any problem:

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
from torchvision.datasets import CIFAR10
from torchvision.transforms import Resize, ToTensor, Compose
import torch
from torch import nn

# 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 = CIFAR10('/tmp/cifar', transform=Compose([Resize(224), ToTensor()]), download=True)
val_loader = DataLoader(val_set, batch_size=1, shuffle=True, num_workers=0)
iba.estimate(model, val_loader, n_samples=1, progbar=True)

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

# fix target
target = 5

# 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))

Please, let me know if this version does not work for you.

Best, Leon

unnir commented 3 years ago

it was my mistake. Sorry and thank you for your answer.

berleon commented 3 years ago

No Problem, let me know if you encounter another problem.