Source code for visual.models.utils
from collections import OrderedDict
import torch
from torch import nn
from visual import LAYER_DICT
[docs]class IntermediateLayerGetter(nn.Module):
"""
Module wrapper that returns intermediate layers from a model
It has a strong assumption that the modules have been registered
into the model in the same order as they are used.
.. Note::
It is best if using other wrappers such as RedirectedReLUs to only wrap with IntermediateLayerGetter after all other wrappers
Arguments:
model (nn.Module): model on which we will extract the features
Examples::
>>> import torchvision
>>> m = torchvision.models.resnet18(pretrained=True)
>>> # extract layer1 and layer3, giving as names `feat1` and feat2`
>>> new_m = IntermediateLayerGetter(m, {'layer1': 'feat1', 'layer3': 'feat2'})
>>> state = {}
>>> out = new_m(torch.rand(1, 3, 224, 224), state)
>>> print([(k, v.shape) for k, v in state[LAYER_DICT].items()])
[('feat1', torch.Size([1, 64, 56, 56])), ('feat2', torch.Size([1, 256, 14, 14]))]
"""
def __init__(self, model):
super(IntermediateLayerGetter, self).__init__()
self.model = model
self.layer_names = []
self.out = OrderedDict()
self.recursive_layer_names(model, '')
[docs] def recursive_layer_names(self, layer, pre_name):
for name, module in layer.named_children():
nname = pre_name + '_' + name if pre_name != '' else name
def new_forward(old_forward, nname):
def new_forward_1(*args, **kwargs):
o = old_forward(*args, **kwargs)
self.out[nname] = o
return o
return new_forward_1
module.__setattr__('forward', new_forward(module.forward, nname))
self.layer_names.append(nname)
if len(list(layer.named_children())) > 0:
self.recursive_layer_names(module, nname)
[docs] def forward(self, x, state=None):
out = self.model(x)
if state is not None:
state[LAYER_DICT] = self.out
return out