from collections import OrderedDict from itertools import product import torch from torchvision import models import unittest def get_available_models(): # TODO add a registration mechanism to torchvision.models return [k for k, v in models.__dict__.items() if callable(v) and k[0].lower() == k[0]] class Tester(unittest.TestCase): def _test_model(self, name, input_shape): # passing num_class equal to a number other than 1000 helps in making the test # more enforcing in nature model = models.__dict__[name](num_classes=50) model.eval() x = torch.rand(input_shape) out = model(x) self.assertEqual(out.shape[-1], 50) def _make_sliced_model(self, model, stop_layer): layers = OrderedDict() for name, layer in model.named_children(): layers[name] = layer if name == stop_layer: break new_model = torch.nn.Sequential(layers) return new_model def test_resnet_dilation(self): # TODO improve tests to also check that each layer has the right dimensionality for i in product([False, True], [False, True], [False, True]): model = models.__dict__["resnet50"](replace_stride_with_dilation=i) model = self._make_sliced_model(model, stop_layer="layer4") model.eval() x = torch.rand(1, 3, 224, 224) out = model(x) f = 2 ** sum(i) self.assertEqual(out.shape, (1, 2048, 7 * f, 7 * f)) for model_name in get_available_models(): # for-loop bodies don't define scopes, so we have to save the variables # we want to close over in some way def do_test(self, model_name=model_name): input_shape = (1, 3, 224, 224) if model_name in ['inception_v3']: input_shape = (1, 3, 299, 299) self._test_model(model_name, input_shape) setattr(Tester, "test_" + model_name, do_test) if __name__ == '__main__': unittest.main()