【模型压缩】(三)——量化

一、概述

量化:

  • 剪枝是删除不重要的权重参数,量化则是减少存储权重的bit,将权重存储在更小的空间中;
  • 权重不需要以高精度方式存储,甚至不应该以高精度方式存储;
  • 如果用简单的量化方式效果并不好,需要一些训练量化参数的计较;

方法:

1、二值化

这是最简单的一种量化方式,就是用0-1两个值代替原来的参数值,往往能达到32倍的压缩程度;该方法能够大大提升模型的训练和推理速度,但性能明显下降;也可以采用一种二值化变体,就是用两个常量(C1和C2)来替代0-1两个值,阈值也可以修改;

缺点:损失精度过多,并且在RNN和LSTM等复杂模型上表现不佳,加剧了梯度消失、爆炸的影响,一般不适用该方式;

2、三元量化

三元量化则是分段为三个,也就是分为两个阈值,也可以根据伯努利分布和参数矩阵以一定的概率分配状态,引入了随机性后鲁棒性较好,可以说是基于概率的三元量化;

3、训练量化

思想是使用K-means聚类对权重进行聚类,其中聚类的数量根据所需的bit决定;为每一个权重创建一个code book,用其进行前向传播,梯度计算并更新每个集群的聚类中心;

二、流程

第一步:对训练过的权值进行聚类,并且用所属的聚类中心替换它们的值;

q4U3ND.md.png

可以看出,对于16个数值,聚类成了4个数值;

第二步:用新权重向前传递计算梯度,最终对聚类中心进行梯度下降的参数更新;

qImK7n.md.png

可以看出,梯度也通过聚类的方式进行更新;

结论:对于参数的保存来说,现在只需要存储集群索引和聚类中心的值就可以了,当然仅仅用这种聚类的方法压缩的程度还不够,结合之后讲解的Huffman编码,可以有效地表示权值,最终模型可以实现大幅度地压缩,并且仅损失较小的精度;

三、优缺点

优点:

  • 量化也可以在训练间和训练后应用;

  • 可以应用于各种类型的神经网络结构;

缺点:

  • 量化的权值使得神经网络更难收敛,为了保证性能,需要较小的学习率;
  • 量化的权值使得反向传播不可行,因为梯度不能通过离散神经元反向传播;需要用近似的方法来估计损失函数相对于离散神经元的梯度;

四、代码案例

import torch
import numpy as np
from sklearn.cluster import KMeans
from scipy.sparse import csc_matrix, csr_matrix


def apply_weight_sharing(model, bits=5):
    """
    Applies weight sharing to the given model
    """
    # 遍历每一层
    for module in model.children():
        dev = module.weight.device
        # 从cuda中将weight取出来
        weight = module.weight.data.cpu().numpy()
        shape = weight.shape
        # 构建稀疏矩阵
        mat = csr_matrix(weight) if shape[0] < shape[1] else csc_matrix(weight)
        min_ = min(mat.data)
        max_ = max(mat.data)
        # 通过传进来的参数bits,计算聚类中心个数
        space = np.linspace(min_, max_, num=2**bits)
        # 这里定义了一个Kmeans训练器
        kmeans = KMeans(n_clusters=len(space), init=space.reshape(-1,1), n_init=1, precompute_distances=True, algorithm="full")
        kmeans.fit(mat.data.reshape(-1,1))
        new_weight = kmeans.cluster_centers_[kmeans.labels_].reshape(-1)
        mat.data = new_weight
        # from_numpy的作用就是将numpy转换为tensor
        module.weight.data = torch.from_numpy(mat.toarray()).to(dev)

上述代码表示用聚类的方法,通过聚类中心代表聚类的每个数的值,大大减小了计算量;

五、Huffman Encoding(霍夫曼编码)

简介:

量化是对权值的离散化,霍夫曼编码是一种无损的数据压缩方式,根据离散值的出现情况频率存储值,字符的频率越高的在位上存储越少;

利用稀疏矩阵索引大大降低了存储需求,根据实验数据,Huffman编码在保持性能不变的前提下,将模型减少了8倍至18倍;

总结:

霍夫曼编码可以理解成一种数据结构,通过将浮点数转换为二进制文件,达到减少存储量的作用;并且分为编码和解码,类似于深度学习中的特征下采样和上采样,本质上也是减少计算量;

六、总结

Tensorflow官网也提供了模型压缩的参考文档:官方网站
下图为一个量化的总结图:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_40620310/article/details/124004676