-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathquantization_utils.py
135 lines (118 loc) · 5.19 KB
/
quantization_utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import numpy as np
import tensorflow as tf
import math
'''
utility function
with with block.suppress_stdout_stderr():
your code
To hide stdout/stderr output i.e. from Tensorflow initialzation
'''
from . import suppress_stdout_stderr as block
def tf_symbolic_convert(value, wl, fl):
'''
Convert float numpy array to wl-bit low precision data with Tensorflow API
Inputs:
- value : a numpy array of input data
- wl : word length of the data format to convert
- fl : fraction length (exponent length for floating-point)
Returns:
- val_fp : tf.Tensor as the symbolic expression for quantization
'''
# ================================================================ #
# YOUR CODE HERE:
# tf.clip_by_value could be helpful
# ================================================================ #
data_tf = tf.convert_to_tensor(value, np.float32)
wlf = tf.cast(wl,tf.float32)
flf = tf.cast(fl,tf.float32)
Quant_step = tf.math.reciprocal(tf.math.pow(2.0,flf,name=None),name=None)
min = - tf.math.pow(2.0,tf.math.subtract(tf.math.subtract(wlf, flf, name=None), 1 , name=None))
max = tf.math.subtract(tf.math.pow(2.0,tf.math.subtract(tf.math.subtract(wlf, flf, name=None), 1 , name=None)),Quant_step,name=None)
a = tf.math.divide_no_nan((tf.math.subtract(data_tf,min,name=None)),Quant_step,name=None)
b = tf.math.round(a,name=None)
c = tf.math.multiply(b,Quant_step)
d = tf.math.add(min,c,name=None)
val_fp = tf.clip_by_value(d, clip_value_min=min, clip_value_max=max)
# ================================================================ #
# END YOUR CODE HERE
# ================================================================ #
return val_fp
class Qnn:
def __init__(self):
pass
# dtype convertion: basic functions
def to_fixedpoint(self, data_i, word_len, frac_len):
return tf_symbolic_convert(data_i, word_len, frac_len)
# utility function to convert symbolically or numerically
def convert(self, data_i, word_len, frac_len, symbolic=False):
if symbolic is True:
data_q = self.to_fixedpoint(data_i, word_len, frac_len)
else:
with tf.Graph().as_default():
data_q = self.to_fixedpoint(data_i, word_len, frac_len)
with block.suppress_stdout_stderr():
with tf.Session() as sess:
data_q = sess.run(data_q)
return data_q
# error measurement
def difference(self, data_q, data_origin):
'''
Compute the difference before and after quantization
Inputs:
- data_q: a numpy array of quantized data
- data_origin: a numpy array of original data
Returns:
- dif : numerical value of quantization error
'''
# ================================================================ #
# YOUR CODE HERE:
# implement mean squared error between data_q and data_origin
# ================================================================ #
mse = ((data_q - data_origin)**2)
dif = np.mean(mse)
# ================================================================ #
# END YOUR CODE HERE
# ================================================================ #
return dif
# search policy
def search(self, data_i, word_len):
'''
Search for the optimal fraction length that leads to minimal quantization error for data_i
Inputs:
- data_i : a numpy array of original data
- word_len : word length of quantized data
Returns:
- fl_opt : fraction length (python built-in int data type) that leads to minimal quantization error
'''
# ================================================================ #
# YOUR CODE HERE:
# compute quantization error for different fraction lengths
# and determine fl_opt
# ================================================================ #
FL=0
fl_opt = 0
min_mse = 1000000000000000000000
while FL < word_len:
Quant_step = 1/(pow(2,FL))
min = - pow(2, word_len-FL-1)
max = pow(2, word_len-FL-1) - Quant_step
print(Quant_step, min , max)
out_array = min + (np.round((data_i - min)/Quant_step) * Quant_step)
data_q = np.clip(out_array, a_min = min, a_max = max)
mse = self.difference(data_i,data_q)
#print(---- data_q)
print(mse)
if mse < min_mse:
min_mse = mse
fl_opt = FL
FL = FL+1
# print(opt_FL)
# ================================================================ #
# END YOUR CODE HERE
# ================================================================ #
return fl_opt
# granularity
def apply(self, data_i, word_len):
fl_opt = self.search(data_i, word_len)
data_q = self.convert(data_i, word_len, fl_opt)
return data_q, fl_opt