예제 #1
0
    def test020_speed(self, b_size=32, dim=256,
                      alpha_fwd=0.999, alpha_bkw=0.99, eps=1e-05, epoch=10):
        """
        Speed test online norm linearized vs loop
        Note: this test is for comparing speed to looped and linearized
            implementations of online norm so the user can decide which
            algorithm to use.
        """
        input = torch.randn(b_size, dim, 32, 32)

        # instantiate Linearized Online Norm class
        onlin = OnlineNorm2D(dim, alpha_fwd=alpha_fwd, alpha_bkw=alpha_bkw, eps=eps, b_size=b_size)

        # time lin algo
        forward = 0
        backward = 0
        for _ in range(epoch):
            start = time.time()
            # fprop through lin algo
            out = onlin(input)
            forward += time.time() - start

            start = time.time()
            # bprop through lin algo
            out.sum().backward()
            backward += time.time() - start

        self.logger.info(f'Linearized Control Normalization Speed Test: '
                         f'Forward {forward * 1e6/1e5:.3f} us | '
                         f'Backward {backward * 1e6/1e5:.3f} us | '
                         f'Total {(forward + backward) * 1e6/1e5:.3f} us')

        # Speed test online norm
        # instantiate Looping Online Norm class
        onloop = OnlineNorm2D(dim, eps=eps,
                              ctrl_norm=ControlNorm2DLoop(dim, alpha_fwd=alpha_fwd,
                                                          alpha_bkw=alpha_bkw, eps=eps))

        # time loop algo
        forward = 0
        backward = 0
        for _ in range(epoch):
            start = time.time()
            # fprop through loop algo
            out = onloop(input)
            forward += time.time() - start

            start = time.time()
            # bprop through loop algo
            out.sum().backward()
            backward += time.time() - start

        self.logger.info(f'Loop Control Normalization Speed Test: '
                         f'Forward {forward * 1e6/1e5:.3f} us | '
                         f'Backward {backward * 1e6/1e5:.3f} us | '
                         f'Total {(forward + backward) * 1e6/1e5:.3f} us')

        self.logger.info('Make input tensors representative of size you will '
                         'use and then use the correct algorithm based on '
                         'speed of execution.')
예제 #2
0
    def test010_similarity(self,
                           b_size=4,
                           dim=256,
                           alpha_fwd=0.999,
                           alpha_bkw=0.99,
                           eps=1e-05,
                           itrs=4):
        """ numerical comparison of online norm linearized vs loop """
        # instantiate inputs
        input = torch.randn(b_size, dim, 32, 32)
        input_0 = input.clone().detach().requires_grad_(True)
        input_1 = input.clone().detach().requires_grad_(True)
        # instantiate gradient at the output
        grad_out = torch.randn(b_size, dim, 32, 32)

        # instantiate Linearized Online Norm class
        onlin = OnlineNorm2D(dim,
                             alpha_fwd=alpha_fwd,
                             alpha_bkw=alpha_bkw,
                             eps=eps,
                             b_size=b_size)

        # instantiate Looping Online Norm class
        onloop = OnlineNorm2D(dim,
                              eps=eps,
                              ctrl_norm=ControlNorm2DLoop(dim,
                                                          alpha_fwd=alpha_fwd,
                                                          alpha_bkw=alpha_bkw,
                                                          eps=eps))

        for _ in range(itrs):
            # fprop through Linearized Online Norm class
            y_0 = onlin(input_0)
            # bprop through Linearized Online Norm class
            y_0.backward(grad_out)
            # fprop through Looping Online Norm class
            y_1 = onloop(input_1)
            # bprop through Looping Online Norm class
            y_1.backward(grad_out)

            # numerically compare output
            np.testing.assert_allclose(y_0.detach().numpy(),
                                       y_1.detach().numpy(),
                                       rtol=1e-4,
                                       atol=1e-5)
            # numerically grad_in
            np.testing.assert_allclose(input_0.grad.detach().numpy(),
                                       input_1.grad.detach().numpy(),
                                       rtol=1e-4,
                                       atol=1e-5)

        self.logger.info('Algorithm implemented using linearization of ops '
                         'numerically matches algorithm implemented with '
                         'loops')
