MIT-TinyML学习笔记【6】DoReFa-Net

本文是在学习TinyML L06时,因为视频没有新版slides中的内容,所以找来DoReFa-Net原文看看,看了很久才大致看懂,看了一些大佬的博客,但是他们没有描述更多细节,所以小白自己记录一下

内容总结写在前面

  • 将BNN中的1-bit bit conv kernel扩展到多bit,计算复杂度为 O ( b i t w i d t h 1 × b i t w i d t h 2 ) O(bitwidth1 \times bitwidth2) O(bitwidth1×bitwidth2)
  • 定义 q u a n t i z e k {quantize_{k}} quantizek 将浮点数输入 r i ∈ [ 0 , 1 ] r_{i} \in [0,1] ri[0,1] 量化到 k-bit输出 r o ∈ [ 0 , 1 ] r_{o}\in [0,1] ro[0,1]
  • 定义权重量化、激活量化、梯度量化
  • 实验表明量化所需要的位宽:梯度 > 激活 > 权重
  • 权重和激活可以使用确定性量化,梯度需要随机量化
  • 第一层和最后一层不量化

1 DoReFa-Net

1.1 比特卷积核

BNN中对于1-bit的点乘定义
x ⋅ y = b i t c o u n t ( a n d ( x , y ) ) , x i , y i ∈ 0 , 1 ∀ i {x}\cdot {y} = bitcount(and({x},{y})), x_{i},y_{i} \in {0,1} \forall i xy=bitcount(and(x,y)),xi,yi0,1i
假设 x {x} x 是 M-bit 定点数序列, x = ∑ m = 0 M − 1 c m ( x ) 2 m {x}=\sum\limits_{m=0}^{M-1} c_{m}({x})2^{m} x=m=0M1cm(x)2m y {y} y 是 K-bit 定点数序列, y = ∑ k = 0 K − 1 c k ( y ) 2 k {y}=\sum\limits_{k=0}^{K-1} c_{k}({y})2^{k} y=k=0K1ck(y)2k 。其中, ( c m ( x ) ) m = 0 M − 1 (c_{m}({x}))_{m=0}^{M-1} (cm(x))m=0M1 ( c k ( y ) ) k = 0 K − 1 (c_{k}({y}))_{k=0}^{K-1} (ck(y))k=0K1为bit vectors,点乘可以表示为:

x ⋅ y = ∑ m = 0 M − 1 ∑ k = 0 K − 1 2 m + k b i t c o u n t [ a n d ( c m ( x ) , c k ( y ) ) ] {x}\cdot {y}=\sum_{m=0}^{M-1}\sum_{k=0}^{K-1}2^{m+k}bitcount[and(c_{m}({x}),c_{k}({y}))] xy=m=0M1k=0K12m+kbitcount[and(cm(x),ck(y))]
c m ( x ) i , c k ( y ) i ∈ { 0 , 1 } , ∀ i , m , k c_{m}({x})_{i},c_{k}({y})_{i}\in \{0,1\}, \forall i,m,k cm(x)i,ck(y)i{0,1},i,m,k
此时计算复杂度为 M ∗ K M*K MK,即计算复杂度和位宽成正比

根据注释的符号解释

个人理解: x = { 10010 , 11011... } {x}=\{10010, 11011...\} x={10010,11011...} (在M=5)时,即 c m ( x ) i c_{m}({x})_{i} cm(x)i 下角标中的每个 i 代表一个M-bit定点数, c m ( ⋅ ) c_{m}(\cdot) cm() 表示一个定点数的第m位, x = ∑ m = 0 M − 1 c m ( x ) 2 m {x}=\sum\limits_{m=0}^{M-1} c_{m}({x})2^{m} x=m=0M1cm(x)2m 表示:例如{10010}时,这个定点数=1x16+1x2=18

1.2 直通估计器STE

使用STE来规避梯度为0的问题
一个简单的例子是在Bernoulli分布采样中定义STE

其中,c为目标函数,由于Bernoulli采样是一个不可微分的过程,因此 ∂ q ∂ p \frac{\partial q}{\partial p} pq 没有定义,因此反向传播不能由链式法则直接求得 ∂ c ∂ p \frac{\partial c}{\partial p} pc

然而由于q和p具有相同的期望,可以使用 ∂ c ∂ p \frac{\partial c}{\partial p} pc ∂ c ∂ q \frac{\partial c}{\partial q} qc 做近似,换句话说STE给出了一个自定义的 ∂ q ∂ p \frac{\partial q}{\partial p} pq,即 ∂ q ∂ p = 1 \frac{\partial q}{\partial p}=1 pq=1

