def forward(self, x): res=x res = self.relu0(res) res = pack_quant_tensor(res,torch.tensor(1.0, dtype=torch.float32),torch.tensor(4.0, dtype=torch.float32)) res = self.linear1(res) res = pack_quant_tensor(res,torch.tensor(1.0, dtype=torch.float32),torch.tensor(4.0, dtype=torch.float32)) res = self.relu1(res) res = pack_quant_tensor(res,torch.tensor(1.0, dtype=torch.float32),torch.tensor(4.0, dtype=torch.float32)) res = self.linear2(res) return res
def forward(self, input): input_tensor, input_scale, input_bit_width = self.unpack_input(input) x = super(QuantAvgPool2d, self).forward(input_tensor) if self.quant_type != QuantType.FP: x = x * (self.kernel_size * self.kernel_size) # remove scaling introduced by average output_bit_width = self.max_output_bit_width(input_bit_width) x, output_scale, output_bit_width = self.accumulator_quant(x, input_scale, output_bit_width) return pack_quant_tensor(x, output_scale, output_bit_width) else: return pack_quant_tensor(x, input_scale, input_bit_width)
def __init__(self): a = Tensor([0,0]) b = Tensor([0,1]) c = Tensor([1,0]) d = Tensor([1,1]) aq = pack_quant_tensor(a,torch.tensor(.125, dtype=torch.float32),torch.tensor(4.0, dtype=torch.float32)) bq = pack_quant_tensor(b,torch.tensor(.125, dtype=torch.float32),torch.tensor(4.0, dtype=torch.float32)) cq = pack_quant_tensor(c,torch.tensor(.125, dtype=torch.float32),torch.tensor(4.0, dtype=torch.float32)) dq = pack_quant_tensor(d,torch.tensor(.125, dtype=torch.float32),torch.tensor(4.0, dtype=torch.float32)) self.data=[aq,bq,cq,dq] self.key=[torch.tensor(0.0, dtype=torch.float32),torch.tensor(1.0, dtype=torch.float32), torch.tensor(1.0, dtype=torch.float32),torch.tensor(0.0, dtype=torch.float32)]
def dropout_classifier(self, x, scale, bit_width): if self.training and self.dropout_steps > 0: out_list = [] for i in range(self.dropout_steps): out = F.dropout(x, p=self.dropout_rate) out = self.output(pack_quant_tensor(out, scale, bit_width)) quant_out, out_scale, out_bit_width = out out_list.append(quant_out) return tuple(out_list) else: out = self.output(pack_quant_tensor(x, scale, bit_width)) quant_out, out_scale, out_bit_width = out if self.compute_micronet_cost: update_conv_or_linear_cost(self.output, bit_width, out_bit_width, quant_out) return quant_out,
def forward(self, x): x = pack_quant_tensor(x, None, self.input_bit_width) x = self.features(x) quant_input, input_scale, input_bit_width = x x, scale, bit_width = self.final_pool(x) if self.compute_micronet_cost: update_avg_pool_cost(self.final_pool, x, input_bit_width) x = x.view(x.size(0), -1) x = self.dropout_classifier(x, scale, bit_width) return x
def forward(self, x): x = self.features(x) x, scale, bit_width = self.final_pool(x) x = x.view(x.size(0), -1) x = self.output(pack_quant_tensor(x, scale, bit_width)) return x
def test_brevitas_avg_pool_export(kernel_size, stride, signed, bit_width, input_bit_width, channels, idim): ishape = (1, channels, idim, idim) ibw_tensor = torch.Tensor([input_bit_width]) b_avgpool = QuantAvgPool2d( kernel_size=kernel_size, stride=stride, bit_width=bit_width, quant_type=QuantType.INT, ) # call forward pass manually once to cache scale factor and bitwidth input_tensor = torch.from_numpy(np.zeros(ishape)).float() scale = np.ones((1, channels, 1, 1)) output_scale = torch.from_numpy(scale).float() input_quant_tensor = pack_quant_tensor(tensor=input_tensor, scale=output_scale, bit_width=ibw_tensor, signed=signed) bo.export_finn_onnx(b_avgpool, ishape, export_onnx_path, input_t=input_quant_tensor) model = ModelWrapper(export_onnx_path) # determine input FINN datatype if signed is True: prefix = "INT" else: prefix = "UINT" dt_name = prefix + str(input_bit_width) dtype = DataType[dt_name] model = model.transform(InferShapes()) model = model.transform(InferDataTypes()) # execution with input tensor using integers and scale = 1 # calculate golden output inp = gen_finn_dt_tensor(dtype, ishape) input_tensor = torch.from_numpy(inp).float() input_quant_tensor = pack_quant_tensor(tensor=input_tensor, scale=output_scale, bit_width=ibw_tensor, signed=signed) b_avgpool.eval() expected = b_avgpool.forward(input_quant_tensor).tensor.detach().numpy() # finn execution idict = {model.graph.input[0].name: inp} odict = oxe.execute_onnx(model, idict, True) produced = odict[model.graph.output[0].name] assert (expected == produced).all() # execution with input tensor using float and scale != 1 scale = np.random.uniform(low=0, high=1, size=(1, channels, 1, 1)).astype(np.float32) inp_tensor = inp * scale input_tensor = torch.from_numpy(inp_tensor).float() input_scale = torch.from_numpy(scale).float() input_quant_tensor = pack_quant_tensor(tensor=input_tensor, scale=input_scale, bit_width=ibw_tensor, signed=signed) # export again to set the scale values correctly bo.export_finn_onnx(b_avgpool, ishape, export_onnx_path, input_t=input_quant_tensor) model = ModelWrapper(export_onnx_path) model = model.transform(InferShapes()) model = model.transform(InferDataTypes()) b_avgpool.eval() expected = b_avgpool.forward(input_quant_tensor).tensor.detach().numpy() # finn execution idict = {model.graph.input[0].name: inp_tensor} odict = oxe.execute_onnx(model, idict, True) produced = odict[model.graph.output[0].name] assert np.isclose(expected, produced).all() os.remove(export_onnx_path)