# 8-bit Unet Verification
目前還沒完工,但快了,還有一些小 bug 要解,以及 M 要用 fixed-point 運算的問題
- inference_Unet_v1_8bit(ver1)
```python=
# -*- coding: utf-8 -*-
"""
Created on Mon Sep 18 04:02:01 2023
@author: Jay
"""
from os import listdir
import cv2 as cv
import os
import CONV
from CONV import GEMMConv3D
from CONV import Conv3D
from CONV import Maxpool_3D
from CONV import De_Conv2x2
#from CONV import De_Conv2x2_fast
import math
from skimage.measure import block_reduce as maxpooling
import matplotlib.pyplot as plt
import numpy as np
layer = ['conv'+str(i) for i in range(1, 24)]
current_path = os.getcwd()
all_file_name = os.listdir(current_path)
print(all_file_name)
parameter = {}
floatingVar = {}
Load_parameter = 0
if Load_parameter == 1:
parameter = np.load('./parameter/parameter.npy',allow_pickle='TRUE').item()
floatingVar = np.load('./parameter/floatingVar.npy',allow_pickle='TRUE').item()
else:
for item in all_file_name:
if item in layer:
file_name = os.listdir(current_path+'/'+item)
print(file_name)
for item_in in file_name:
parameter[item+'_'+item_in[:-4]] = np.load(current_path+'/'+item+'/'+item_in)
elif item.endswith("npy"):
print('npy:', item)
floatingVar[item[:-4]] = np.load(current_path+'/'+item)
# resize the output activations
for i in range(1, 32):
floatingVar['out'+str(i)] = np.reshape(floatingVar['out'+str(i)], (floatingVar['out'+str(i)].shape[1],floatingVar['out'+str(i)].shape[2],floatingVar['out'+str(i)].shape[3]))
floatingVar['out'+str(i)+'_quantFloating'] = np.reshape(floatingVar['out'+str(i)+'_quantFloating'], (floatingVar['out'+str(i)+'_quantFloating'].shape[1],floatingVar['out'+str(i)+'_quantFloating'].shape[2],floatingVar['out'+str(i)+'_quantFloating'].shape[3]))
# Initialize the input_scale of each layer
for idx in range(2, 24):
parameter['conv' + str(idx) + '_input_scale'] = parameter['conv' + str(idx-1) + '_output_scale'].copy()
parameter['conv'+str(idx)+'_input_zero_point'] = parameter['conv'+str(idx-1)+'_output_zero']
use_shift_instead_of_divide = 2
print(" ==================== Unet inference (Int8 model) ====================")
Unet = {}
debug = {}
input_data = floatingVar['input_np'][0,]
out_num = 0
Unet['q_out'+str(out_num)] = np.round( (input_data / parameter['conv1_input_scale']) + parameter['conv1_input_zero_point'])
print("max = ", np.max(Unet['q_out'+str(out_num)]))
print("min = ", np.min(Unet['q_out'+str(out_num)]))
out_num += 1
weight_num = 1
bit = 32
# =========================================== Encoder ===========================================
for times in range(5):
print("\n-------- out{} --------".format(out_num))
# Conv + Relu
Unet['q_out'+str(out_num)] = GEMMConv3D( (Unet['q_out'+str(out_num-1)] - parameter['conv'+str(weight_num)+'_input_zero_point'] ) , parameter['conv'+str(weight_num)+'_weight_int'])
# calculate left shift bit
ratio = ( parameter['conv' + str(weight_num) + '_input_scale'] * parameter['conv' + str(weight_num) + '_weight_scale'] / parameter['conv' + str(weight_num) + '_output_scale'] )
shift_bit = math.log(ratio, 2)
shift_bit = abs( math.ceil(shift_bit) )
M = ratio / 2**(-shift_bit)
M_fixed = round(M * 2**bit)
Unet['shift_bit'+str(out_num)] = shift_bit
Unet['M'+str(out_num)] = M
Unet['M_fixed'+str(out_num)] = M_fixed
# Relu
Unet['q_out'+str(out_num)] [ Unet['q_out'+str(out_num)] < 0.0 ] = 0.0
print('ratio = {}, shift_bit = {}'.format(ratio, shift_bit))
if use_shift_instead_of_divide == 1 :
Unet['q_out'+str(out_num)] = Unet['q_out'+str(out_num)] * Unet['M_fixed'+str(out_num)]
Unet['q_out'+str(out_num)] = Unet['q_out'+str(out_num)] // (2**(bit+Unet['shift_bit'+str(out_num)]))
elif use_shift_instead_of_divide == 2 :
one = np.ones(Unet['q_out'+str(out_num)].shape)
tmp = Unet['q_out'+str(out_num)] * Unet['M_fixed'+str(out_num)]
float_int_err = ( tmp / (2**(bit+Unet['shift_bit'+str(out_num)])) ) - ( tmp // (2**(bit+Unet['shift_bit'+str(out_num)])) )
outTmp = tmp // (2**(bit+Unet['shift_bit'+str(out_num)]))
tag = float_int_err > 0.5
Unet['q_out'+str(out_num)] = outTmp.copy()
Unet['q_out'+str(out_num)][tag] = outTmp[tag] + one[tag]
else:
Unet['q_out'+str(out_num)] = np.round( Unet['q_out'+str(out_num)] * ratio )
Unet['q_out'+str(out_num)] += parameter['conv' + str(weight_num) + '_output_zero']
Unet['q_out'+str(out_num)] [ Unet['q_out'+str(out_num)] > 255.0 ] = 255.0
print("max = ", np.max(Unet['q_out'+str(out_num)]))
print("min = ", np.min(Unet['q_out'+str(out_num)]))
Unet['ratio'+str(out_num)] = ratio
Unet['q_out_floating'+str(out_num)] = parameter['conv' + str(weight_num) + '_output_scale'] * (Unet['q_out'+str(out_num)] - parameter['conv'+str(weight_num)+'_output_zero'] )
debug['out'+str(out_num)+'_quantFloating_quant'] = np.round( (floatingVar['out'+str(out_num)+'_quantFloating'] / parameter['conv' + str(weight_num) + '_output_scale']) + parameter['conv'+str(weight_num)+'_output_zero'])
out_num += 1
weight_num += 1
#--------------------------------------------------------------------------------------------------------
print("\n-------- out{} --------".format(out_num))
# Conv + Relu
Unet['q_out'+str(out_num)] = GEMMConv3D( (Unet['q_out'+str(out_num-1)] - parameter['conv'+str(weight_num)+'_input_zero_point'] ) , parameter['conv'+str(weight_num)+'_weight_int'])
# calculate left shift bit
ratio = ( parameter['conv' + str(weight_num) + '_input_scale'] * parameter['conv' + str(weight_num) + '_weight_scale'] / parameter['conv' + str(weight_num) + '_output_scale'] )
shift_bit = math.log(ratio, 2)
shift_bit = abs( math.ceil(shift_bit) )
M = ratio / 2**(-shift_bit)
M_fixed = round(M * 2**bit)
Unet['shift_bit'+str(out_num)] = shift_bit
Unet['M'+str(out_num)] = M
Unet['M_fixed'+str(out_num)] = M_fixed
# Relu
Unet['q_out'+str(out_num)] [ Unet['q_out'+str(out_num)] < 0.0 ] = 0.0
print('ratio = {}, shift_bit = {}'.format(ratio, shift_bit))
if use_shift_instead_of_divide == 1 :
Unet['q_out'+str(out_num)] = Unet['q_out'+str(out_num)] * Unet['M_fixed'+str(out_num)]
Unet['q_out'+str(out_num)] = Unet['q_out'+str(out_num)] // (2**(bit+Unet['shift_bit'+str(out_num)]))
elif use_shift_instead_of_divide == 2 :
one = np.ones(Unet['q_out'+str(out_num)].shape)
tmp = Unet['q_out'+str(out_num)] * Unet['M_fixed'+str(out_num)]
float_int_err = ( tmp / (2**(bit+Unet['shift_bit'+str(out_num)])) ) - ( tmp // (2**(bit+Unet['shift_bit'+str(out_num)])) )
outTmp = tmp // (2**(bit+Unet['shift_bit'+str(out_num)]))
tag = float_int_err > 0.5
Unet['q_out'+str(out_num)] = outTmp.copy()
Unet['q_out'+str(out_num)][tag] = outTmp[tag] + one[tag]
else:
Unet['q_out'+str(out_num)] = np.round( Unet['q_out'+str(out_num)] * ratio )
Unet['q_out'+str(out_num)] += parameter['conv' + str(weight_num) + '_output_zero']
Unet['q_out'+str(out_num)] [ Unet['q_out'+str(out_num)] > 255.0 ] = 255.0
print("max = ", np.max(Unet['q_out'+str(out_num)]))
print("min = ", np.min(Unet['q_out'+str(out_num)]))
Unet['ratio'+str(out_num)] = ratio
Unet['q_out_floating'+str(out_num)] = parameter['conv' + str(weight_num) + '_output_scale'] * (Unet['q_out'+str(out_num)] - parameter['conv'+str(weight_num)+'_output_zero'] )
debug['out'+str(out_num)+'_quantFloating_quant'] = np.round( (floatingVar['out'+str(out_num)+'_quantFloating'] / parameter['conv' + str(weight_num) + '_output_scale']) + parameter['conv'+str(weight_num)+'_output_zero'])
out_num += 1
weight_num += 1
if(times < 4):
print("\n-------- out{} --------".format(out_num))
# Pooling
Unet['q_out'+str(out_num)] = Maxpool_3D(Unet['q_out'+str(out_num-1)])
out_num += 1
'''
print(" ===================== check with Ans (each layer) ===================== ")
checkList = [1, 2]
for i in range(len(checkList)):
print('---------check out{}------------'.format(checkList[i]))
temp1 = Unet['q_out'+str(checkList[i])]
temp2 = debug['out'+str(checkList[i])+'_quantFloating_quant']
err = temp1 - temp2
print("max err = ", np.max(err))
print("min err = ", np.min(err))
'''
print("====================================================================================================")
print('------check input------')
input_int = floatingVar['input_int']
my_input_int = Unet['q_out'+str(0)]
err_input = input_int - my_input_int
print("max err = ", np.max(err_input))
print("min err = ", np.min(err_input))
if((input_int == my_input_int).all()):
print("same")
else:
print('different')
print('------check weight1------')
weight1_int = parameter['conv'+str(1)+'_weight_int']
weight1_int_fromFloat = np.round ( (floatingVar['conv1_weight'] / parameter['conv1_weight_scale'] + parameter['conv1_weight_zero'] ) )
err_weight1 = weight1_int - weight1_int_fromFloat
print("max err = ", np.max(err_weight1))
print("min err = ", np.min(err_weight1))
if((weight1_int == weight1_int_fromFloat).all()):
print("same")
else:
print('different')
print("====================================================================================================")
#print(out_num)
#print(weight_num)
# =========================================== Decoder ===========================================
catNum = 11
for times in range(4):
#--------------------------------------------------------------------------------------------------------
print("\n-------- out{} --------".format(out_num))
# de-Conv
Unet['q_out'+str(out_num)] = De_Conv2x2((Unet['q_out'+str(out_num-1)] - parameter['conv'+str(weight_num)+'_input_zero_point'] ) , parameter['conv'+str(weight_num)+'_weight_int'])
# calculate left shift bit
ratio = ( parameter['conv' + str(weight_num) + '_input_scale'] * parameter['conv' + str(weight_num) + '_weight_scale'] / parameter['conv' + str(weight_num) + '_output_scale'] )
shift_bit = math.log(ratio, 2)
shift_bit = abs( math.ceil(shift_bit) )
M = ratio / 2**(-shift_bit)
M_fixed = round(M * 2**bit)
Unet['shift_bit'+str(out_num)] = shift_bit
Unet['M'+str(out_num)] = M
Unet['M_fixed'+str(out_num)] = M_fixed
print('ratio = {}, shift_bit = {}'.format(ratio, shift_bit))
if use_shift_instead_of_divide == 1 :
Unet['q_out'+str(out_num)] = Unet['q_out'+str(out_num)] * Unet['M_fixed'+str(out_num)]
Unet['q_out'+str(out_num)] = Unet['q_out'+str(out_num)] // (2**(bit+Unet['shift_bit'+str(out_num)]))
elif use_shift_instead_of_divide == 2 :
one = np.ones(Unet['q_out'+str(out_num)].shape)
tmp = Unet['q_out'+str(out_num)] * Unet['M_fixed'+str(out_num)]
float_int_err = ( tmp / (2**(bit+Unet['shift_bit'+str(out_num)])) ) - ( tmp // (2**(bit+Unet['shift_bit'+str(out_num)])) )
outTmp = tmp // (2**(bit+Unet['shift_bit'+str(out_num)]))
tag = float_int_err > 0.5
Unet['q_out'+str(out_num)] = outTmp.copy()
Unet['q_out'+str(out_num)][tag] = outTmp[tag] + one[tag]
else:
Unet['q_out'+str(out_num)] = np.round( Unet['q_out'+str(out_num)] * ratio )
Unet['q_out'+str(out_num)] += parameter['conv' + str(weight_num) + '_output_zero']
Unet['q_out'+str(out_num)] [ Unet['q_out'+str(out_num)] > 255.0 ] = 255.0
Unet['q_out'+str(out_num)] [ Unet['q_out'+str(out_num)] < 0.0 ] = 0.0
#Unet['q_out'+str(out_num)] += abs( np.min(Unet['q_out'+str(out_num)]) )
print("max = ", np.max(Unet['q_out'+str(out_num)]))
print("min = ", np.min(Unet['q_out'+str(out_num)]))
Unet['ratio'+str(out_num)] = ratio
Unet['q_out_floating'+str(out_num)] = parameter['conv' + str(weight_num) + '_output_scale'] * (Unet['q_out'+str(out_num)] - parameter['conv'+str(weight_num)+'_output_zero'] )
debug['out'+str(out_num)+'_quantFloating_quant'] = np.round( (floatingVar['out'+str(out_num)+'_quantFloating'] / parameter['conv' + str(weight_num) + '_output_scale']) + parameter['conv'+str(weight_num)+'_output_zero'])
out_num += 1
weight_num += 1
#--------------------------------------------------------------------------------------------------------
print("\n-------- out{} --------".format(out_num))
# concatenate
Unet['q_out'+str(out_num)] = np.concatenate([Unet['q_out'+str(out_num-1)], Unet['q_out'+str(catNum)]], axis=0)
out_num += 1
#--------------------------------------------------------------------------------------------------------
print("\n-------- out{} --------".format(out_num))
# Conv + Relu
Unet['q_out'+str(out_num)] = GEMMConv3D( (Unet['q_out'+str(out_num-1)] - parameter['conv'+str(weight_num)+'_input_zero_point'] ) , parameter['conv'+str(weight_num)+'_weight_int'])
# calculate left shift bit
ratio = ( parameter['conv' + str(weight_num) + '_input_scale'] * parameter['conv' + str(weight_num) + '_weight_scale'] / parameter['conv' + str(weight_num) + '_output_scale'] )
shift_bit = math.log(ratio, 2)
shift_bit = abs( math.ceil(shift_bit) )
M = ratio / 2**(-shift_bit)
M_fixed = round(M * 2**bit)
Unet['shift_bit'+str(out_num)] = shift_bit
Unet['M'+str(out_num)] = M
Unet['M_fixed'+str(out_num)] = M_fixed
# Relu
Unet['q_out'+str(out_num)] [ Unet['q_out'+str(out_num)] < 0.0 ] = 0.0
print('ratio = {}, shift_bit = {}'.format(ratio, shift_bit))
if use_shift_instead_of_divide == 1 :
Unet['q_out'+str(out_num)] = Unet['q_out'+str(out_num)] * Unet['M_fixed'+str(out_num)]
Unet['q_out'+str(out_num)] = Unet['q_out'+str(out_num)] // (2**(bit+Unet['shift_bit'+str(out_num)]))
elif use_shift_instead_of_divide == 2 :
one = np.ones(Unet['q_out'+str(out_num)].shape)
tmp = Unet['q_out'+str(out_num)] * Unet['M_fixed'+str(out_num)]
float_int_err = ( tmp / (2**(bit+Unet['shift_bit'+str(out_num)])) ) - ( tmp // (2**(bit+Unet['shift_bit'+str(out_num)])) )
outTmp = tmp // (2**(bit+Unet['shift_bit'+str(out_num)]))
tag = float_int_err > 0.5
Unet['q_out'+str(out_num)] = outTmp.copy()
Unet['q_out'+str(out_num)][tag] = outTmp[tag] + one[tag]
else:
Unet['q_out'+str(out_num)] = np.round( Unet['q_out'+str(out_num)] * ratio )
Unet['q_out'+str(out_num)] += parameter['conv' + str(weight_num) + '_output_zero']
Unet['q_out'+str(out_num)] [ Unet['q_out'+str(out_num)] > 255.0 ] = 255.0
print("max = ", np.max(Unet['q_out'+str(out_num)]))
print("min = ", np.min(Unet['q_out'+str(out_num)]))
Unet['ratio'+str(out_num)] = ratio
Unet['q_out_floating'+str(out_num)] = parameter['conv' + str(weight_num) + '_output_scale'] * (Unet['q_out'+str(out_num)] - parameter['conv'+str(weight_num)+'_output_zero'] )
debug['out'+str(out_num)+'_quantFloating_quant'] = np.round( (floatingVar['out'+str(out_num)+'_quantFloating'] / parameter['conv' + str(weight_num) + '_output_scale']) + parameter['conv'+str(weight_num)+'_output_zero'])
out_num += 1
weight_num += 1
#--------------------------------------------------------------------------------------------------------
print("\n-------- out{} --------".format(out_num))
# Conv + Relu
Unet['q_out'+str(out_num)] = GEMMConv3D( (Unet['q_out'+str(out_num-1)] - parameter['conv'+str(weight_num)+'_input_zero_point'] ) , parameter['conv'+str(weight_num)+'_weight_int'])
# calculate left shift bit
ratio = ( parameter['conv' + str(weight_num) + '_input_scale'] * parameter['conv' + str(weight_num) + '_weight_scale'] / parameter['conv' + str(weight_num) + '_output_scale'] )
shift_bit = math.log(ratio, 2)
shift_bit = abs( math.ceil(shift_bit) )
M = ratio / 2**(-shift_bit)
M_fixed = round(M * 2**bit)
Unet['shift_bit'+str(out_num)] = shift_bit
Unet['M'+str(out_num)] = M
Unet['M_fixed'+str(out_num)] = M_fixed
# Relu
Unet['q_out'+str(out_num)] [ Unet['q_out'+str(out_num)] < 0.0 ] = 0.0
print('ratio = {}, shift_bit = {}'.format(ratio, shift_bit))
if use_shift_instead_of_divide == 1 :
Unet['q_out'+str(out_num)] = Unet['q_out'+str(out_num)] * Unet['M_fixed'+str(out_num)]
Unet['q_out'+str(out_num)] = Unet['q_out'+str(out_num)] // (2**(bit+Unet['shift_bit'+str(out_num)]))
elif use_shift_instead_of_divide == 2 :
one = np.ones(Unet['q_out'+str(out_num)].shape)
tmp = Unet['q_out'+str(out_num)] * Unet['M_fixed'+str(out_num)]
float_int_err = ( tmp / (2**(bit+Unet['shift_bit'+str(out_num)])) ) - ( tmp // (2**(bit+Unet['shift_bit'+str(out_num)])) )
outTmp = tmp // (2**(bit+Unet['shift_bit'+str(out_num)]))
tag = float_int_err > 0.5
Unet['q_out'+str(out_num)] = outTmp.copy()
Unet['q_out'+str(out_num)][tag] = outTmp[tag] + one[tag]
else:
Unet['q_out'+str(out_num)] = np.round( Unet['q_out'+str(out_num)] * ratio )
Unet['q_out'+str(out_num)] += parameter['conv' + str(weight_num) + '_output_zero']
Unet['q_out'+str(out_num)] [ Unet['q_out'+str(out_num)] > 255.0 ] = 255.0
print("max = ", np.max(Unet['q_out'+str(out_num)]))
print("min = ", np.min(Unet['q_out'+str(out_num)]))
Unet['ratio'+str(out_num)] = ratio
Unet['q_out_floating'+str(out_num)] = parameter['conv' + str(weight_num) + '_output_scale'] * (Unet['q_out'+str(out_num)] - parameter['conv'+str(weight_num)+'_output_zero'] )
debug['out'+str(out_num)+'_quantFloating_quant'] = np.round( (floatingVar['out'+str(out_num)+'_quantFloating'] / parameter['conv' + str(weight_num) + '_output_scale']) + parameter['conv'+str(weight_num)+'_output_zero'])
out_num += 1
weight_num += 1
catNum -= 3
print("\n-------- out{} --------".format(out_num))
# =========================================== Output Layer ===========================================
output_channel = floatingVar['conv'+str(weight_num)+'_weight'].shape[0]
input_channel = floatingVar['conv'+str(weight_num)+'_weight'].shape[1]
floatingVar['conv'+str(weight_num)+'_weight'] = np.reshape(floatingVar['conv'+str(weight_num)+'_weight'], (-1, floatingVar['conv'+str(weight_num)+'_weight'].shape[1]))
parameter['conv'+str(weight_num)+'_weight_int'] = np.reshape( parameter['conv'+str(weight_num)+'_weight_int'], (-1, parameter['conv'+str(weight_num)+'_weight_int'].shape[1]))
Unet['q_out'+str(out_num)] = np.zeros([output_channel, Unet['q_out'+str(out_num-1)].shape[1], Unet['q_out'+str(out_num-1)].shape[2]])
outTmp = np.zeros([output_channel, Unet['q_out'+str(out_num-1)].shape[1], Unet['q_out'+str(out_num-1)].shape[2]])
Unet['q_out'+str(out_num-1)] -= parameter['conv'+str(weight_num)+'_input_zero_point']
for oc in range(output_channel):
for ic in range(input_channel):
for y in range(Unet['q_out'+str(out_num-1)].shape[1]):
for x in range(Unet['q_out'+str(out_num-1)].shape[2]):
Unet['q_out'+str(out_num)][oc, y, x] += Unet['q_out'+str(out_num-1)][ic, y, x] * parameter['conv'+str(weight_num)+'_weight_int'][0, ic]
# calculate left shift bit
ratio = ( parameter['conv' + str(weight_num) + '_input_scale'] * parameter['conv' + str(weight_num) + '_weight_scale'] / parameter['conv' + str(weight_num) + '_output_scale'] )
shift_bit = math.log(ratio, 2)
shift_bit = abs( math.ceil(shift_bit) )
M = ratio / 2**(-shift_bit)
M_fixed = round(M * 2**bit)
Unet['shift_bit'+str(out_num)] = shift_bit
Unet['M'+str(out_num)] = M
Unet['M_fixed'+str(out_num)] = M_fixed
print('ratio = {}, shift_bit = {}'.format(ratio, shift_bit))
if use_shift_instead_of_divide == 1 :
Unet['q_out'+str(out_num)] = Unet['q_out'+str(out_num)] * Unet['M_fixed'+str(out_num)]
Unet['q_out'+str(out_num)] = Unet['q_out'+str(out_num)] // (2**(bit+Unet['shift_bit'+str(out_num)]))
elif use_shift_instead_of_divide == 2 :
one = np.ones(Unet['q_out'+str(out_num)].shape)
tmp = Unet['q_out'+str(out_num)] * Unet['M_fixed'+str(out_num)]
float_int_err = ( tmp / (2**(bit+Unet['shift_bit'+str(out_num)])) ) - ( tmp // (2**(bit+Unet['shift_bit'+str(out_num)])) )
outTmp = tmp // (2**(bit+Unet['shift_bit'+str(out_num)]))
tag = float_int_err > 0.5
Unet['q_out'+str(out_num)] = outTmp.copy()
Unet['q_out'+str(out_num)][tag] = outTmp[tag] + one[tag]
else:
Unet['q_out'+str(out_num)] = np.round( Unet['q_out'+str(out_num)] * ratio )
Unet['q_out'+str(out_num)] += parameter['conv' + str(weight_num) + '_output_zero']
Unet['q_out'+str(out_num)] [ Unet['q_out'+str(out_num)] > 255.0 ] = 255.0
print("max = ", np.max(Unet['q_out'+str(out_num)]))
print("min = ", np.min(Unet['q_out'+str(out_num)]))
Unet['ratio'+str(out_num)] = ratio
Unet['q_out_floating'+str(out_num)] = parameter['conv' + str(weight_num) + '_output_scale'] * (Unet['q_out'+str(out_num)] - parameter['conv'+str(weight_num)+'_output_zero'] )
debug['out'+str(out_num)+'_quantFloating_quant'] = np.round( (floatingVar['out'+str(out_num)+'_quantFloating'] / parameter['conv' + str(weight_num) + '_output_scale']) + parameter['conv'+str(weight_num)+'_output_zero'])
print(" ===================== check with Ans (each layer) ===================== ")
checkList = [1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 15, 17, 18, 19, 21, 22, 23, 25, 26, 27, 29, 30, 31]
for i in range(len(checkList)):
print('---------check out{}------------'.format(checkList[i]))
temp1 = Unet['q_out'+str(checkList[i])]
temp2 = debug['out'+str(checkList[i])+'_quantFloating_quant']
err = temp1 - temp2
print("max err = ", np.max(err))
print("min err = ", np.min(err))
print(" ===================== check with out31 (floating point) ===================== ")
out31_floating = parameter['conv' + str(weight_num) + '_output_scale'] * ( Unet['q_out'+str(out_num)] - parameter['conv'+str(weight_num)+'_output_zero'] )
out31_floating_ans = floatingVar['out'+str(out_num)+'_quantFloating']
err = out31_floating - out31_floating_ans
print("max err = ", np.max(err))
print("min err = ", np.min(err))
# =========================================== Sigmoid ===========================================
myOutput = out31_floating
one = np.ones([1, 224, 224])
mySigmoidOutput = one / (one + np.exp(-myOutput))
ans = floatingVar['output_np'][0]
print(" ===================== check with Sigmoid output (floating point) ===================== ")
err = mySigmoidOutput - ans
print("max err = ", np.max(err))
print("min err = ", np.min(err))
inputImage = (input_data[0] * 255).astype("uint8")
label = (floatingVar['label_np'][0, 0] * 255).astype("uint8")
imageAns = (ans[0] * 255).astype("uint8")
imageMy = (mySigmoidOutput[0] * 255).astype("uint8")
print(" ===================== check with Ans (uint8 of image) ===================== ")
err = imageAns.astype("int32") - imageMy.astype("int32")
print("max err = ", np.max(err))
print("min err = ", np.min(err))
def IOU_calculate(arr1_one_tag, arr2_one_tag):
intersect = np.sum(arr1_one_tag * arr2_one_tag)
union = np.sum(arr1_one_tag) + np.sum(arr2_one_tag) - intersect
iou = round(intersect/union, 5)
return iou
label_tag = label >= 250
floating_tag = imageAns >= 250
uint8_floating_tag = floatingVar['Image_output'] >= 250
uint8_tag = imageMy >= 250
print("-------------------- IOU --------------------")
print("IOU of floating = ", IOU_calculate(label_tag, floating_tag))
print("IOU of uint8 floating = ", IOU_calculate(label_tag, uint8_floating_tag))
print("IOU of uint8 = ", IOU_calculate(label_tag, uint8_tag))
# =========================================== visualization ===========================================
fig, axes = plt.subplots(ncols=4, figsize=(10, 3), sharex=True, sharey=True)
ax = axes.ravel()
ax[0].imshow(inputImage, cmap=plt.cm.gray)
ax[0].set_title('input data')
ax[1].imshow(label, cmap=plt.cm.gray)
ax[1].set_title('label')
ax[2].imshow(imageAns, cmap=plt.cm.gray)
ax[2].set_title('floating Unet(IOU=' + str( IOU_calculate(label_tag, uint8_floating_tag) ) + ')')
ax[3].imshow(imageMy, cmap=plt.cm.gray)
ax[3].set_title('8-bit Unet(IOU=' + str( IOU_calculate(label_tag, uint8_tag) ) + ')')
#fig.show()
fig.tight_layout()
#plt.subplots_adjust(wspace=0, hspace=0)
fig.savefig('8-bit Unet result.png')
```
```python=
# -*- coding: utf-8 -*-
"""
Created on Mon Sep 18 21:58:04 2023
@author: leots
"""
import os
import numpy as np
import torch
from CONV import GEMMConv3D
from CONV import Maxpool_3D
from CONV import De_Conv2x2
#====================================Read Files=========================================#
current_path = os.getcwd()
all_file_name = os.listdir(current_path) # it prints out all file names in this directory
#print("all_file_name",all_file_name)
layer = ['conv'+str(i) for i in range(1, 24)]
parameter = {}
floatingVar = {}
quantizedOutAct = {}
Load_parameter = 1
if Load_parameter == 1:
parameter = np.load('parameter.npy',allow_pickle='TRUE').item()
floatingVar = np.load('floatingVar.npy',allow_pickle='TRUE').item()
else:
for item in all_file_name:
if item in layer:
file_name = os.listdir(current_path+'/'+item)
'''
if item == 'conv1':
print(item)
print(file_name)
'''
for item_in in file_name:
#if item == 'conv1':
#print(item_in[:-4]) # excludes .npy -> clever!!!
parameter[item+'_'+item_in[:-4]] = np.load(current_path+'/'+item+'/'+item_in)
elif item.endswith("npy"):
#print('npy:', item)
floatingVar[item[:-4]] = np.load(current_path+'/'+item)
#============================Load Quantized act. output=======================================#
for item in all_file_name:
if item == 'quantized_act_out':
file_name = os.listdir(current_path+'/'+item)
for in_item in file_name:
#print(in_item)
quantizedOutAct[in_item[:-4]] = np.load(current_path+'/'+item+'/'+in_item)
# CONV1 first
#///////////////////////////////Computation starts!!!//////////////////////////////////////#
#convi_wight is 4D, except conv23_weigth, which is 1x1 conv
#==============================Converts input_np into quantized tensor==================================#
input_tensor = torch.tensor(floatingVar['input_np'])
#torch.quantize_per_tensor(input, scale, zero_point, dtype) → Tensor, using .int_rep() shows integer representation
input_scale = torch.tensor(parameter['conv1_input_scale'])
input_zero_point = torch.tensor(parameter['conv1_input_zero_point'])
quantized_input = torch.round(input_tensor/input_scale+ input_zero_point)
quantized_input = torch.tensor(quantized_input, dtype=torch.uint8)
quantized_input = quantized_input.numpy() #transforms tensor into np for GEMM
# before calling GEMM3D the operands need to be formated into 3D array
quantized_input = quantized_input.reshape(quantized_input.shape[1], quantized_input.shape[2], quantized_input.shape[3])
output = GEMMConv3D(quantized_input, parameter['conv1_weight_int']) #GEMM
output = torch.tensor(output, dtype=torch.float32) # the same
#print(np.max(quantized_conv1_output_np), np.min(quantized_conv1_output_np)) #max: 46355, min: 0
# verify dequantized output and the real output
# Note: dequantize() seems not to be working
output_scale = torch.tensor(parameter['conv1_output_scale'])
output_zero_point = torch.tensor(parameter['conv1_output_zero'])
weight_scale = parameter['conv1_weight_scale']
'''
output_torch = torch.quantize_per_tensor(output, output_scale, output_zero_point, torch.quint8).int_repr() # quantize the GEMM output
output_torch = output_torch.numpy()
'''
output_my = output*input_scale*weight_scale/output_scale+output_zero_point
#output_my_round = np.round(output_my)
#output_my_round = output_my_round.numpy()
output_my = np.round(output_my.numpy())
output_my[output_my < 0.0] = 0.0 #ReLU
#output_my_round[output_my_round < 0.0] = 0.0
# quantize the golden data to compare with my quantized output
golden_output = torch.tensor(floatingVar['out1'])
#golden_output = torch.quantize_per_tensor(golden_output, output_scale, output_zero_point, torch.quint8).int_repr()
golden_output = torch.round(golden_output/output_scale+output_zero_point)
golden_output = golden_output.numpy()
# error between floating and quantized output still exists -> 0.9799
'''
ans = golden_output
error = np.abs(quantizedOutAct['qout1'] - floatingVar['out1'])
print('max of error = ', np.max(error))
if (np.max(error) < 1e-5):
print("pass!!")
else:
print("failed.....")
'''
ans = golden_output
error = np.abs(output_my - ans)
print('max of error = ', np.max(error))
print('max error index = ', np.where(error == np.max(error)))
if (np.max(error) < 3):
print("pass!!")
else:
print("failed.....")
```