本文定义 q u a n t i z e k {quantize_{k}} quantizek 将浮点数输入 r i ∈ [ 0 , 1 ] r_{i} \in [0,1] ri[0,1] 量化到 k-bit输出 r o ∈ [ 0 , 1 ] r_{o}\in [0,1] ro[0,1] ,其STE如下:

可以看到STE的输出是一个k-bit实数,而 r o r_{o} ro是一个k-bit定点数,两个k-bit实数可以使用第一小节描述的定点数点乘(使用正确的缩放)

把这一段原文放在这里,我的理解是, q u a n t i z e k {quantize_{k}} quantizek STE的输出是实数,而 q u a n t i z e k {quantize_{k}} quantizek的输出 r o r_{o} ro为定点数,可以把STE的输出先按照定义的 q u a n t i z e k {quantize_{k}} quantizek转换成定点数,然后再使用比特卷积dot product

1.3 权重的低比特位宽量化

在之前的工作中,STE被用来二值化权重,例如在BNN中

在XNOR-Net中,权重在二值化后进行了缩放

在XNOR-Net中,缩放因子 E F ( ∣ r i ∣ ) {E}_{F}(|r_{i}|) EF(ri)是对应每个权重的输出通道的绝对值取均值,引入这个scaling factor的可以增加权重值的表达范围,同时仍然能在前向传播卷积时利用比特卷积。

然而在反向传播计算梯度和权重之间的卷积时,channel-wise缩放因子的存在使得无法使用比特卷积核,因此,使用一个常量缩放因子来代替通道级缩放。

当k>1时,使用k-bit表示的权重,将STE应用在权重上:

量化到k-bit之前,使用 t a n h tanh tanh来限制权重值得范围在-1~1之间,通过将量化的数值限制在[0, 1]之间,最大值是对整个层的权重而言的。然后通过 q u a n t i z e k {quantize_{k}} quantizek将其量化到[0, 1]之间的k-bit定点数,最后通过affine transform将结果映射到[-1, 1]之间
考虑对称性

需要注意的是,当k=1时,等式9不同于等式7,它提供了一个不同的二值化权重的方法,然而,论文发现在实验中这种区别不重要。

1.4 激活的低比特位宽量化

在BNN和XNOR-Net中,激活和权重采用相同的方法进行二值化。然而使用XNOR-Net中的方法无法得到很好的结果,且BNN中的二值化方法会在AlexNet这样的模型上损失很多精度。

因此,本文应用STE在输入激活r(each weight layer)。假设前一层的输出传递一个有界的激活函数h,确保 r ∈ [ 0 , 1 ] r\in[0,1] r[0,1],因此在DoReFa-Net中激活的量化简单定义为:

1.5 梯度的低比特位宽量化

在前面几节中描述了确定性量化可以产生低比特位宽的权重和激活,然而发现低位宽梯度必须采用随机量化。

要量化梯度到低比特位宽,需要注意梯度是无界的,并且可能具有比激活值更大的值范围。


其中, d r = ∂ c ∂ r dr=\frac{\partial c}{\partial r} dr=rc 为一些层的输出 r 在反向传播时的梯度(对损失函数c的导数),最大致是对梯度张量的所有维度(除了batch size)的统计,然后在梯度上进行缩放将结果映射到0~1之间,并且在量化之后又缩放回去

为了进一步补偿潜在的由梯度量化所引入的bias,使用一个额外的噪声方程 N ( k ) = σ 2 k − 1 N(k)=\frac{\sigma}{2^{k}-1} N(k)=2k1σ,其中 σ 服从 U n i f o r m ( − 0.5 , 0.5 ) \sigma 服从 Uniform (-0.5,0.5) σ服从Uniform(0.5,0.5) 均匀分布,因此噪声可能具有和量化误差相同的幅值。实验发现人工噪声对达到好的performance至关重要。最终得到量化梯度的表达式

梯度的量化只在反向传播时进行,因此应用STE

2 DoReFa-Net训练算法

(哎呀少标记了一句,在12行的地方,量化梯度为Eq. 12)

以及这里的4 应该就算是后面PCAT拿来改进的地方

3 Source Code

注意这里返回的是three quantization functions