예제 #3
0
def online_norm(num_features,
                afwd=0.999,
                abkw=0.99,
                eps=1e-05,
                weight=True,
                bias=True,
                ctrl_norm=None,
                layer_scaling=True,
                b_size=args.batch_size,
                **kwargs):
    """ Function which instantiates Online Norm Layer """
    return OnlineNorm2D(num_features,
                        alpha_fwd=afwd,
                        alpha_bkw=abkw,
                        eps=eps,
                        weight=weight,
                        bias=bias,
                        ctrl_norm=ctrl_norm,
                        layer_scaling=layer_scaling,
                        b_size=b_size,
                        **kwargs)
예제 #4
0
def online_norm(num_features, alpha_fwd=0.999, alpha_bkw=0.99,
                eps=1e-05, affine=True, ecm='ls', **kwargs):
    """ Function which instantiates Online Norm Layer """
    return OnlineNorm2D(num_features, alpha_fwd=alpha_fwd, alpha_bkw=alpha_bkw,
                        eps=eps, affine=affine, ecm=ecm, **kwargs)
예제 #5
0
def norm(num_features,
         mode='batch',
         eps=1e-05,
         momentum=0.1,
         weight=True,
         bias=True,
         track_running_stats=True,
         gn_num_groups=32,
         **kwargs):
    """
    Function which instantiates a normalization scheme based on mode

    Arguments:
        num_features: :math:`C` from an expected input of size
            :math:`(N, C, H, W)`
        mode: Option to select normalization method (Default: None)
        eps: a value added to the denominator for numerical stability.
            Default: 1e-5
        momentum: the value used for the running_mean and running_var
            computation. Can be set to ``None`` for cumulative moving average
            (i.e. simple average). Default: 0.1
        weight: a boolean value that when set to ``True``, this module has
            learnable linear parameters. Default: ``True``
        bias: a boolean value that when set to ``True``, this module has
            learnable bias parameters. Default: ``True``
        track_running_stats: a boolean value that when set to ``True``, this
            module tracks the running mean and variance, and when set to ``False``,
            this module does not track such statistics and always uses batch
            statistics in both training and eval modes. Argument valid when
            using batch or instance norm. Default: ``True``

        Note:
            1. When using BN affine = weight & bias
            2. When using OnlineNorm **kwargs will hold hfwd, hbkw, ctrl_norm
            layer_scaling, and b_size. See definition of OnlineNorm2D for
            specifics.
    """

    if mode == 'batch':
        warnings.warn('Normalizer: Batch')
        affine = weight and bias
        if weight != bias:
            warnings.warn('affine not used in batch norm')
        normalizer = nn.BatchNorm2d(num_features=num_features,
                                    eps=eps,
                                    momentum=momentum,
                                    affine=affine,
                                    track_running_stats=track_running_stats)

    elif mode == 'group':
        warnings.warn('Normalizer: Group')
        affine = weight and bias
        if weight != bias:
            warnings.warn('affine not used in group norm')
        normalizer = nn.GroupNorm(gn_num_groups,
                                  num_features,
                                  eps=eps,
                                  affine=affine)

    elif mode == 'layer':
        warnings.warn('Normalizer: Layer')
        normalizer = LayerNorm2d(eps=eps, weight=weight, bias=bias)

    elif mode == 'instance':
        warnings.warn('Normalizer: Instance')
        affine = weight and bias
        if weight != bias:
            warnings.warn('affine not used in batch norm')
        normalizer = nn.InstanceNorm2d(num_features,
                                       eps=eps,
                                       momentum=momentum,
                                       affine=affine,
                                       track_running_stats=track_running_stats)

    elif mode == 'online':
        warnings.warn('Normalizer: Online')
        normalizer = OnlineNorm2D(num_features=num_features,
                                  eps=eps,
                                  weight=weight,
                                  bias=bias,
                                  **kwargs)

    elif mode == 'none' or mode is None:
        warnings.warn('Normalizer: None')
        normalizer = Identity()

    else:
        raise KeyError('mode options include: "batch" | "group" | "layer" | '
                       '"instance" | "online" | "none"')

    return normalizer