DeepCompression思考

版权声明:本文为博主原创文章,转载请标注出处。 https://blog.csdn.net/Yan_Joy/article/details/79038101

网上很少有Deepcompress的实现源码,前一段时间使用TensorFlow实现了一下,还是有些问题值得注意。

TensorFlow的局限性


TensorFlow支持的是一种静态图,当模型的参数确定之后,便无法继续修改。这对于逐阶段、分层的训练带来了一定的困难。具体在本项目中,权重的固定无法在单次模型训练中进行逐层的设置,只能采取一种比较麻烦的方法:量化完某一层后,先保存全局模型权重,然后清空TensorFlow的graph,重新建立新模型,并把对应量化层设置为不更新权重,最后加载模型权重,继续进行训练。
相比之下,pytorch使用了动态图,在定义完模型之后还可以边训练边修改其参数,具有很高的灵活性。这也是深度学习未来的发展方向。目前的开发者版本nightly中,TensorFlow也开始支持动态图的定义,但还未普及。

聚类算法的低效性


聚类算法是量化的前提,sklearn中提供了诸如K-Means,Mean-shift,Gaussian mixtures等可用的方法。其中K-Means是一种简单有效而较为快速的方法了。其算法计算是选择k个初始中心点,例如c[0]=data[0],…c[k-1]=data[k-1];对于data[0]….data[n], 分别与c[0]…c[k-1]比较,假定与c[i]差值最少,就标记为i;可以看到,在计算距离上,需要n*k次的距离计算,同时进行k个数据量,n次的排序。在个人电脑上,由于训练网络参数规模较小,因而无法体现出其运算时间。在对VGG这样大型的网络测试时,发现对于256个聚类中心,在fc的4096*4096维度的全连接层进行聚类时,耗时超过20分钟(没有运行完便停止了),严重影响了算法的实用性。目前的解决办法是抽样采样,如对1%的参数进行聚类作为整体参数的聚类中心。这样操作后聚类时间能缩短到5分钟以内。
有没有一个更加简便的方法呢?对于训练好的一个模型,特别是经过l2正则化的,其参数分布基本上可以看作是一个高斯分布模型,对其进行拟合即可得到分布参数。这样问题就转化为:对一个特定的高斯分布模型,是否能够根据其参数直接得到聚类中心?如果可以,那这个聚类过程将会大大缩短时间:首先对权重进行直方图划分,得到不同区间的参数分布图,再由此拟合高斯函数,最后用这个函数获得聚类中心。这个工作需要一定的数学方法,这里只是简单猜想一下。

重训练带来的时间成本


我们日常说道的数据压缩,是根据信源的分布、概率进行的,特别是通过构建字典,来大大减少信息冗余。这套方法直接使用在模型上,效果往往不好。一个最重要的原因就是参数虽然有着美妙的分布,但几乎没有两个相同的参数。在对Alexnet进行gzip压缩后,仅仅从233MB下降到216MB,远不如文本以及图像压缩算法的压缩率。因此传统方法难以解决深度学习的问题。
剪枝量化虽好,但其问题也是传统压缩所没有的,那就是重训练所带来的时间成本。这个过程就是人为为参数增加条件,让网络重新学习降低loss的过程,因此也无法再重新恢复成原始的网络,因为参数不重要,重要的是结果。这个过程和训练一样,是痛苦而漫长的。又因为是逐层训练,一个网络的训练时间和层数密切相关。Mnist这种简单任务,512*512的权重量化重训练,由最开始的8s增加到36s,增加了约4倍时间。如果在GPU服务器上,Alex的时间成本可能还是勉强接受的,要是有GoogleNet,ResNet这种,真的是要训到天荒地老了。不过也不排除另一个更大的原因,就是自己的代码缺乏优化。实现过程中,有很多操作无法直接实现,或者没有找到简便的方法,不得不绕了个弯子,确实会严重降低性能。

总结


Deepcompression的效果有目共睹,但其实现过程却比较复杂也耗费大量时间。当然作为服务提供商,需要大规模部署,有足够的算力,是可以完成这样大的工作量的。不过模型压缩仅仅是第一步,更深层次的问题在于运算速度。量化是一个很好的方向,但靠聚类带来的量化中心往往难以计算,这时需要人为设计一些计算有利的量化方法,如二值网络。相信随着未来移动端需求的增长,网络压缩、加速工作会更加重要。

阅读更多
换一批

没有更多推荐了,返回首页