def get_dorefa(bitW, bitA, bitG):
    """
    Return the three quantization functions fw, fa, fg, for weights, activations and gradients respectively
    """
    def quantize(x, k):
        n = float(2 ** k - 1)
        
        @tf.custom_gradient
        def _quantize(x):
            return tf.round(x * n) / n, lambda dy: dy
            
        return _quantize(x)

  
    def fw(x):
        if bitW == 32:
            return x

        if bitW == 1:   # BWN
            E = tf.stop_gradient(tf.reduce_mean(tf.abs(x)))

            @tf.custom_gradient
            def _sign(x):
                return tf.where(tf.equal(x, 0), tf.ones_like(x), tf.sign(x / E)) * E, lambda dy: dy

            return _sign(x)

        x = tf.tanh(x)
        x = x / tf.reduce_max(tf.abs(x)) * 0.5 + 0.5
        return 2 * quantize(x, bitW) - 1

    def fa(x):
        if bitA == 32:
            return x
        return quantize(x, bitA)

  
    def fg(x):
        if bitG == 32:
            return x

        @tf.custom_gradient
        def _identity(input):
            def grad_fg(x):
                rank = x.get_shape().ndims
                assert rank is not None
                maxx = tf.reduce_max(tf.abs(x), list(range(1, rank)), keep_dims=True)
                x = x / maxx
                n = float(2**bitG - 1)
                x = x * 0.5 + 0.5 + tf.random_uniform(
                    tf.shape(x), minval=-0.5 / n, maxval=0.5 / n)
                x = tf.clip_by_value(x, 0.0, 1.0)
                x = quantize(x, bitG) - 0.5

                return x * maxx * 2

            return input, grad_fg

        return _identity(x)

    return fw, fa, fg

在Model类中调用fw,fa 实现了量化权重和激活

        def new_get_variable(v):
            name = v.op.name
            # don't binarize first and last layer
            if not name.endswith('W') or 'conv0' in name or 'fct' in name:
                return v
            else:
                logger.info("Quantizing weight {}".format(v.op.name))
                return fw(v)

        def nonlin(x):
            if BITA == 32:
                return tf.nn.relu(x)    # still use relu for 32bit cases
            return tf.clip_by_value(x, 0.0, 1.0) # h()

        def activate(x):
            return fa(nonlin(x))

构建模型的时候应用了梯度的量化fg

4 参考内容

[低比特量化之DoreFa-Net理论与实践](低比特量化之DoreFa-Net理论与实践 - 知乎 (zhihu.com))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: "Mit-Cheetah-Note"是一种学习辅助工具,旨在提高学生的学习效率和效果。它结合了MIT(麻省理工学院)的学习方法和猎豹速读技术。 首先,MIT-Cheetah-Note采用了麻省理工学院的学习方法。这些方法包括主题导图,问题解决和概念联系等。主题导图是一种可视化的学习工具,帮助学生整理和理解知识点之间的关系。问题解决则鼓励学生通过提出问题来主动思考和深入理解知识。概念联系是通过将新知识与已有知识相结合,加深学生对知识的理解。 其次,这个学习工具还集成了猎豹速读技术。速读是一种训练阅读效率和记忆力的技巧。通过使用猎豹速读技术,学生可以提高阅读速度和理解能力。这对于大量阅读任务的学生来说尤其有用,如备考、论文写作等。 MIT-Cheetah-Note采用了数码笔和智能设备相结合的方式进行学习记录和储存。学生可以使用数码笔在纸上做笔记,并通过智能设备将这些笔记同步到云端。这样一来,学生可以随时随地访问他们的学习记录,从而更好地回顾和复习。 总而言之,MIT-Cheetah-Note是将麻省理工学院的学习方法和猎豹速读技术融入一体的学习辅助工具。它帮助学生提高学习效率和效果,并通过数字化技术方便学生的学习记录和辅助复习。 ### 回答2: Mit-Cheetah-Note 是一种人工智能语音助手,最初由麻省理工学院(MIT)研发。该技术基于深度学习和自然语言处理,在提供智能语音交互的同时,还具备类似于记事本的功能。 Mit-Cheetah-Note 可以用于多个方面,例如记录会议笔记、制定待办事项、管理日程安排等。用户可以通过语音指令来创建笔记,编辑文本内容或者提醒自己日程。Mit-Cheetah-Note 还能理解自然语言,对语音指令做出准确的响应,从而提高用户的工作效率。 与其他语音助手相比,Mit-Cheetah-Note 的特点是其记事本功能。用户可以通过语音输入方式,较快地记录需要记下的信息,而无需手动键入。此外,Mit-Cheetah-Note 还有一个方便的搜索功能,可通过关键词搜索用户之前创建的笔记内容,帮助用户快速找到所需的信息。 Mit-Cheetah-Note 可以应用于多种场景,如商务会议、学术讲座、个人笔记等。它不仅可以减少记笔记的时间和工作量,还可以提高笔记的准确性和完整性。 总之,Mit-Cheetah-Note 是一种集成了语音助手和记事本功能的人工智能技术,使用户能够通过语音指令快速记录信息和管理日程,提高工作效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值