def integerize(input, float_bits, bits=16): bound = math.pow(2.0, bits - 1) min_val = -bound max_val = bound - 1 res = torch.floor_(input * math.pow(2., float_bits) + 0.5) if (res > max_val).any() or (res < min_val).any(): print('Overflow. Some values were clipped') return torch.clamp(res, min_val, max_val)
def forward(self, inputs): inputs = F.avg_pool2d(inputs, self.kernel_size, self.stride, self.padding, self.ceil_mode, self.count_include_pad) inputs = torch.floor_(inputs * self.kernel_size * self.kernel_size + 0.1) pool_factor = math.pow(2, 16) // math.pow(self.kernel_size, 2) bound = math.pow(2.0, self.bits - 1) min_val = -bound max_val = bound - 1 return torch.clamp(roundnorm_reg(inputs * pool_factor, self.bits), min_val, max_val)
def forward(self, inputs): inputs = F.adaptive_avg_pool2d(inputs, self.output_size) mult = inputs.shape[2] * inputs.shape[3] // self.output_size[ 0] // self.output_size[1] inputs = torch.floor_(inputs * mult + 0.1) pool_factor = math.pow(2, 16) // mult bound = math.pow(2.0, self.bits - 1) min_val = -bound max_val = bound - 1 return torch.clamp(roundnorm_reg(inputs * pool_factor, self.bits), min_val, max_val)
def get_sign_bias_from_bn(prev: nn.Module, bn: nn.BatchNorm2d, scale=None): """get equivalent ``(s, b)`` for this bn such that ``bn(prev(x * scale)) >= 0`` iff ``s * (x + b) >= 0``, where ``s in [-1, 1]`` and ``b`` is an integer""" from .net_bin import PositiveInputCombination mean = bn.running_mean if isinstance(prev, PositiveInputCombination): mean = mean - prev.get_bias() k, b = bn._get_scale_bias(bn.running_var, mean) # cond: k * x + b > 0 if scale is not None: k *= scale sign = k.sign() assert torch.all(sign.abs() > 1e-4) bias = b / k bias = torch.floor_(bias) + (sign < 0).to(bias.dtype) return sign, bias
def round(input, float_bits, bits=16): bound = math.pow(2.0, bits - 1) min_val = -bound max_val = bound - 1 return torch.clamp(torch.floor_(input * math.pow(2., float_bits) + 0.5), min_val, max_val) * math.pow(2., -float_bits)
def roundnorm_reg(input, n): return torch.floor_((input + math.pow(2., n - 1)) * math.pow(2., -n))
def threshold_(self, preds, threshold=0.5): return torch.where(preds > threshold, torch.ceil_(preds), torch.floor_(preds))
def roundnorm_reg(inp, num_rounded_bits): return torch.floor_((inp + math.pow(2., num_rounded_bits - 1)) * math.pow(2., -num_rounded_bits))