定点化就是把浮点转换成指定位宽的整数。
需要定点化操作的情形:
- 将浮点数转换为指定位宽的整数;
- 定点数的精度调整,即移位、截断;
- 定点数的乘加运算;
- 定点数对齐。
1 定点化转换
对于一个浮点小数,我们要将其转换为9bit位宽的整数,如何转换才能保证最大保留其精度呢?
这里举例说明。假设一个浮点数如下:
num_float = 0.1234567
对应定点数位宽为:
bit = 9
这里假定该定点数为有符号整数,那么其数值范围为
−
2
8
∼
2
8
−
1
-2^{8} \sim 2^{8}-1
−28∼28−1.
为了将浮点转换为整数,我们需要使浮点数乘以一个因子使得其值落在
−
2
8
∼
2
8
−
1
-2^{8} \sim 2^{8}-1
−28∼28−1之间,想要保留最大精度,那么如果浮点数为正值,当然,选择整数最大能显示的数值。一般地浮点数与定点数的转换因子如下:
KaTeX parse error: Expected 'EOF', got '_' at position 14: \text{scaling_̲factor} = \left…
这里n = bit = 9
。但是,这里的scaling_factor
不是整数,也不是2的倍数。scaling_factor
是整数且是2的倍数是为了考虑能够用定点数的位宽位置表示小数点位置,这样,通过移位、截断等操作就可以改变数值精度而不改变实际值的有效数值。后面将举例说明。
这里考虑如何将scaling_factor
转为整数且为2的倍数:
首先对scaling_factor
取log2
对数,
log_scaling_factor = log2(scaling_factor)
然后对其取整,这里杨晨给了三种方式:
- conservative** 保守计算:
int_log_scaling_factor = floor(log_scaling_factor)
。能够使最终得到的整数范围在$ 2^{n-2} \sim 2^{n-1}-1 (正数)或者 (正数)或者 (正数)或者 -2^{n-1} \sim -2^{n-2} $,我们目前就是采用的这种方法,能保证数值也不溢出 - aggressive* 激进计算:
int_log_scaling_factor = ceil(log_scaling_factor)
。虽然精度看起来能表示更高,但这里数值一定会溢出,个人认为不宜采用 - neutral 适度计算:
int_log_scaling_factor = round(log_scaling_factor)
同样会存在数值溢出,也不宜采用…
得到int_log_scaling_factor
后,最终我们可得到,一般地有
\text{scaling_factor} = \left{
\begin{align}
2{\left[\log_2\frac{2{n-1}-1}{\text{num_float}}\right]}, &\quad \text{num_float} > 0; \
2{\left[\log_2\frac{-2{n-1}}{\text{num_float}}\right]}, &\quad \text{num_float} < 0; \
1, &\quad \text{num_float} = 0.
\end{align}
\right.
然后,得到定点整数为
num_quantized = clip(round(scaling_factor * num_float), min=-2**(n-1), max=2**(n-1)-1)
这里scaling_factor
为
2
11
2^{11}
211,得到的定点整数为253。
那么定点数253的真实值是多少?换句话说小数点在哪儿?
253的真实值为253/scaling_factor
.
将253转换为二进制,则得到+11111101
。其小数点为向左移log2(scaling_factor)
步数的位置。即为+[.][0][0]11111101
。
需要说明的是:在神经网络中,某一特征层或者权重的定点化是根据统计得到最大绝对数值决定的。
2 定点数运算
首先观察如下表,尝试填写?处的值。
i
i
i
×
\times
×
w
w
w
+
+
+
b
b
b
=
=
=
a
a
aNOTEbit96109float126.5602$\times
0.4717
0.4717
0.4717+$2.3145=62.0129463real valuescaling_factor
2
1
2^1
21
2
6
2^6
26
2
5
2^5
25
2
4
2^4
24也即小数点位置 KaTeX parse error: Expected 'EOF', got '_' at position 12: 2^\text{bit_̲dot}
quantized253$\times
30
30
30+
74
74
74=
?
?
?
如何计算?
q
u
a
n
t
i
z
e
d
f
l
o
a
t
126.5
???如何计算?quantized float126.5
???如何计算?quantizedfloat126.5\times
?
?
?+
?
?
?=
?
请直接计算此行
a
值
b
i
n
a
r
y
‘
+
11111101
‘
?请直接计算此行a值 binary`+11111101`
?请直接计算此行a值binary‘+11111101‘\times
?
?
?+
?
?
?=
?
?
?
模拟
F
P
G
A
b
i
n
a
r
y
f
l
o
a
t
‘
+
1111110
[
.
]
1
‘
???模拟FPGAbinary float`+1111110[.]1`
???模拟FPGAbinaryfloat‘+1111110[.]1‘\times
?
?
?+
?
?
?=$?a值小数点位置?
注意: 上述quantized、binary是不能直接计算的,为什么?
2.1 定点数乘法
我们先看乘法。
对于上表的quantized一行, 253 × 30 = 7590 253 \times 30 = 7590 253×30=7590;
对于quantized float一行, 126.5 × 0.46875 = 59.296875 126.5 \times 0.46875 = 59.296875 126.5×0.46875=59.296875;
这里 7590 2 1 + 6 = 59.296875 \frac{7590}{2^{1+6}} = 59.296875 21+67590=59.296875
比较原始float计算值59.69844634,可以看出定点乘法结果的差异。
在FPGA里又是如何运算的呢?FPGA里存的都是二进制的数。
那么对于binary一行则有,
+11111101 * +11110 = +1110110100110
这里需要说明的是,FPGA里对与卷积或者全连接的乘法中间结果进行了限制,最高20bit位宽。
其实,+1110110100110
就等于7590,小数点的位置在哪儿呢?在
2
1
+
6
=
2
7
2^{1+6} = 2^7
21+6=27处,即+111011[.]0100110
!
故,对于binary float一行则有,
+1111110[.]1 * +[.][0]11110 = +111011[.]0100110
2.2 定点数加法
有了乘法的中间结果,我们再来看加法。
对于上表quantized一行,7590是不能直接与74相加的,因为不在同一个尺度上,或者说小数点不对齐。
我们先看quantized float,这里的计算和我们实现的caffe quantization操作是一致的。则有 59.296875 + 2.3125 = 61.609375 59.296875 + 2.3125 = 61.609375 59.296875+2.3125=61.609375,但这个结果还未定点化,还需进一步操作: round ( 61.609375 × 2 4 ) 2 4 = 61.625 \frac{\text{round}(61.609375 \times 2^4)} {2^4} = 61.625 24round(61.609375×24)=61.625。
然后切换到binary float来理解(也是FPGA的运算原理),这里小数点需要对齐:
- 1 1 1 0 1 1.0 1 0 0 1 1 0 # i x w
-
-
1 0.0 1 0 1 0 # b
-
= + 1 1 1 1 0 1.1 0 0 1[1 1 0] # round截断
= + 1 1 1 1 0 1.1 0 1 0 # 即986,986/2**4 = 61.625
这里需要说明的是,再FPGA运算中,为了使得
b
b
b能够与
i
×
w
i \times w
i×w选小数点对齐,则需要对
b
b
b进行移位,移位的步数为向左移bit_dot_i + bit_dot_w - bit_dot_b
次。然后对得到的结果进行round截断,使得最终输出值保持指定精度,截断的位宽为bit_dot_i + bit_dot_w - bit_dot_a
。
3 定点数对齐
对于Concat操作,进入的定点数可能是不对齐的,如同做定点数加法时一样,需要将所有定点数对齐,再统一round截断。如
输入1: + 0 0 1 1 0.1 1 0
输入2: - 1 0 0.1 0 1 1 1
对齐后为:
1: + 0 0 1 1 0.1 1 0[0 0] # 输入1向左移了两位
2: - 1 0 0.1 0 1 1 1
为了保持9bit(有符号数),round截断最后两位后输入为:
1: + 0 0 1 1 0.1 1 0
2: -[0 0]1 0 0.1 1 0
4 定点化神经网络浮点模拟模型转为供FPGA使用的定点数权重及移位信息流程
to be continued.