本文介绍一种经典的模型压缩方法Network Slimming,可以实现:

  1. 减小模型大小
  2. 减少运行时的内存占用
  3. 在不影响精度的同时,降低计算操作数

论文中提供的示意图如下,可以看到左侧BN层中橙色的神经元权重较小,因此剪枝之后就去掉了这些层的连接。论文的思路即通过去掉BN层中权重较小的神经元来达到精简网络的目的。


实现去掉权重较小的神经元的流程如下:

1. sparsity regularization

论文提出,在训练的时候增加稀疏正则化方法。

主要作用:令BN层中权值为0的神经元尽可能多,以达到更好的剪枝效果。

实现方式:添加一个新的loss,其大小为BN层中所有神经元的权值和,使用梯度下降法使这个新的loss尽可能小。

# sparsity-induced惩罚项的附加次梯度下降
def updateBN():for m in model.modules():if isinstance(m, nn.BatchNorm2d):m.weight.grad.data.add_(args.s*torch.sign(m.weight.data))  # L1

2. 划分保留层和剪枝层

步骤为:

  1. 给定要保留层的比例,记下所有BN层大于该比例的权重。
  2. 根据比例设置阈值,根据阈值建立一个mask,大于阈值的部分为1,小于阈值的部分为0
  3. 利用mask提取保留的神经元。
# 将这些权重排序
y, i = torch.sort(bn) # 这些权重排序
thre_index = int(total * args.percent) # 要保留的数量
thre = y[thre_index] # 最小的权重值# ===================================预剪枝====================================
pruned = 0
cfg = []
cfg_mask = []
for k, m in enumerate(model.modules()):if isinstance(m, nn.BatchNorm2d):weight_copy = m.weight.data.abs().clone()# 小于权重thre的为0,大于的为1,即保留的部分mask = weight_copy.gt(thre).float().cuda()# 统计被剪枝的权重的总数pruned = pruned + mask.shape[0] - torch.sum(mask)# 权重和偏置分别对应相乘m.weight.data.mul_(mask) m.bias.data.mul_(mask)# 记录每个batchnorm保留的权重和权重数cfg.append(int(torch.sum(mask))) cfg_mask.append(mask.clone())print('layer index: {:d} \t total channel: {:d} \t remaining channel: {:d}'.format(k, mask.shape[0], int(torch.sum(mask))))elif isinstance(m, nn.MaxPool2d):cfg.append('M')

3. 进行BN层的剪枝

进行BN层的剪枝,即丢弃小于阈值的参数;

# ===================================正式剪枝====================================
# 层数
layer_id_in_cfg = 0
start_mask = torch.ones(3)
end_mask = cfg_mask[layer_id_in_cfg]
for [m0, m1] in zip(model.modules(), newmodel.modules()):# 对BN层进行剪枝if isinstance(m0, nn.BatchNorm2d):# 获取大于0的所有数据的索引,使用squeeze变成向量idx1 = np.squeeze(np.argwhere(np.asarray(end_mask.cpu().numpy())))if idx1.size == 1: # 只有一个要变成数组的1个idx1 = np.resize(idx1,(1,))# 用经过剪枝后的层参数的替换原来的# x = (x - mean)/war*weight + datam1.weight.data = m0.weight.data[idx1.tolist()].clone()m1.bias.data = m0.bias.data[idx1.tolist()].clone()m1.running_mean = m0.running_mean[idx1.tolist()].clone()m1.running_var = m0.running_var[idx1.tolist()].clone()# 下一层layer_id_in_cfg += 1# 当前在处理的层的maskstart_mask = end_mask.clone()# 全连接层不做处理if layer_id_in_cfg < len(cfg_mask):end_mask = cfg_mask[layer_id_in_cfg]

4. 进行卷积层剪枝

根据前后BN层的保留层,可以计算得到卷积层保留的卷积核大小(上层BN层输出,下层BN层输入),保留前后BN的对应保留的元素,其余剪枝。

    # 对卷积层进行剪枝elif isinstance(m0, nn.Conv2d):# 上一层BN层对应的输出mask为start_maskidx0 = np.squeeze(np.argwhere(np.asarray(start_mask.cpu().numpy())))# 下一层BN层对应的输入mask为start_maskidx1 = np.squeeze(np.argwhere(np.asarray(end_mask.cpu().numpy())))print('In shape: {:d}, Out shape {:d}.'.format(idx0.size, idx1.size))if idx0.size == 1:idx0 = np.resize(idx0, (1,))if idx1.size == 1:idx1 = np.resize(idx1, (1,))# 剪枝[c_out, c_int, k, k]w1 = m0.weight.data[:, idx0.tolist(), :, :].clone()w1 = w1[idx1.tolist(), :, :, :].clone()m1.weight.data = w1.clone()

5. 对FC层进行剪枝

