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))
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)
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)