【PTQ】Cross-Layer Equalization跨层均衡-证明和实践详细解读

news2024/12/23 12:22:45

Cross-Layer Equalization跨层均衡

aimet解读

符合规则的模型结构

  • 统一要求:单数据流,中间激活不流向其他地方
  • 概念说明:
    • Conv: gruoups=1的普通卷积,包括TransposedConv和Conv
    • DepthwiseConv: 深度可分离卷积,groups=in_channels, in_channels=out_channels。
  • cle均衡块:(相邻块的连接中间可能穿插Relu或者是Relu6等正缩放线性运算的算子)
    • Conv ==> Conv
    • Conv ==> DepthwiseConv ==> Conv
    • DepthwiseConv ==> Conv

优化目标

  • 前提说明:

    • 正缩放线性运算函数特性: f ( s x ) = s f ( x ) \begin{align} f(sx)=sf(x) \end{align} f(sx)=sf(x),relu/relu6等算子符合该特性
    • 我们优化的函数总是以cle均衡块:Conv ==> Conv作为基础的情况,使用函数可表达为如下的函数
      h = f ( W ( 1 ) x + b ( 1 ) ) y = f ( W ( 2 ) h + b ( 2 ) ) y = f ( W ( 2 ) f ( W ( 1 ) x + b ( 1 ) ) + b ( 2 ) ) \begin{align} h=&f(W^{(1)}x+b^{(1)}) \\ y=&f(W^{(2)}h+b^{(2)}) \\ y=&f(W^{(2)}f(W^{(1)}x+b^{(1)})+b^{(2)}) \end{align} h=y=y=f(W(1)x+b(1))f(W(2)h+b(2))f(W(2)f(W(1)x+b(1))+b(2))
    • 提出的优化目标和思路:
      • 出发点:cle的目的就是想要在模型推理结果不变的情况下,通过调整相连conv层的weight的每通道的权重,使得同一个weight的数值范围能够基本保持一致,这样能够让后续的per-layer量化效果能够和per-channel量化效果相当。
      • 思路:使用对角矩阵调整conv的每channel权重,使得该conv的每channel权重的数值范围range能够大致相同。而如何保证调整conv层权重后的模型推理运算结果不变,利用了正缩放线性运算函数特性。
    • 具体的权重调整公式如下所示:
      S = d i a g ( s i ) h = S f ( S − 1 W ( 1 ) x + S − 1 b ( 1 ) ) y = f ( W ( 2 ) S f ( S − 1 W ( 1 ) x + S − 1 b ( 1 ) ) + b ( 2 ) ) = f ( W ~ ( 2 ) f ( W ~ ( 1 ) x + b ~ ( 1 ) ) + b ( 2 ) ) \begin{align} S=&diag(s_{i}) \\ h=&Sf(S^{-1}W^{(1)}x+S^{-1}b^{(1)}) \\ y=&f(W^{(2)}Sf(S^{-1}W^{(1)}x+S^{-1}b^{(1)})+b^{(2)}) \\ =&f(\tilde{W}^{(2)}f(\tilde{W}^{(1)}x+\tilde{b}^{(1)})+b^{(2)}) \end{align} S=h=y==diag(si)Sf(S1W(1)x+S1b(1))f(W(2)Sf(S1W(1)x+S1b(1))+b(2))f(W~(2)f(W~(1)x+b~(1))+b(2))
    • 上述的推演公式可知如下的调整后的新的权重:
      • (9)公式:对应pre-layer(也就是第一个conv)的权重的调整,即对每output_channel上进行了对应的调整
      • (10)公式:对应cur-layer(也就是第二个conv)的权重的调整,即对每input_channel上进行了对应的调整
        W ~ ( 1 ) = S − 1 W ( 1 ) W ~ ( 2 ) = W ( 2 ) S b ~ ( 1 ) = S − 1 b ( 1 ) \begin{align} \tilde{W}^{(1)}=&S^{-1}W^{(1)} \\ \tilde{W}^{(2)}=&W^{(2)}S \\ \tilde{b}^{(1)}=&S^{-1}b^{(1)} \end{align} W~(1)=W~(2)=b~(1)=S1W(1)W(2)SS1b(1)
    • 具体的优化目标:
      • 理想情况下,对于同一个权重而言,希望每channel权重的range同整个权重的range相等。

      • 因此提出如下的优化目标:

        • r ~ i ( 1 ) \tilde{r}^{(1)}_{i} r~i(1):表示每channel通道权重的数值范围(都是按照对称量化进行衡量的
        • R ~ ( 1 ) \tilde{R}^{(1)} R~(1):表示每整个权重的数值范围
        • (13)公式:最终的优化目标,获得一个 S S S能够数值最大

        p ~ i ( 1 ) = r ~ i ( 1 ) R ~ ( 1 ) max ⁡ S ∑ i p ~ i ( 1 ) p ~ i ( 2 ) \begin{align} \tilde{p}^{(1)}_{i}=\frac{\tilde{r}^{(1)}_{i}}{\tilde{R}^{(1)}} \\ \mathop{\max}\limits_{S} \sum\limits_{i} \tilde{p}^{(1)}_{i} \tilde{p}^{(2)}_{i} \end{align} p~i(1)=R~(1)r~i(1)Smaxip~i(1)p~i(2)

  • 解优化目标:

    • 推导优化目标(基于(13)公式进行推导)
      r ~ ( 1 ) = S − 1 r ( 1 ) r ~ ( 2 ) = r ( 2 ) S R ~ ( k ) = max ⁡ i ( r ~ i ( k ) ) max ⁡ S ∑ i p ~ i ( 1 ) p ~ i ( 2 ) = max ⁡ S ∑ i r ~ i ( 1 ) r ~ i ( 2 ) R ~ ( 1 ) R ~ ( 2 ) = max ⁡ S ∑ i 1 s i r i ( 1 ) s i r i ( 2 ) max ⁡ j ( 1 s j r j ( 1 ) ) max ⁡ k ( s k r k ( 2 ) ) = ∑ i r i ( 1 ) r i ( 2 ) max ⁡ S 1 max ⁡ j ( 1 s j r j ( 1 ) ) max ⁡ k ( s k r k ( 2 ) ) \begin{align} \tilde{r}^{(1)}=&S^{-1}r^{(1)} \\ \tilde{r}^{(2)}=&r^{(2)}S \\ \tilde{R}^{(k)}=&\mathop{\max}_{i}(\tilde{r}^{(k)}_{i}) \\ \mathop{\max}\limits_{S} \sum\limits_{i} \tilde{p}^{(1)}_{i} \tilde{p}^{(2)}_{i} = &\mathop{\max}\limits_{S} \sum\limits_{i} \frac{\tilde{r}^{(1)}_{i}\tilde{r}^{(2)}_{i}}{\tilde{R}^{(1)}\tilde{R}^{(2)}} \\ =&\mathop{\max}\limits_{S} \sum\limits_{i} \frac{\frac{1}{s_{i}}r^{(1)}_{i} s_{i} r^{(2)}_{i}}{\mathop{\max}_{j}(\frac{1}{s_{j}}r^{(1)}_{j}) \mathop{\max}_{k}(s_{k} r^{(2)}_{k})} \\ =& \sum\limits_{i} r^{(1)}_{i} r^{(2)}_{i} \mathop{\max}\limits_{S} \frac{1}{\mathop{\max}_{j}(\frac{1}{s_{j}}r^{(1)}_{j}) \mathop{\max}_{k}(s_{k} r^{(2)}_{k})} \end{align} r~(1)=r~(2)=R~(k)=Smaxip~i(1)p~i(2)===S1r(1)r(2)Smaxi(r~i(k))SmaxiR~(1)R~(2)r~i(1)r~i(2)Smaximaxj(sj1rj(1))maxk(skrk(2))si1ri(1)siri(2)iri(1)ri(2)Smaxmaxj(sj1rj(1))maxk(skrk(2))1

    • 优化目标简化(基于(19)公式)

      • 这是一个最优化的问题,本来的优化目标从优化最大值变成了优化最小值的问题

      arg ⁡ max ⁡ S ∑ i p ~ i ( 1 ) p ~ i ( 2 ) = arg ⁡ min ⁡ S [ max ⁡ j ( 1 s j r j ( 1 ) ) max ⁡ k ( s k r k ( 2 ) ) ] \begin{align} \mathop{\arg\max}\limits_{S} \sum\limits_{i} \tilde{p}^{(1)}_{i} \tilde{p}^{(2)}_{i}=&\mathop{\arg\min}\limits_{S} [\mathop{\max}_{j}(\frac{1}{s_{j}}r^{(1)}_{j}) \mathop{\max}_{k}(s_{k} r^{(2)}_{k})] \end{align} Sargmaxip~i(1)p~i(2)=Sargmin[maxj(sj1rj(1))maxk(skrk(2))]

    • 利用反证法,对于优化目标,可以推出如下的结论(26):

      • 对于整个权重的range数值范围,我们有如下的假设,即pre-layer的权重的第 J J J个channel有着最大的操作

      J = arg ⁡ max ⁡ j ( 1 s j r j ( 1 ) ) K = arg ⁡ max ⁡ k ( s k r k ( 2 ) ) \begin{align} J=&\mathop{\arg\max}\limits_{j}(\frac{1}{s_{j}}r^{(1)}_{j}) \\ K=&\mathop{\arg\max}\limits_{k}(s_{k} r^{(2)}_{k}) \end{align} J=K=jargmax(sj1rj(1))kargmax(skrk(2))

      • 反证法证明过程:如果 J ≠ K J \neq K J=K,那么总是存在一个 ε > 0 \varepsilon > 0 ε>0,使得满足如下不等式。最为矛盾的是(25)行的不等式的含义,这个表明,还有更好的 s ~ K \tilde{s}_{K} s~K能够让(20)的优化目标更优的解。因此对于我们的优化目标来说,必然存在 J = K J = K J=K

      s ~ K = s K − ε 1 s J r J ( 1 ) > 1 s ~ K r K ( 1 ) > 1 s K r K ( 1 ) 1 s J r J ( 1 ) s K r K ( 2 ) > 1 s J r J ( 1 ) s ~ K r K ( 2 ) \begin{align} \tilde{s}_{K} =& s_{K} - \varepsilon \\ \frac{1}{s_{J}}r^{(1)}_{J} >& \frac{1}{\tilde{s}_{K}}r^{(1)}_{K} > \frac{1}{s_{K}}r^{(1)}_{K} \\ \frac{1}{s_{J}}r^{(1)}_{J} s_{K} r^{(2)}_{K} >& \frac{1}{s_{J}}r^{(1)}_{J} \tilde{s}_{K} r^{(2)}_{K} \end{align} s~K=sJ1rJ(1)>sJ1rJ(1)sKrK(2)>sKεs~K1rK(1)>sK1rK(1)sJ1rJ(1)s~KrK(2)

      arg ⁡ max ⁡ j ( 1 s j r j ( 1 ) ) = arg ⁡ max ⁡ k ( s k r k ( 2 ) ) \begin{align} \mathop{\arg\max}\limits_{j}(\frac{1}{s_{j}}r^{(1)}_{j})=&\mathop{\arg\max}\limits_{k}(s_{k} r^{(2)}_{k}) \end{align} jargmax(sj1rj(1))=kargmax(skrk(2))

    • 利用(26)的结论,如果我们再进一步简化优化目标,最后会发现优化目标变成一个跟 S S S无关的解,而是依赖于 i = arg ⁡ max ⁡ i ( r i ( 1 ) r i ( 2 ) ) i=\mathop{\arg\max}\limits_{i}(r^{(1)}_{i} r^{(2)}_{i}) i=iargmax(ri(1)ri(2))。因此这里为了能够解得所有的 S S S,这里增加了如下所示的条件限制:
      ∀ i : r ~ i ( 1 ) = r ~ i ( 2 ) \begin{align} {\forall}_i : \tilde{r}^{(1)}_{i}=\tilde{r}^{(2)}_{i} \end{align} i:r~i(1)=r~i(2)

    • 因此结合(26)和(27),我们可以得到满足条件的解如下:
      s i = 1 r i ( 2 ) r i ( 1 ) r i ( 2 ) \begin{align} s_{i} =& \frac{1}{r^{(2)}_{i}} \sqrt{r^{(1)}_{i} r^{(2)}_{i}} \end{align} si=ri(2)1ri(1)ri(2)

限制和缺陷

从上述的优化过程中,我们可以看出,CLE存在一些缺陷和使用限制

  • 优化推导过程中使用的是对称量化,因此cle后只适合对称量化权重的PTQ方式
  • 因为pre-layer的bias改变的问题,改变了pre-layer的输出数值的范围,有可能出现每通道数值范围差别大,可能会导致后量化效果差。
  • 对于pre-layer来说,是按照output_channel的方向进行权重微调,这个是符合per-channel的;但是对于cur-layer来说,是按照input_channel的方向进行权重微调,在含义上不符合per-channel的方式。

实操和结果显示

cle的实现函数
import numpy as np

def my_cle(pre_layer_weight, pre_layer_bias, cur_layer_weight):
    # 自建的cle函数,用于计算和
    channel_num = list(pre_layer_weight.shape)[0]
    r1 = np.array([np.abs(pre_layer_weight[i]).max() for i in range(channel_num)]).tolist()
    r2 = np.array([np.abs(cur_layer_weight[i]).max() for i in range(channel_num)]).tolist()
    scale = list()
    for a,b in zip(r1, r2):
        mul_v = a * b
        if mul_v == 0.0:
            scale.append(1.0)
        else:
            scale.append(math.sqrt(a/b))
    
    scale = np.array(scale, dtype=np.float32)
    pre_layer_weight_res = [pre_layer_weight[i]/s for i, s in enumerate(scale)]
    cur_layer_weight_res = [cur_layer_weight[i]*s for i, s in enumerate(scale)]
    pre_layer_bias_res   = [pre_layer_bias[i]/s for i, s in enumerate(scale)]
    pre_layer_weight_res = np.array(pre_layer_weight_res)
    cur_layer_weight_res = np.array(cur_layer_weight_res)
    pre_layer_bias_res = np.array(pre_layer_bias_res)
    return scale, pre_layer_weight_res, pre_layer_bias_res, cur_layer_weight_res
模型定义
import torch
class onnx2torch_cle(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.conv = torch.nn.Conv2d(in_channels=3, out_channels=16, kernel_size=5,
                                    stride=1, padding=2)
        self.relu1 = torch.nn.ReLU()
        self.conv2 = torch.nn.Conv2d(in_channels=16, out_channels=4, kernel_size=5,
                                    stride=1, padding=2)
    
    def forward(self, x):
        x = self.conv(x)
        x = self.relu1(x)
        x = self.conv2(x)
        return x
    
整体的cle流程
def test_cle():
    model = onnx2torch_cle()
    weight_all(model)
    model = model.eval()
    model = model.cpu()
    model_aimet = copy.deepcopy(model)
    input_shape = [1, 3, 264, 264]
    dummy_input = torch.rand(input_shape)
    dummy_output = model(dummy_input)
    # 可视化权重
    output_png_root = os.path.join(os.path.dirname(__file__), 'doc')
    if not os.path.exists(output_png_root):
        os.mkdir(output_png_root)
    file_name = 'org_pre_layer_w'
    show_weight(model.conv.weight.detach().numpy(), file_name, os.path.join(output_png_root, '{}.png'.format(file_name)))
    file_name = 'org_cur_layer_w'
    show_weight(model.conv2.weight.detach().numpy().transpose(1,0,2,3), file_name, os.path.join(output_png_root, '{}.png'.format(file_name)))

    # cle微调权重
    scale, pre_layer_weight_res, pre_layer_bias_res, cur_layer_weight_res = my_cle(model.conv.weight.detach().numpy(), 
                                                                                   model.conv.bias.detach().numpy(), 
                                                                                   model.conv2.weight.detach().numpy().transpose(1,0,2,3))
    cur_layer_weight_res = torch.from_numpy(cur_layer_weight_res.transpose(1,0,2,3))
    pre_layer_weight_res = torch.from_numpy(pre_layer_weight_res)
    pre_layer_bias_res = torch.from_numpy(pre_layer_bias_res)
    model.conv.weight.data = pre_layer_weight_res
    model.conv.bias.data = pre_layer_bias_res
    model.conv2.weight.data = cur_layer_weight_res
    dummy_output_cle = model(dummy_input)
    a,b = compare_data(dummy_output.detach().numpy(), dummy_output_cle.detach().numpy())
    print(scale)
    print(a,b)
    file_name = 'cle_pre_layer_w'
    show_weight(model.conv.weight.detach().numpy(), file_name, os.path.join(output_png_root, '{}.png'.format(file_name)))
    file_name = 'cle_cur_layer_w'
    show_weight(model.conv2.weight.detach().numpy().transpose(1,0,2,3), file_name, os.path.join(output_png_root, '{}.png'.format(file_name)))
  
if __name__ == "__main__":
    test_cle()
测试结果
  • 从compare的结果可以看出,cle前后的模型在同个输入下的输出是基本保持一致的(余弦相似度=1.0、相对最大误差=3.6033464e-07)。

  • 下述的可视化结果如下,我们可以看到:

    • cle后model.conv.weight的每output_channel上的range相较cle前更加均衡
    • cle后model.conv2.weight的每input_channel上的range同model.conv.weight的每output_channel上的range基本相同
  • 原始模型的权重分布如下:

    • model.conv.weight
      在这里插入图片描述

    • model.conv2.weight
      在这里插入图片描述

  • cle后模型的权重分布如下:

    • model.conv.weight
      在这里插入图片描述

    • model.conv2.weight
      在这里插入图片描述

具体的测试脚本程序

可见下载链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1209283.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Adobe家里的“3D“建模工 | Dimension

今天,我们来谈谈一款在Adobe系列中比肩C4D的高级3D软件的存在—— Dimension。 Adobe Dimension ,其定位是一款与Photoshop以及Illustrator相搭配的3D绘图软件。 Adobe Dimensions与一般的3D绘图软件相较之下,在操作界面在功能上有点不大相同…

第四天课程 分布式搜索引擎1

分布式搜索引擎01 – elasticsearch基础 0.学习目标 1.初识elasticsearch 1.1.了解ES 1.1.1.elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容 例如: …

常见排序算法实现

💕"每一天都是值得被热爱的"💕 作者:Mylvzi 文章主要内容:常见排序算法实现 1.排序的概念 所谓排序,就是按照特定顺序重新排列序列的操作 排序的稳定性: 当一个序列中存在相同的元素时 排序过…

Swift制作打包framework

新建framework项目 设置生成fat包,包括模拟器x86_64和arm64 Buliding Settings -> Architectures -> Build Active Architecture Only 设置为NO 设置打包环境,选择release edit Scheme -> run -> Build configuration 设置为 Release 设置…

专题解读|Graph Fairness代表性工作介绍

1. 图上的公平性问题 图在现实世界中无处不在,例如知识图谱,社交网络和生物网络。近年来,图神经网络( graph neural networks,GNNs ) 在图结构数据建模方面表现出了强大的能力。一般地,GNNs采用消息传递机制&#xff…

什么是应用集成?应用集成快速指南

什么是应用集成? 想象一下,在剧院观看音乐剧,没有人站在正确的地方,每个人都在互相交谈,或者有漫长而尴尬的沉默,管弦乐队的音乐家们在错误的时刻演奏,完全是混乱的,就会很难看。 业…

房产中介租房小程序系统开发搭建:详细指南教你如何构建

随着微信小程序的日益普及,越来越多的企业和个人开始尝试开发自己的小程序。以下是制作一个房地产微信小程序的详细教程,希望对大家有所帮助。 一、注册登录乔拓云平台,进入后台 首先,需要注册并登录乔拓云平台,该平台…

Centos上删除文件及目录的命令积累

01-如果我想删除Centos上当前目录下的文件 test06-2023-11-14-01.sql 该怎么操作? 答:如果你想删除CentOS上当前目录下的文件 test06-2023-11-14-01.sql,可以使用 rm 命令。以下是删除文件的基本语法: rm test06-2023-11-14-01.s…

sql查询查看数据库空间使用情况

SELECT UPPER(F.TABLESPACE_NAME) "表空间名", D.TOT_GROOTTE_MB "表空间大小(M)", D.TOT_GROOTTE_MB - F.TOTAL_BYTES "已使用空间(M)", TO_CHAR(ROUND((D.TOT_GROOTTE_MB - F.TOTAL_BYTES) / D.TOT_GROOTTE_MB * 100,2),990.99) || % "使…

Nexus的Maven私有仓库搭建

Nexus的maven私有仓库搭建 一、了解 maven仓库设置 默认设置 其中: maven-central: 预定义的代理Maven Central仓库,它包含了大量的开源Java依赖包。maven-public: 存储库是一个组合存储库,它包含了maven-releases和maven-snapshots存储库…

【机器学习基础】机器学习的模型评估(评估方法及性能度量原理及主要公式)

🚀个人主页:为梦而生~ 关注我一起学习吧! 💡专栏:机器学习 欢迎订阅!后面的内容会越来越有意思~ 💡往期推荐: 【机器学习基础】机器学习入门(1) 【机器学习基…

CM211-1 MC022主板输入刷Armbian

咋一看以为是NAND的存储,经过各方搜索,发现BWCMMQ511G08G存储芯片是狭义的NAND,支持emmc协议,故而做尝试。 烧写步骤 1.下载Armbian镜像 Armbian_23.11.0_amlogic_s905l3-cm211_lunar_6.1.60_server_2023.11.01.img.gz 2.将镜像…

Leetcode—4.寻找两个正序数组的中位数【困难】

2023每日刷题(二十九) Leetcode—4.寻找两个正序数组的中位数 直接法实现代码 int mid, mid1, mid2; bool findmid(int n, int k, int x) {if(n % 2 1) {if(k n / 2) {mid x;return true;}} else {if(k n / 2 - 1) {mid1 x;} else if(k n / 2) {…

程序员,你的护城河挖好了吗?

程序员的护城河 在遥远的古代,护城河是一种防御工事,通常用于保护城市或城堡免受外部攻击。它是由人工挖掘或天然形成的河流、壕沟或城墙等,可以作为防御屏障,阻止敌人的进入。 而对于程序员而言,“护城河”是一种比喻…

Java之SpringCloud Alibaba【九】【Spring Cloud微服务Skywalking】

Java之SpringCloud Alibaba【一】【Nacos一篇文章精通系列】跳转Java之SpringCloud Alibaba【二】【微服务调用组件Feign】跳转Java之SpringCloud Alibaba【三】【微服务Nacos-config配置中心】跳转Java之SpringCloud Alibaba【四】【微服务 Sentinel服务熔断】跳转Java之Sprin…

【milkv】2、mpu6050驱动添加及测试

前言 本章介绍mpu6050的驱动添加以及测试。 其中驱动没有采用sdk提供的驱动,一方面需要配置irq,另一方面可以学习下如何通过ko方式添加驱动。 一、参考文章 驱动及测试文件编译流程: https://community.milkv.io/t/risc-v-milk-v-lsm6ds…

Semantic Kernel 学习笔记2

本来想白瞟免费Bing Search API如下,但是报错无法链接利用免费的必应 Bing 自定义搜索打造站内全文搜索_bing_subscription_key-CSDN博客 改成按照官方推荐申请,并在.env文件中添加BING_API_KEY""字段。 1. 打开https://www.microsoft.com/en-…

Quarkus 替代 SpringBoot

1 概述2 SpringBoot3 Quarkus4 比较5 调查结果6 从 Spring 转换到 Quarkus7 我是 Spring 开发者,为什么要选Quarkus?8 Spring 开发者可以活用哪些现有知识?9 对Spring开发者有额外的好处吗?10 Spring开发者如何开始学习Quarkus&am…

mp4视频批量截取!!!

mp4视频批量截取!!! 问题:如果我们想截取一个mp4视频中的多个片段,一个一个截会很麻烦! 可以将想要截取的开始时间和结束时间保存到 excel表 中,进行批量截取。 1、对一个视频,记…

临床决策分析(DCA)演示APP:理解DCA分析

临床决策分析(DCA)演示APP:理解DCA分析 之前讨论了DCA分析的分析过程和作用,认为其最主要的作用是确定预测模型的决策阈值,从而促进预测模型与临床的结合。DCA的影响不止于此,在DCA分析中,预测…