由于FC层的输出是固定的(分类类数),因此只对FC层的输入维度进行剪枝,也是根据上一层BN层的输出,对应保留的元素,其余剪枝。

    # 对全连接层进行剪枝elif isinstance(m0, nn.Linear):idx0 = np.squeeze(np.argwhere(np.asarray(start_mask.cpu().numpy())))if idx0.size == 1:idx0 = np.resize(idx0, (1,))# 剪枝m1.weight.data = m0.weight.data[:, idx0].clone()m1.bias.data = m0.bias.data.clone()

源代码

剪枝论文一(Network Slimming)相关推荐

  1. Network Slimming——有效的通道剪枝方法(Channel Pruning)

    "Learning Efficient Convolutional Networks through Network Slimming"这篇文章提出了一种有效的结构性剪枝方法,即规 ...

  2. 【剪枝算法】通过网络瘦身学习高效的卷积网络Learning Efficient Convolutional Networks through Network Slimming论文翻译

    此论文翻译仅仅用于自己方便学习.译文来自其他处. 在许多实际应用中部署深度卷积神经网络(CNN)很大程度上受到其计算成本高的限制.在本文中,我们提出了一种新的CNNs学习方案,能同时1)减小模型大小; ...

  3. 模型剪枝经典论文解读:《Learning Efficient Convolutional Networks through Network Slimming》

    Learning Efficient Convolutional Networks through Network Slimming 摘要: CNN在落地中的部署,很大程度上受到其高计算成本的限制.在 ...

  4. 论文复现:Learning Efficient Convolutional Networks through Network Slimming

    论文核心 论文提出了一种结构化剪枝策略,剪枝对象为 channel ,对 channel 重要性的评价标准使用的是 Batch Normalization 层中的缩放因子,这不会给网络带来额外的开销. ...

  5. vision transformer 剪枝论文汇总

    Vision Transformer Pruning 这篇论文的核心思想很简单,就是剪维度,也就是说剪的是这个d. 具体方法就是通过一个gate,如图中的dimension pruning,输出0或者 ...

  6. Network Slimming

    Network Slimming-Learning Efficient Convolutional Networks through Network Slimming](https://arxiv.o ...

  7. 通过Network Slimming学习高效卷积网络

    1.文章信息 本文是2017年发表在计算机视觉领域顶会ICCV的一篇文章,被引量已经达到了1214次,是引用比较广泛的一种模型剪枝方法,作者来自清华大学.英特尔中国实验室.复旦大学和科内尔大学. 2. ...

  8. 微软研究院研究员Ryan Beckett 博士论文《Network Control Plane Synthesis and Verification》下载—2018ACM最佳博士论文题目奖

    欢迎关注微信公众号[计算机视觉联盟] 获取更多前沿AI.CV资讯 论文下载 关注微信公众号[计算机视觉联盟],回复关键词[Ryan]即可下载全文! 论文封面 论文目录 目前,Beckett 是微软研究 ...

  9. 【论文精读1】基于BN的模型剪枝-Learning Efficient Convolution Networks through Network Slimming

    原论文下载地址 论文思想:先结构剪枝后微调.

最新文章

  1. 几十亿打水漂!世界最大移动通信展MWC因疫情33年来首次取消,多方损失惨重...
  2. hybriddb mysql移植_HybridDB for MySQL 实现在线与离线数据分离的实践
  3. 修改mysql导入sql大小限制_修改phpMyAdmin导入SQL文件的大小限制
  4. Zookeeper集群的搭建及遇到的问题
  5. python的md5
  6. Linux操作系统定时任务系统 Cron
  7. linux 命令案例学习——文件搜索
  8. ad中电容用什么封装_【AD封装】VH3.96mm插件座子(带3D)
  9. WinCEService项目
  10. bat文件备份MySQL数据库
  11. 特征图注意力_CV注意力机制论文阅读笔记
  12. 现代浏览器:WebM 格式/网络视频的广泛应用
  13. 电商数据分析常见的指标汇总
  14. 怎么打开和修改dll文件的?如何调用和编辑?
  15. /sdcard目录详解
  16. CF1428F-Fruit Sequences
  17. java 消息摘要_java – 使用BouncyCastle签名消息摘要
  18. linux交换分区的命令,LInux下的交换分区以及相关查看命令
  19. 【宝贝,既然你爱了,那就敞开心扉】
  20. 脑机接口科普0003——Hans Berger

热门文章

  1. 令程序员泪流满面的瞬间,实在忍不住笑了
  2. OID 用于公共设备
  3. SSL vs TLS vs STARTTLS
  4. 拉勾网`Python职位`分析
  5. 数据结构3_160805无头单向不循环
  6. 毕达哥拉斯(勾股定理)
  7. 文档布局分析工具之DIVA
  8. 外贸B2B网站如何做Google SEO获取流量?
  9. 【历史上的今天】4 月 11 日:Apple I 设计完成;微软官宣“告别” Clippy;伯克利计算机先驱出生
  10. opendir() 函数