6种卷积神经网络压缩方法
来源 | OSCHINA 社区
作者 | 华为云开发者联盟-嵌入式视觉
原文链接:https://my.oschina.net/u/4526289/blog/7119041
前端压缩,是指在不改变原网络结构的压缩技术,主要包括知识蒸馏、轻量级网络(紧凑的模型结构设计)以及滤波器(filter)层面的剪枝(结构化剪枝)等;
后端压缩,是指包括低秩近似、未加限制的剪枝(非结构化剪枝 / 稀疏)、参数量化以及二值网络等,目标在于尽可能减少模型大小,会对原始网络结构造成极大程度的改造。
一,低秩近似
1.1,总结
二,剪枝与稀疏约束
衡量神经元的重要程度
移除掉一部分不重要的神经元,这步比前 1 步更加简便,灵活性更高
对网络进行微调,剪枝操作不可避免地影响网络的精度,为防止对分类性能造成过大的破坏,需要对剪枝后的模型进行微调。对于大规模行图像数据集(如 ImageNet)而言,微调会占用大量的计算资源,因此对网络微调到什么程度,是需要斟酌的
返回第一步,循环进行下一轮剪枝
2.1,总结
三,参数量化
标量量化(scalar quantization)。
标量量化会在一定程度上降低网络的精度,为避免这个弊端,很多算法考虑结构化的向量方法,其中一种是乘积向量(Product Quantization, PQ),详情咨询查阅论文。
以 PQ 方法为基础,Wu 等人设计了一种通用的网络量化算法:QCNN (quantized CNN),主要思想在于 Wu 等人认为最小化每一层网络输出的重构误差,比最小化量化误差更有效。
3.1,总结
四,二值化网络
def residual_unit(data, num_filter, stride, dim_match, num_bits=1):
"""残差块 Residual Block 定义
"""
bnAct1 = bnn.BatchNorm(data=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 = data
else:
shortcut = bnn.Convolution(data=bnAct1, num_filter=num_filter, kernel=(3, 3), stride=stride, pad=(1, 1))
return conv2 + shortcut
4.1,二值网络的梯度下降
1. 权重 weight 初始化为浮点
2. 前向传播 Forward Pass:
利用决定化方式(sign (x) 函数)把 Weight 量化为 +1/-1, 以 0 为阈值
利用量化后的 Weight (只有 + 1/-1) 来计算前向传播,由二值权重与输入进行卷积运算(实际上只涉及加法),获得卷积层输出。
3. 反向传播 Backward Pass:
把梯度更新到浮点的 Weight 上(根据放松后的符号函数,计算相应梯度值,并根据该梯度的值对单精度的权重进行参数更新)
训练结束:把 Weight 永久性转化为 +1/-1, 以便 inference 使用
4.2,两个问题
直接根据权重的正负进行二值化:xb=sign (x)xb=sign(x)。符号函数 sign (x) 定义如下:
进行随机的二值化,即对每一个权重,以一定概率取 ±1±1
4.3,二值连接算法改进
4.4,二值网络设计注意事项
不要使用 kernel = (1, 1) 的 Convolution (包括 resnet 的 bottleneck):二值网络中的 weight 都为 1bit, 如果再是 1x1 大小, 会极大地降低表达能力
增大 Channel 数目 + 增大 activation bit 数 要协同配合:如果一味增大 channel 数, 最终 feature map 因为 bit 数过低, 还是浪费了模型容量。同理反过来也是。
建议使用 4bit 及以下的 activation bit, 过高带来的精度收益变小, 而会显著提高 inference 计算量
五,知识蒸馏
第一项是由小模型的预测结果与大模型的 “软标签” 所构成的交叉熵(cross entroy);
第二项为预测结果与普通类别标签的交叉熵。
# -*-coding-*- : utf-8
"""
本程序没有给出具体的模型结构代码,主要给出了知识蒸馏 softmax 损失计算部分。
"""
import mxnet as mx
def get_symbol(data, class_labels, resnet_layer_num,Temperature,mimic_weight,num_classes=2):
backbone = StudentBackbone(data) # Backbone 为分类网络 backbone 类
flatten = mx.symbol.Flatten(data=conv1, name="flatten")
fc_class_score_s = mx.symbol.FullyConnected(data=flatten, num_hidden=num_classes, name='fc_class_score')
softmax1 = mx.symbol.SoftmaxOutput(data=fc_class_score_s, label=class_labels, name='softmax_hard')
import symbol_resnet # Teacher model
fc_class_score_t = symbol_resnet.get_symbol(net_depth=resnet_layer_num, num_class=num_classes, data=data)
s_input_for_softmax=fc_class_score_s/Temperature
t_input_for_softmax=fc_class_score_t/Temperature
t_soft_labels=mx.symbol.softmax(t_input_for_softmax, name='teacher_soft_labels')
softmax2 = mx.symbol.SoftmaxOutput(data=s_input_for_softmax, label=t_soft_labels, name='softmax_soft',grad_scale=mimic_weight)
group=mx.symbol.Group([softmax1,softmax2])
group.save('group2-symbol.json')
return group
# 将类别标签进行one-hot编码
one_hot = tf.one_hot(y, n_classes,1.0,0.0) # n_classes为类别总数, n为类别标签
# one_hot = tf.cast(one_hot_int, tf.float32)
teacher_tau = tf.scalar_mul(1.0/args.tau, teacher) # teacher为teacher模型直接输出张量, tau为温度系数T
student_tau = tf.scalar_mul(1.0/args.tau, student) # 将模型直接输出logits张量student处于温度系数T
objective1 = tf.nn.sigmoid_cross_entropy_with_logits(student_tau, one_hot)
objective2 = tf.scalar_mul(0.5, tf.square(student_tau-teacher_tau))
"""
student模型最终的损失函数由两部分组成:
第一项是由小模型的预测结果与大模型的“软标签”所构成的交叉熵(cross entroy);
第二项为预测结果与普通类别标签的交叉熵。
"""
tf_loss = (args.lamda*tf.reduce_sum(objective1) + (1-args.lamda)*tf.reduce_sum(objective2))/batch_size
tf.scalar_mul 函数为对 tf 张量进行固定倍率 scalar 缩放函数。一般 T 的取值在 1 - 20 之间,这里我参考了开源代码,取值为 3。我发现在开源代码中 student 模型的训练,有些是和 teacher 模型一起训练的,有些是 teacher 模型训练好后直接指导 student 模型训练。
六,浅层 / 轻量网络
浅层网络:通过设计一个更浅(层数较少)结构更紧凑的网络来实现对复杂模型效果的逼近,但是浅层网络的表达能力很难与深层网络相匹敌。因此,这种设计方法的局限性在于只能应用解决在较为简单问题上。如分类问题中类别数较少的 task。
轻量网络:使用如 MobilenetV2、ShuffleNetv2 等轻量网络结构作为模型的 backbone 可以大幅减少模型参数数量。
参考资料
神经网络模型压缩和加速之知识蒸馏 https://github.com/chengshengchan/model_compression/blob/master/teacher-student.py https://github.com/dkozlov/awesome-knowledge-distillation XNOR-Net 解析卷积神经网络 - 深度学习实践手册 知识蒸馏(Knowledge Distillation)简述(一)
往期推荐
谷歌多名资深 “开源大佬” 被裁员
大厂裁员轰轰烈烈,哪个技术岗位可以独善其身?
全球开源技术峰会GOTC 2023将于4月在上海举办
这里有最新开源资讯、软件更新、技术干货等内容
点这里 ↓↓↓ 记得 关注✔ 标星⭐ 哦
微信扫码关注该文公众号作者