A-卷积网络压缩方法总结( 二 )

。剪枝操作对网络结构的破坏程度极小,将剪枝与其他后端压缩技术相结合,能够达到网络模型最大程度压缩,目前工业界有使用剪枝方法进行模型压缩的案例 。
三 , 参数量化相比于剪枝操作,参数量化则是一种常用的后端压缩技术 。所谓“量化”,是指从权重中归纳出若干“代表”,由这些“代表”来表示某一类权重的具体数值 。“代表”被存储在码本(codebook)之中,而原权重矩阵只需记录各自“代表”的索引即可,从而极大地降低了存储开销 。这种思想可类比于经典的词包模型(bag-of-words model) 。常用量化算法如下:

  1. 标量量化(scalar quantization) 。
  2. 标量量化会在一定程度上降低网络的精度,为避免这个弊端,很多算法考虑结构化的向量方法,其中一种是乘积向量(Product Quantization, PQ) , 详情咨询查阅论文 。
  3. 以PQ方法为基?。?Wu等人设计了一种通用的网络量化算法:QCNN(quantized CNN),主要思想在于Wu等人认为最小化每一层网络输出的重构误差,比最小化量化误差更有效 。
标量量化算法基本思路是,对于每一个权重矩阵 \(W\in \mathbb{R}^{m\times n}\) , 首先将其转化为向量形式:\(w\in \mathbb{R}^{1\times mn}\) 。之后对该权重向量的元素进行 \(k\) 个簇的聚类,这可借助于经典的 k-均值(k-means)聚类算法快速完成:
\[\underset{c}{arg min}\sum_{i}^{mn}\sum_{j}^{k}\begin{Vmatrix}?w_{i}-c_{j}\end{Vmatrix}_{2}^{2}\]这样,只需将 \(k\) 个聚类中心(\(c_{j}\),标量)存储在码本中,而原权重矩阵则只负责记录各自聚类中心在码本中索引 。如果不考虑码本的存储开销,该算法能将存储空间减少为原来的 \(log_{2}(k)/32\) 。基于 \(k\) 均值算法的标量量化在很多应用中非常有效 。参数量化与码本微调过程图如下:
【A-卷积网络压缩方法总结】
A-卷积网络压缩方法总结

文章插图
这三类基于聚类的参数量化算法,其本质思想在于将多个权重映射到同一个数值 , 从而实现权重共享 , 降低存储开销的目的 。
3.1 , 总结参数量化是一种常用的后端压缩技术 , 能够以很小的性能损失实现模型体积的大幅下降 , 不足之处在于,量化的网络是“固定”的 , 很难对其做任何改变,同时这种方法通用性差,需要配套专门的深度学习库来运行网络 。
这里,权重参数从浮点转定点、二值化等方法都是是试图避免浮点计算耗时而引入的方法,这些方法能加快运算速率,同时减少内存和存储空间的占用,并保证模型的精度损失在可接受的范围内,因此这些方法的应用是有其现实价值的 。更多参数量化知识 , 请参考此 github仓库 。
四 , 二值化网络
  1. 二值化网络可以视为量化方法的一种极端情况:所有的权重参数取值只能为 \(\pm 1\)  , 也就是使用 1bit来存储WeightFeature 。在普通神经网络中,一个参数是由单精度浮点数来表示的,参数的二值化能将存储开销降低为原来的 1/32
  2. 二值化神经网络以其高的模型压缩率和在前传中计算速度上的优势,近几年格外受到重视和发展,成为神经网络模型研究中的非常热门的一个研究方向 。但是,第一篇真正意义上将神经网络中的权重值和激活函数值同时做到二值化的是 Courbariaux 等人 2016 年发表的名为《Binarynet: Training deep neural networks with weights and activations constrained to +1 or -1》的一篇论文 。这篇论文第一次给出了关于如何对网络进行二值化和如何训练二值化神经网络的方法 。
  3. CNN 网络一个典型的模块是由卷积(Conv)->批标准化(BNorm)->激活(Activ)->池化(Pool)这样的顺序操作组成的 。对于异或神经网络,设计出的模块是由批标准化(BNorm)->二值化激活(BinActiv)->二值化卷积(BinConv)->池化(Pool)的顺序操作完成 。这样做的原因是批标准化以后,保证了输入均值为 0,然后进行二值化激活,保证了数据为 -1 或者 +1,然后进行二值化卷积,这样能最大程度上减少特征信息的损失 。二值化残差网络结构定义实例代码如下:
def residual_unit(data, num_filter, stride, dim_match, num_bits=1):"""残差块 Residual Block 定义"""bnAct1 = bnn.BatchNorm(data=https://www.huyubaike.com/biancheng/data, num_bits=num_bits)conv1 = bnn.Convolution(data=bnAct1, num_filter=num_filter, kernel=(3, 3), stride=stride, pad=(1, 1))convBn1 = bnn.BatchNorm(data=conv1, num_bits=num_bits)conv2 = bnn.Convolution(data=convBn1, num_filter=num_filter, kernel=(3, 3), stride=(1, 1), pad=(1, 1))if dim_match:shortcut = dataelse:shortcut = bnn.Convolution(data=bnAct1, num_filter=num_filter, kernel=(3, 3), stride=stride, pad=(1, 1))return conv2 + shortcut

推荐阅读