模型压缩

一、算法概述

1.1 svd分解

1.1.1 问题引出:对仿射变换进行降维线性近似

对一个卷积层来说,卷积的输出响应可表示为,其中扩展成 ,扩展成,为输入通道个数,为卷积核大小,为输出通道个数。

在假设输出响应是一个低秩空间下,存在低秩的矩阵,使得,其中为的均值,因此,输出响应可重写为:

其中,。低秩的可分解成两个矩阵的乘积,即,其中,于是可得,

其中,。因此,可使用两个卷积层(卷积核分别为和 )来近似原来的卷积层,该近似的完成还存在两个问题:

  1. 矩阵如何求解?
  2. 如何分解?
  1. 使用优化问题来求解:

该优化问题可用svd求解:
令为减去均值后的N个响应,协方差矩阵(根据协方差矩阵定义推导)。

2.上述矩阵的分解可用svd:,因此

1.1.2 推广: 对加入非线性(relu)层的卷积层进行降维近似

上述输出响应近似推广到非线性输出响应的近似,则优化问题可变为:


解上述优化问题具有挑战性,因此可用通过求解近似优化问题来求解:

这里当时,等价于原优化问题。使用迭代的方法分别优化和

  1. 固定,求解;
    当固定时,最小化目标函数可得,则优化问题变为:

该优化问题与线性时的优化问题相似,但是这里有两个响应集,重写优化问题可得:


此处的响应集均是减均值之后的结果,该问题可用GSVD求解。

  1. 固定,求解; 当固定后,可逐元素的优化:

1.1.3 减小逐层误差累积: 非对称分解思路

为了防止底层近似误差累积都深层,采用非对称方法来解决该问题,优化问题变成:

其中是该层的近似输入,因此是近似输出。解该优化问题如非线性情况。

1.1.4 选择最优的衰减通道数

上述优化问题中是决定近似层复杂度的唯一参数,每一层的冗余不同,因此不同层应合理的选择适当的参数值。

经验上PCA能量与分类准确率有关,定义目标函数:


其中,表示层第大的特征值,是近似之前的复杂度,是期望的近似之后的总复杂度。该优化可用贪心算法求解。

1.2 卷积核分解

1.2.1 scheme2

基于事实:不同的卷积核与通道之间存在冗余。

基于思想:每个卷积层可分解成一系列的两个子空间矩形卷积层,第一个卷积层有个卷积核,第二层有个卷积核。

因此原始的卷积核可近似为:


因此能得到优化问题:

使用共轭梯度法解该优化问题。

1.3 组合使用svd分解与卷积核分解

思路:先使用核分解将卷积层分解成和的卷积核,再使用通道近似的方法,将的卷积核近似成和的卷积核。

二、实现步骤

2.1 脚本说明

  1. compute_d.py 通道数的选择

  2. solve_linear_PWb_space.py 通道线性分解

  3. solve_nonlinear_PWb.py 通道非线性分解

  4. asymmetric.py 通道非对称分解

  5. cgd_sch2.py 核分解

2.2 svd分解步骤

1、导出需要分解层的feature map和权重:

1.1 导出要分解层的feature map存成.h5文件(3000-6000幅图),每幅图feature map 为三维(feature_size, feature_size, output_channel)

    feature map文件:feature_map/conv1_1/imgname.h5

    注意:feature map为三维(feature high,feature width,outputchannel),一般每层feature map取3000-6000幅为宜

1.2 将权重文件转成.pkl文件,以convname_w.pkl和convname_b.pkle命名

    权重文件:Wbs/conv1_1_w.pkl   Wbs/conv1_1_b.pkl

2、通道分解:

2.1 选择每层减少通道数de_ch:
    
    计算每层yyt的值,脚本solve_linear_PWb_space.py中已有相关计算,结果存于solution/solution_linear/conv1_1/accelerating_linear_Mb.pkl
    
    修改相应的卷积层名称layers,和原始复杂度计算Complexity
    
    修改输入文件名:init_dir 为accelerating_linear_Mb.pkl的地址
    
    设置期望近似后的复杂度 Complexity_predict=Complexity_total*0.4 
    
    $ python compute_d.py   打印出每层减少通道后的通道数

2.2 分别修改solve_linear_PWb_space.py、solve_nonlinear_PWb.py、asymmetric.py中每个feature map随机采样点数randsize=4,和输入文件地址:

    indir --- feature_map 地址
    wdir --- conv1_1_w.pkl地址
    bdir --- conv1_1_b.pkl 地址

2.3 线性、非线性和非对称分别执行:

    $ python solve_linear_PWb_space.py --layer=conv1_1 --de_ch=16 --batch_size=6000
    
    $ python solve_nonlinear_PWb.py --layer=conv1_1 --de_ch=16 --batch_size=6000
    
    $ python  asymmetric.py --layer=conv1_1 --de_ch=16 --batch_size=6000
    
    其中,layer为要分解卷积层,de_ch为减少通道数,batch_size为feature map的个数。
    
    注意:非对称分解需要输入上一层近似之后的feature map,因此分解一层都要导出前面都近似之后的feature map,且该feature map要和原始的feature map相对应。

2.4 分解好的权重文件存放在solution目录下:

    线性:solution_linear/conv1_1/accelerating_linear_PWb.pkl

    非线性:solution_nonlinear/conv1_1/accelerating_nonlinear_PWb.pkl
    
    非对称:solution_asy/conv1_1/acceleratin_asy_PWb.pkl

2.5 修改网络,测试精度:

    将分解层网络(3 * 3,outchannel)改成(3 * 3,de_ch)+ (1 * 1,outchannel),并导入相应层分解后的权重,测试精度

2.3 卷积核分解步骤

1 修改cgd_sch2.py中输入文件地址:

wdir =  'Wbs/' + FLAGS.layer + '_w.pkl' 权重文件

bdir =  'Wbs/' + FLAGS.layer + '_b.pkl' bias文件

2 $ Python cgd_sch2.py –layer=conv1_1 –de_ch=16

其中,layer为要分解卷积层,de_ch为减少通道数

3 分解好的权重文件solution/cgd/conv1_1/sch2_HV_cgd_step10.pkl

4 修改网络,测试精度:

将(3 * 3, outchannel)改成(3 * 1, de_ch) + (1 * 3, outchannel),并导入相应层分解后的权重文件,测试精度

三、注意

  1. 由于svd分解是基于对feature map冗余信息的降维近似,当生成feature map所用的数据集与原来训练网络模型时所用的数据集有差别时,分解的精度会受很大影响。但是卷积核分解不存在此问题。

  2. 利用svd的非线性方法进行分解时需要求解GSVD,当feature map的协方差矩阵低秩时可能有复数解,此时应该使用线性求解的方法

  3. 利用cgd求解双凸问题时,初始值的选择可能会影响目标函数的结果。

参考文献

[1] Zhang X, Zou J, He K, et al. Accelerating Very Deep Convolutional Networks for Classification and Detection[J]. IEEE Transactions on Pattern Analysis & Machine Intelligence, 2016, 38(10):1943.

[2] Jaderberg M, Vedaldi A, Zisserman A. Speeding up Convolutional Neural Networks with Low Rank Expansions[J]. Computer Science, 2014, 4(4):XIII.

[3] Takane Y, Hwang H. Regularized linear and kernel redundancy analysis[J]. Computational Statistics & Data Analysis, 2007, 52(1):394-405.

你可能感兴趣的:(模型压缩)