Spaces:
Runtime error
Runtime error
| # Copyright (c) OpenMMLab. All rights reserved. | |
| import numpy as np | |
| import pytest | |
| import torch | |
| import torch.nn as nn | |
| from mmcv.cnn.bricks import (ACTIVATION_LAYERS, CONV_LAYERS, NORM_LAYERS, | |
| PADDING_LAYERS, PLUGIN_LAYERS, | |
| build_activation_layer, build_conv_layer, | |
| build_norm_layer, build_padding_layer, | |
| build_plugin_layer, build_upsample_layer, is_norm) | |
| from mmcv.cnn.bricks.norm import infer_abbr as infer_norm_abbr | |
| from mmcv.cnn.bricks.plugin import infer_abbr as infer_plugin_abbr | |
| from mmcv.cnn.bricks.upsample import PixelShufflePack | |
| from mmcv.utils.parrots_wrapper import _BatchNorm | |
| def test_build_conv_layer(): | |
| with pytest.raises(TypeError): | |
| # cfg must be a dict | |
| cfg = 'Conv2d' | |
| build_conv_layer(cfg) | |
| with pytest.raises(KeyError): | |
| # `type` must be in cfg | |
| cfg = dict(kernel_size=3) | |
| build_conv_layer(cfg) | |
| with pytest.raises(KeyError): | |
| # unsupported conv type | |
| cfg = dict(type='FancyConv') | |
| build_conv_layer(cfg) | |
| kwargs = dict( | |
| in_channels=4, out_channels=8, kernel_size=3, groups=2, dilation=2) | |
| cfg = None | |
| layer = build_conv_layer(cfg, **kwargs) | |
| assert isinstance(layer, nn.Conv2d) | |
| assert layer.in_channels == kwargs['in_channels'] | |
| assert layer.out_channels == kwargs['out_channels'] | |
| assert layer.kernel_size == (kwargs['kernel_size'], kwargs['kernel_size']) | |
| assert layer.groups == kwargs['groups'] | |
| assert layer.dilation == (kwargs['dilation'], kwargs['dilation']) | |
| cfg = dict(type='Conv') | |
| layer = build_conv_layer(cfg, **kwargs) | |
| assert isinstance(layer, nn.Conv2d) | |
| assert layer.in_channels == kwargs['in_channels'] | |
| assert layer.out_channels == kwargs['out_channels'] | |
| assert layer.kernel_size == (kwargs['kernel_size'], kwargs['kernel_size']) | |
| assert layer.groups == kwargs['groups'] | |
| assert layer.dilation == (kwargs['dilation'], kwargs['dilation']) | |
| cfg = dict(type='deconv') | |
| layer = build_conv_layer(cfg, **kwargs) | |
| assert isinstance(layer, nn.ConvTranspose2d) | |
| assert layer.in_channels == kwargs['in_channels'] | |
| assert layer.out_channels == kwargs['out_channels'] | |
| assert layer.kernel_size == (kwargs['kernel_size'], kwargs['kernel_size']) | |
| assert layer.groups == kwargs['groups'] | |
| assert layer.dilation == (kwargs['dilation'], kwargs['dilation']) | |
| # sparse convs cannot support the case when groups>1 | |
| kwargs.pop('groups') | |
| for type_name, module in CONV_LAYERS.module_dict.items(): | |
| cfg = dict(type=type_name) | |
| # SparseInverseConv2d and SparseInverseConv3d do not have the argument | |
| # 'dilation' | |
| if type_name == 'SparseInverseConv2d' or type_name == \ | |
| 'SparseInverseConv3d': | |
| kwargs.pop('dilation') | |
| layer = build_conv_layer(cfg, **kwargs) | |
| assert isinstance(layer, module) | |
| assert layer.in_channels == kwargs['in_channels'] | |
| assert layer.out_channels == kwargs['out_channels'] | |
| kwargs['dilation'] = 2 # recover the key | |
| def test_infer_norm_abbr(): | |
| with pytest.raises(TypeError): | |
| # class_type must be a class | |
| infer_norm_abbr(0) | |
| class MyNorm: | |
| _abbr_ = 'mn' | |
| assert infer_norm_abbr(MyNorm) == 'mn' | |
| class FancyBatchNorm: | |
| pass | |
| assert infer_norm_abbr(FancyBatchNorm) == 'bn' | |
| class FancyInstanceNorm: | |
| pass | |
| assert infer_norm_abbr(FancyInstanceNorm) == 'in' | |
| class FancyLayerNorm: | |
| pass | |
| assert infer_norm_abbr(FancyLayerNorm) == 'ln' | |
| class FancyGroupNorm: | |
| pass | |
| assert infer_norm_abbr(FancyGroupNorm) == 'gn' | |
| class FancyNorm: | |
| pass | |
| assert infer_norm_abbr(FancyNorm) == 'norm_layer' | |
| def test_build_norm_layer(): | |
| with pytest.raises(TypeError): | |
| # cfg must be a dict | |
| cfg = 'BN' | |
| build_norm_layer(cfg, 3) | |
| with pytest.raises(KeyError): | |
| # `type` must be in cfg | |
| cfg = dict() | |
| build_norm_layer(cfg, 3) | |
| with pytest.raises(KeyError): | |
| # unsupported norm type | |
| cfg = dict(type='FancyNorm') | |
| build_norm_layer(cfg, 3) | |
| with pytest.raises(AssertionError): | |
| # postfix must be int or str | |
| cfg = dict(type='BN') | |
| build_norm_layer(cfg, 3, postfix=[1, 2]) | |
| with pytest.raises(AssertionError): | |
| # `num_groups` must be in cfg when using 'GN' | |
| cfg = dict(type='GN') | |
| build_norm_layer(cfg, 3) | |
| # test each type of norm layer in norm_cfg | |
| abbr_mapping = { | |
| 'BN': 'bn', | |
| 'BN1d': 'bn', | |
| 'BN2d': 'bn', | |
| 'BN3d': 'bn', | |
| 'SyncBN': 'bn', | |
| 'GN': 'gn', | |
| 'LN': 'ln', | |
| 'IN': 'in', | |
| 'IN1d': 'in', | |
| 'IN2d': 'in', | |
| 'IN3d': 'in', | |
| } | |
| for type_name, module in NORM_LAYERS.module_dict.items(): | |
| if type_name == 'MMSyncBN': # skip MMSyncBN | |
| continue | |
| for postfix in ['_test', 1]: | |
| cfg = dict(type=type_name) | |
| if type_name == 'GN': | |
| cfg['num_groups'] = 3 | |
| name, layer = build_norm_layer(cfg, 3, postfix=postfix) | |
| assert name == abbr_mapping[type_name] + str(postfix) | |
| assert isinstance(layer, module) | |
| if type_name == 'GN': | |
| assert layer.num_channels == 3 | |
| assert layer.num_groups == cfg['num_groups'] | |
| elif type_name != 'LN': | |
| assert layer.num_features == 3 | |
| def test_build_activation_layer(): | |
| with pytest.raises(TypeError): | |
| # cfg must be a dict | |
| cfg = 'ReLU' | |
| build_activation_layer(cfg) | |
| with pytest.raises(KeyError): | |
| # `type` must be in cfg | |
| cfg = dict() | |
| build_activation_layer(cfg) | |
| with pytest.raises(KeyError): | |
| # unsupported activation type | |
| cfg = dict(type='FancyReLU') | |
| build_activation_layer(cfg) | |
| # test each type of activation layer in activation_cfg | |
| for type_name, module in ACTIVATION_LAYERS.module_dict.items(): | |
| cfg['type'] = type_name | |
| layer = build_activation_layer(cfg) | |
| assert isinstance(layer, module) | |
| # sanity check for Clamp | |
| act = build_activation_layer(dict(type='Clamp')) | |
| x = torch.randn(10) * 1000 | |
| y = act(x) | |
| assert np.logical_and((y >= -1).numpy(), (y <= 1).numpy()).all() | |
| act = build_activation_layer(dict(type='Clip', min=0)) | |
| y = act(x) | |
| assert np.logical_and((y >= 0).numpy(), (y <= 1).numpy()).all() | |
| act = build_activation_layer(dict(type='Clamp', max=0)) | |
| y = act(x) | |
| assert np.logical_and((y >= -1).numpy(), (y <= 0).numpy()).all() | |
| def test_build_padding_layer(): | |
| with pytest.raises(TypeError): | |
| # cfg must be a dict | |
| cfg = 'reflect' | |
| build_padding_layer(cfg) | |
| with pytest.raises(KeyError): | |
| # `type` must be in cfg | |
| cfg = dict() | |
| build_padding_layer(cfg) | |
| with pytest.raises(KeyError): | |
| # unsupported activation type | |
| cfg = dict(type='FancyPad') | |
| build_padding_layer(cfg) | |
| for type_name, module in PADDING_LAYERS.module_dict.items(): | |
| cfg['type'] = type_name | |
| layer = build_padding_layer(cfg, 2) | |
| assert isinstance(layer, module) | |
| input_x = torch.randn(1, 2, 5, 5) | |
| cfg = dict(type='reflect') | |
| padding_layer = build_padding_layer(cfg, 2) | |
| res = padding_layer(input_x) | |
| assert res.shape == (1, 2, 9, 9) | |
| def test_upsample_layer(): | |
| with pytest.raises(TypeError): | |
| # cfg must be a dict | |
| cfg = 'bilinear' | |
| build_upsample_layer(cfg) | |
| with pytest.raises(KeyError): | |
| # `type` must be in cfg | |
| cfg = dict() | |
| build_upsample_layer(cfg) | |
| with pytest.raises(KeyError): | |
| # unsupported activation type | |
| cfg = dict(type='FancyUpsample') | |
| build_upsample_layer(cfg) | |
| for type_name in ['nearest', 'bilinear']: | |
| cfg['type'] = type_name | |
| layer = build_upsample_layer(cfg) | |
| assert isinstance(layer, nn.Upsample) | |
| assert layer.mode == type_name | |
| cfg = dict( | |
| type='deconv', in_channels=3, out_channels=3, kernel_size=3, stride=2) | |
| layer = build_upsample_layer(cfg) | |
| assert isinstance(layer, nn.ConvTranspose2d) | |
| cfg = dict(type='deconv') | |
| kwargs = dict(in_channels=3, out_channels=3, kernel_size=3, stride=2) | |
| layer = build_upsample_layer(cfg, **kwargs) | |
| assert isinstance(layer, nn.ConvTranspose2d) | |
| assert layer.in_channels == kwargs['in_channels'] | |
| assert layer.out_channels == kwargs['out_channels'] | |
| assert layer.kernel_size == (kwargs['kernel_size'], kwargs['kernel_size']) | |
| assert layer.stride == (kwargs['stride'], kwargs['stride']) | |
| layer = build_upsample_layer(cfg, 3, 3, 3, 2) | |
| assert isinstance(layer, nn.ConvTranspose2d) | |
| assert layer.in_channels == kwargs['in_channels'] | |
| assert layer.out_channels == kwargs['out_channels'] | |
| assert layer.kernel_size == (kwargs['kernel_size'], kwargs['kernel_size']) | |
| assert layer.stride == (kwargs['stride'], kwargs['stride']) | |
| cfg = dict( | |
| type='pixel_shuffle', | |
| in_channels=3, | |
| out_channels=3, | |
| scale_factor=2, | |
| upsample_kernel=3) | |
| layer = build_upsample_layer(cfg) | |
| assert isinstance(layer, PixelShufflePack) | |
| assert layer.scale_factor == 2 | |
| assert layer.upsample_kernel == 3 | |
| def test_pixel_shuffle_pack(): | |
| x_in = torch.rand(2, 3, 10, 10) | |
| pixel_shuffle = PixelShufflePack(3, 3, scale_factor=2, upsample_kernel=3) | |
| assert pixel_shuffle.upsample_conv.kernel_size == (3, 3) | |
| x_out = pixel_shuffle(x_in) | |
| assert x_out.shape == (2, 3, 20, 20) | |
| def test_is_norm(): | |
| norm_set1 = [ | |
| nn.BatchNorm1d, nn.BatchNorm2d, nn.BatchNorm3d, nn.InstanceNorm1d, | |
| nn.InstanceNorm2d, nn.InstanceNorm3d, nn.LayerNorm | |
| ] | |
| norm_set2 = [nn.GroupNorm] | |
| for norm_type in norm_set1: | |
| layer = norm_type(3) | |
| assert is_norm(layer) | |
| assert not is_norm(layer, exclude=(norm_type, )) | |
| for norm_type in norm_set2: | |
| layer = norm_type(3, 6) | |
| assert is_norm(layer) | |
| assert not is_norm(layer, exclude=(norm_type, )) | |
| class MyNorm(nn.BatchNorm2d): | |
| pass | |
| layer = MyNorm(3) | |
| assert is_norm(layer) | |
| assert not is_norm(layer, exclude=_BatchNorm) | |
| assert not is_norm(layer, exclude=(_BatchNorm, )) | |
| layer = nn.Conv2d(3, 8, 1) | |
| assert not is_norm(layer) | |
| with pytest.raises(TypeError): | |
| layer = nn.BatchNorm1d(3) | |
| is_norm(layer, exclude='BN') | |
| with pytest.raises(TypeError): | |
| layer = nn.BatchNorm1d(3) | |
| is_norm(layer, exclude=('BN', )) | |
| def test_infer_plugin_abbr(): | |
| with pytest.raises(TypeError): | |
| # class_type must be a class | |
| infer_plugin_abbr(0) | |
| class MyPlugin: | |
| _abbr_ = 'mp' | |
| assert infer_plugin_abbr(MyPlugin) == 'mp' | |
| class FancyPlugin: | |
| pass | |
| assert infer_plugin_abbr(FancyPlugin) == 'fancy_plugin' | |
| def test_build_plugin_layer(): | |
| with pytest.raises(TypeError): | |
| # cfg must be a dict | |
| cfg = 'Plugin' | |
| build_plugin_layer(cfg) | |
| with pytest.raises(KeyError): | |
| # `type` must be in cfg | |
| cfg = dict() | |
| build_plugin_layer(cfg) | |
| with pytest.raises(KeyError): | |
| # unsupported plugin type | |
| cfg = dict(type='FancyPlugin') | |
| build_plugin_layer(cfg) | |
| with pytest.raises(AssertionError): | |
| # postfix must be int or str | |
| cfg = dict(type='ConvModule') | |
| build_plugin_layer(cfg, postfix=[1, 2]) | |
| # test ContextBlock | |
| for postfix in ['', '_test', 1]: | |
| cfg = dict(type='ContextBlock') | |
| name, layer = build_plugin_layer( | |
| cfg, postfix=postfix, in_channels=16, ratio=1. / 4) | |
| assert name == 'context_block' + str(postfix) | |
| assert isinstance(layer, PLUGIN_LAYERS.module_dict['ContextBlock']) | |
| # test GeneralizedAttention | |
| for postfix in ['', '_test', 1]: | |
| cfg = dict(type='GeneralizedAttention') | |
| name, layer = build_plugin_layer(cfg, postfix=postfix, in_channels=16) | |
| assert name == 'gen_attention_block' + str(postfix) | |
| assert isinstance(layer, | |
| PLUGIN_LAYERS.module_dict['GeneralizedAttention']) | |
| # test NonLocal2d | |
| for postfix in ['', '_test', 1]: | |
| cfg = dict(type='NonLocal2d') | |
| name, layer = build_plugin_layer(cfg, postfix=postfix, in_channels=16) | |
| assert name == 'nonlocal_block' + str(postfix) | |
| assert isinstance(layer, PLUGIN_LAYERS.module_dict['NonLocal2d']) | |
| # test ConvModule | |
| for postfix in ['', '_test', 1]: | |
| cfg = dict(type='ConvModule') | |
| name, layer = build_plugin_layer( | |
| cfg, | |
| postfix=postfix, | |
| in_channels=16, | |
| out_channels=4, | |
| kernel_size=3) | |
| assert name == 'conv_block' + str(postfix) | |
| assert isinstance(layer, PLUGIN_LAYERS.module_dict['ConvModule']) | |