def test_bias_correction_bn_params_no_activation(self):
        np.random.seed(1)
        shape = (3, 3, 2, 2)

        weight = np.random.randn(*shape)

        quantized_weight = np.random.randn(*shape)

        bn_params = libpymo.BnParamsBiasCorr()
        gamma = np.array(np.random.randn(3))
        beta = np.array(np.random.randn(3))
        bn_params.gamma = gamma
        bn_params.beta = beta

        bias_tensor = libpymo.TensorParamBiasCorrection()
        bias = np.array(np.random.randn(shape[1]))
        bias_copy = bias.copy()
        bias_tensor.data = bias

        activation = libpymo.ActivationType.noActivation
        biasCorrection = libpymo.BnBasedBiasCorrection()
        biasCorrection.correctBias(bias_tensor, quantized_weight, weight,
                                   bn_params, activation)
        bias_python = bn_based_bias_correction(weight, quantized_weight,
                                               bias_copy, beta, gamma,
                                               ActivationType.no_activation)
        assert (np.allclose(bias_python, bias_tensor.data))
Example #2
0
def call_analytical_mo_correct_bias(layer: torch.nn.Module,
                                    bn: Union[torch.nn.BatchNorm2d, None],
                                    activation_type: Union[ActivationType,
                                                           None]):
    """
    :param layer: Layer to be corrected
    :param bn: Input BN to layer
    :param activation_type: Input activation to layer
    """
    bias_correction = libpymo.BnBasedBiasCorrection()
    # Passed wrapped layer since quantized network has to be corrected
    device = layer._modules['_module_to_wrap'].bias.device
    use_cuda = utils.is_model_on_gpu(layer)

    quant_dequant_weight = get_quantized_dequantized_weight(layer, use_cuda)

    weight_tensor = layer._module_to_wrap.weight

    # Transpose weights to C, N, H, W from N, C, H, W since axis are flipped for transposed conv
    if isinstance(
            layer._module_to_wrap,
            torch.nn.ConvTranspose2d) and layer._module_to_wrap.groups == 1:
        weight_tensor = weight_tensor.permute(1, 0, 2, 3)
        quant_dequant_weight = quant_dequant_weight.permute(1, 0, 2, 3)

    quant_dequant_weight = quant_dequant_weight.detach().cpu().numpy()

    weight_tensor = weight_tensor.detach().cpu().numpy()
    bias_tensor = libpymo.TensorParamBiasCorrection()
    bias_tensor.data = layer._module_to_wrap.bias.detach().cpu().numpy()

    # Assigning activation to No Acivation
    activation = libpymo.ActivationType.noActivation
    bn_params = libpymo.BnParamsBiasCorr()
    if bn is None:
        shape = weight_tensor.shape[1]
        bn_params.gamma = np.ones(shape)
        bn_params.beta = np.zeros(shape)
    else:
        bn_params.gamma = bn.get_module().weight.detach().cpu().numpy()
        bn_params.beta = bn.get_module().bias.detach().cpu().numpy()

        if activation_type == ActivationType.relu:
            activation = libpymo.ActivationType.relu
        # Relu6's type in connected graph is hardtanh
        elif activation_type == ActivationType.relu6:
            activation = libpymo.ActivationType.relu6

    bias_correction.correctBias(bias_tensor, quant_dequant_weight,
                                weight_tensor, bn_params, activation)

    # Assigning the updated bias back to the layer
    bias = torch.nn.Parameter(torch.Tensor(bias_tensor.data))

    layer._module_to_wrap.bias.data = bias.to(device=device)
Example #3
0
    def analytical_bias_correction_per_layer(
            corrected_model: tf.compat.v1.Session,
            layer: tf.Operation,
            preceeding_bn_layer_info: ConvBnInfoType,
            quant_params: QuantParams,
            is_first_conv: bool = False) -> tf.compat.v1.Session:
        """
        Perform bn based bias correction (analytical bc).

        :param corrected_model: active tensorflow session for corrected model
        :param layer: conv/linear layer to be corrected
        :param preceeding_bn_layer_info: corresponding preceeding bn/ activation info
        :param quant_params: Quantization specific params from user
        :param is_first_conv: flag to indicate if it's the first conv layer
        :return: None, updates corrected_model in place

        """

        layer = corrected_model.graph.get_operation_by_name(layer.name)
        # get bn param and quantized weights from conv for this layer
        bias_tensor, weight_tensor = BiasCorrection._get_conv_linear_params(
            corrected_model, layer)
        quantized_weight = BiasCorrection._get_quantized_weights(
            weight_tensor, quant_params)

        bn_params = libpymo.BnParamsBiasCorr()
        activation_type = libpymo.ActivationType.noActivation

        if preceeding_bn_layer_info:
            input_tf_bn_op_name = preceeding_bn_layer_info.input_bn.get_module(
            ).name
            bn_op = corrected_model.graph.get_operation_by_name(
                input_tf_bn_op_name)
            bn_params = BiasCorrection._get_bn_params(corrected_model, bn_op)
            if preceeding_bn_layer_info.in_activation_type == ActivationType.relu:
                activation_type = libpymo.ActivationType.relu
            elif preceeding_bn_layer_info.in_activation_type == ActivationType.relu6:
                activation_type = libpymo.ActivationType.relu6
            elif preceeding_bn_layer_info.in_activation_type == ActivationType.no_activation:
                activation_type = libpymo.ActivationType.noActivation
            else:
                assert (0, 'Unknown activation type',
                        preceeding_bn_layer_info.in_activation_type)
        else:
            if is_first_conv:
                # for the first conv layer case, we use gamma = 1 and beta = 0
                shape = weight_tensor.shape[1]
                bn_params.gamma = np.ones(shape)
                bn_params.beta = np.zeros(shape)
            else:
                assert 0, "layer info is None and is not first conv layer"

        # need to invoke cpp api for bn based bias correction
        biasCorrection = libpymo.BnBasedBiasCorrection()

        biasCorrection.correctBias(bias_tensor, quantized_weight,
                                   weight_tensor, bn_params, activation_type)

        # this api updates bias or adds bias add to layer if not present
        layer = corrected_model.graph.get_operation_by_name(layer.name)
        BiasUtils.update_bias_for_op(corrected_model, layer,
                                     np.array(bias_tensor.data))
        logger.info('Completed analytical bias correction for layer %s',
                    layer.name)