赞
踩
讲道理 它这个摘要写得好霸气。。太猛了
这个方法它可以同时做到以下三件事:
1. 减小模型大小
2. 减小运行时的内存占用
3. 在牺牲一点点精度的情况下大幅减少计算
能做到以上这些事情的其他方法也有,但是其他方法或需要特殊的硬件,或需要额外的训练开销,但是这个方法都没有!
那么它是怎么做到呢?简单来说,就是拿一个大型网络(如resent105),往里面搞点东西,然后拿去训练,在训练的过程中自动的把那些额外的channel删掉,进而得到一个比较精简的模型。
效果也是很不错的:模型大小是原来的1/20,操作数是原来的1/5。
1. 现有方法并不能解决所有问题(就是摘要里说的1. 减小模型大小;2. 减小运行时的内存占用;3. 在牺牲一点点精度的情况下大幅减少计算);
2. 现有的很多方法需要额外的软/硬件加持,比如针对权重剪枝的压缩方法显然不适用于常见的加速矩阵运算的GPU。
文章先抛出一些比较常见的压缩方法:
这个方法之前想过,就是利用SVD来对权重矩阵进行降维,进而达到压缩模型的作用。
这个方法的优点很明显,那就是够简单(毕竟连我都想得到。。。。),缺点就是只能针对全链接起作用(因为全链接才可以把权重写成矩阵的形式),而在处理CV的大型网络中,最占存储和最耗费计算资源的其实是CNN,所以整体效果并不明显。
这个应该怎么翻译呢。。。权重分桶?可能吧.. 其实这个方法也挺有趣的,就是把各个权重进行聚类,然后使用聚类中心代替当前权重。然后再用一个表来存储一个字节数较小的数和聚类中心之间的映射关系,然后再用这些字节数较小的数放到权重中。(讲得有点绕,但是很简单就对了)
优点:很明显,在存储的时候压缩效果特别好。试想,从double变成int8, 减少了这么多倍。
缺点:也很明显,就是:
1. 并不能减少推理时候的内存消耗和时间加速,因为你需要把你映射出来的float32/float64放到内存中,需要该用多少还是用多少;
2.准确率损失绝对大。试想,如果使用uint8来存储,那就只能有256个聚类中心,但是一个channel的大小可能是512*512,那平均每个聚类中心就有1024个数值了,这个准确率绝对会受到很大的影响。但是如果你使用int16或者int32来存储的话,那精度的确会上升,但是这个时候,你的压缩效果就绝对没那么高了。
这个是权重剪枝,就是把一些不重要的权重置0/删除。
优点:我觉得没有优点。。。
缺点:做权重剪枝有两个办法,一个是把不重要的权重置0,一个是把不重要的权重删掉。如果你把不重要的权重置0,看起来好像是ok的,但是你0也是个数值,所以不管是在外存还是内存中,该占用的内存还是占用了。而对于第二个处理方式(把不重要的权重删掉),首先不说主流的框架不支持,主要是主流的硬件也不支持。因为深度学习采用GPU的原因正是因为GPU使用矩阵运行来加速我们的训练,而把不重要的参数删掉之后,那这个矩阵就出现了空洞,这时候就没办法用矩阵运算了。
基于结构的剪枝。paper中说道,我们的方法也是属于这个范畴,但是他说其他的一些结构化剪枝没有咱们文中这个丝滑(我还没看他对比的那几篇paper,姑且就相信他吧)。
优点:这种基于结构化的剪枝不需要软/硬件加速,因为没有破坏矩阵运算的结构,但是我觉得本质原因是结构化剪枝是得到一个小规模的正常的网络,所以它和其他网络并没有区别。
缺点:作者说说这篇paper提出的方法更加丝滑。
这个我不懂了,没接触过,不过按照paper中的描述,应该有点像AutoML。
用简单的一句话概括就是:将L1正则化从权重扩展到channel。
其实这个也解决了我之前的一个问题:我之前用L1来normalize网络中的权重,然后将权重删掉虽然可行,但是就陷入了前面所说的,基于权重剪枝的问题。那我如何把L1的作用水平从weight到更高呢?
在这里,他就把损失函数定义成, 其中g(*)就是平滑L1正则。那么虽然L逐渐被优化,绝大多数的都变成了0,这时候我们再看另外一个公式:当绝大多数变成0的时候,很多的channel也变成了0,那就可以把他们删除掉了。
一开始我是有点疑惑,为什么为0的channel正好就会是不重要的,然后我发现了是和有关的,那就懂了,这就变成了一个优化问题了。
然后这篇paper中有提到一个trick也是不错的:就是使用smooth L1正则化来代替L1正则化。
这篇也给了一些启示,或许从L2出发思考也会有其他的不错的方案。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。