量化映射的通用公式为:
r
=
S
(
q
−
Z
)
r = S(q - Z)
r=S(q−Z)
其中r表示量化前数据的真实值,S表示缩放因子,q表示量化后的数值,Z表示零点
非对称量化需要一个偏移量Z来完成零点的映射,即量化前的零点和量化后的零点不一致。
非对称量化的一般公式为:
1.计算缩放因子S和偏移量Z
S
=
r
m
a
x
−
r
m
i
n
q
m
a
x
−
q
m
i
n
S = \frac{r_{max} - r_{min}}{q_{max} - q_{min}}
S=qmax−qminrmax−rmin
Z
=
q
m
a
x
−
R
o
u
n
d
(
r
m
a
x
S
)
Z = q_{max} - Round(\frac{r_{max}}{S})
Z=qmax−Round(Srmax)
r
m
a
x
r_{max}
rmax和
r
m
i
n
r_{min}
rmin表示真实数据的最大值和最小值,
q
m
a
x
q_{max}
qmax和
q
m
i
n
q_{min}
qmin表示量化后的最大值和最小值,例如uint8就是127和-128。 Round()表示取整,如果是量化为int型。
2.量化
q
=
R
o
u
n
d
(
r
S
+
Z
)
q = Round(\frac{r}{S} + Z)
q=Round(Sr+Z)
3.反量化
r
=
(
q
−
Z
)
∗
S
r = (q - Z)*S
r=(q−Z)∗S
对称量化在量化前和量化后的零点保持一致,即零点对应,因此无需像非对称量化那样引入一个偏移量Z。
对称量化的一般公式为:
1.计算缩放因子
S
=
∣
r
m
a
x
∣
∣
q
m
a
x
∣
S = \frac{|r_{max}|}{|q_{max}|}
S=∣qmax∣∣rmax∣
2.量化
q
=
R
o
u
n
d
(
r
S
)
q = Round(\frac{r}{S})
q=Round(Sr)
Round()表示取整,如果是量化为int型。
3.反量化
r
=
q
∗
S
r = q*S
r=q∗S
对称量化无需引入偏移量Z,因此计算量低,缺点是量化后的数据是非饱和的,即有一部分区域不存在量化的数据。
非对称量化因为额外引入了一个偏移量来修正零点,因此需要的计算量会大一点。优点是其量化后的数据是饱和的,即量化前的最小值对应量化范围的最小值,量化后的最大值对应量化范围的最大值。
当数据不存在离散点时,非对称量化得到的量化数据是饱和的。但是当数据存在离散点时,量化后的数据就会分布不合理。
通过直方图可以有效过滤离散点,即在一定置信度范围内保留一定范围的数据,将范围外的数据当作离散点进行过滤。
def histgram_range(x, int_max):
hist, range = np.histogram(x, 100) # 划分成100块
total = len(x) # 数据量
left = 0
right = len(hist) - 1
limit = 0.99 # 只保留99%的数据
while True:
cover_paecent = hist[left:right].sum() / total
if cover_paecent <= limit:
break
# 双指针移动
elif(hist[left] <= hist[right]):
left += 1
else:
right -= 1
left_val = range[left]
right_val = range[right]
dynamic_range = max(abs(left_val), abs(right_val))
return dynamic_range / int_max # cal scale