Quantization

news/2024/12/4 19:47:35/文章来源:https://www.cnblogs.com/MTandHJ/p/18587047

目录
  • 线性量化 (Linear Quantization)
    • 对称量化
    • 非对称量化
  • 非线性量化
    • Power-of-X
  • Rounding
    • Deterministic rounding
    • Stochastic rounding

[1] 进击的程序猿-模型压缩-神经网络量化基础.

[2] Przewlocka-Rus D., Sarwar S. S., Sumbul H. E., Li Y. and De Salvo B. Power-of-two quantization for low bitwidth and hardware compliant neural networks. tinyML Research Symposium, 2022.

[3] Li Y., Dong X. and Wang W. Additive powers-of-two quantization: an efficient non-uniform discretization for neural networks. ICLR, 2020.

[4] Xia L., Anthonissen M., Hochstenbach M. and Koren B. Improved stochastic rounding. 2020.

整理了一下量化中的基础概念和方法. 其实, 在计算机中, 我们所见之浮点数也只不过是真正数字的一个高精度量化 (e.g, FP32), 但是随着模型的逐步增加, 我们需要将模型进一步'精简'. 当然了, '精简'的法子有很多: 裁剪 (pruning), 蒸馏 (distillation), 包括这里讲到的量化 (quantization). 个人感觉, 相较于裁剪和蒸馏, 量化是一种即插即用的方法 (虽然会有一些追求极限精度的量化方法需要一些校准). 本文讨论如下的例子:

\[\underbrace{[-3.1, -0.03, 0.1, 1.2]}_{x_f} \mathop{\longrightarrow} \limits^{Q} [...] \subset \underbrace{[-128, 127]}_{\text{Int8}}/\underbrace{[0, 255]}_{\text{UInt8}}. \]

线性量化 (Linear Quantization)

对称量化

  • \(x_q = Q(x_f)\) 的对称量化过程如下:

    1. 确定 \(x_f\) 的(绝对值)范围: \(\Delta_f = \max_i(|x_f[i]|)\);
    2. 确定 \(x_q\) 的范围: \(\Delta_q = 2^{N-1} - 1\), \(N\) 表示量化后的精度, 比如 Int8 时 \(\Delta_q = 127\).
    3. 量化:

      \[x_q = Q(x_f) := \text{round}(\frac{x_f}{\Delta_f} \cdot \Delta_q). \]

  • 如上图所示, \(\Delta_f\) 首先将 \(x_f\) 压缩到 \([-1, 1]\) 之中, 然后再映射回 \([-128, 127]\) 的量化后的精度中.


def quant(f: torch.Tensor, N: int = 8):delta_f = f.abs().max()delta_q = 2 ** (N - 1) - 1return (f * delta_q / delta_f).round().to(torch.int), delta_f
  • 利用上述代码可得:

\[[-127, -1, 4, 49]. \]

  • 反解的过程:

    \[\hat{x}_f = Q^{-1}(x_q) := \frac{x_q}{\Delta_q} \cdot \Delta_f. \]


def dequant(q: torch.Tensor, delta_f: torch.Tensor, N: int = 8):delta_q = 2 ** (N - 1) - 1return (q * delta_f / detal_q).float()
  • 得到:

    \[[-3.1000, -0.0244, 0.0976, 1.1961]. \]

非对称量化

  • \(x_q = Q(x_f)\) 的非对称量化过程如下:

    1. 确定 \(x_f\) 的(绝对值)范围: \(\Delta_f = x_f^{\max} - x_f^{\min}\);
    2. 确定 \(x_q\) 的范围: \(\Delta_q = 2^{N} - 1\), \(N\) 表示量化后的精度, 比如 UInt8 时 \(\Delta_q = 255\).
    3. 确定零点偏移量: \(x_{offset} = -x_f^{\min}\)
    4. 量化:

      \[x_q = Q(x_f) := \text{round}(\frac{x_f + x_{offset}}{\Delta_f} \cdot \Delta_q). \]

  • 注意到:

    \[x_f + x_{offset} = x_f - x_f^{\min} \in [0, \Delta_f]. \]


def quant(f: torch.Tensor, N: int = 8):offset = -f.min()delta_f = f.max() + offsetdelta_q = 2 ** N - 1return ((f + offset) * delta_q / delta_f).round().to(torch.int), delta_f, offset
  • 通过如上代码可得量化结果:

    \[[0, 182, 190, 255] \]

  • 通过如下方式进行反解:

    \[\hat{x}_f = Q^{-1}(x_q) := \frac{x_q}{\Delta_q} \cdot \Delta_f - x_{offset}. \]


def dequant(q: torch.Tensor, delta_f: torch.Tensor, offset: torch.Tensor, N: int = 8):delta_q = 2 ** N - 1return (q * delta_f / delta_q).add(-offset).float()
  • 得到:

    \[[-3.1000, -0.0310, 0.1039, 1.2000] \]

非线性量化

  • 其实, 一般的量化都可以用如下的过程统一表示:

    1. \(x_f\) normalize 到 \(\phi(x) \in [0/-1, 1]\) 区间内;
    2. 在该区间内设置 \(2^N\) (或者 \(2^N - 1\)) 个点, 记为:

      \[\mathcal{Q} = \{q_i\}_{i \in \mathcal{I}}. \]

    3. 寻找最近邻的作为量化结果:

      \[Q(x) = \mathop{\text{argmin}} \limits_{i \in \mathcal{I}} |\phi(x) - q_i|. \]

  • 之前的线性量化实际上就是:

    \[\mathcal{Q} = \{i / (2^{N - 1} - 1)\}_{i \in \mathcal{I}}, \\ \mathcal{I} = \{-(2^{N-1} - 1), \ldots, 0, 1, \ldots, 2^{N-1} - 1\}, \]

    \[\mathcal{Q} = \{i / (2^{N} - 1)\}_{i \in \mathcal{I}}, \\ \mathcal{I} = \{0, 1, \ldots, 2^{N} - 1\}. \]

  • 而 round 就是一种自动的 nearest 的搜索方式.

  • 当然了, \(\mathcal{Q}\) 的分布不必像线性量化一样那样的均匀, 实际上这种分布往往不是最优的. 容易感觉到, 最优的分布应当在 \(x_f\) 中比较稠密的范围分布较多的量化点, 否则会造成大量的浪费. 当然了, 这种非线性量化的方式相较于线性量化有它的不足之处, 就是得根据数据'找'一个合适的分布, 这个'找'的过程往往是比较耗时的.

Power-of-X

  • Power-of-X 的特点就是 \(\mathcal{Q}\) 的分布是服从指数分布的:

    \[\mathcal{Q} = \{\alpha^{i-1} \}_{i \in \mathcal{I}} \cup \{\mathcal{Q}_0 = 0\}, \\ \mathcal{I} = \{1, \ldots, 2^{N} - 1\}. \]

    其中 \(\alpha \in (0, 1)\).

  • 其量化过程为:

    1. 确定 \(x_f\) 的(绝对值)范围: \(\Delta_f = \max_i(|x_f[i]|)\);
    2. 确定 \(x_q\) 的范围: \(\Delta_q = 2^{N-1} - 1\), \(N\) 表示量化后的精度, 比如 Int8 时 \(\Delta_q = 127\).
    3. 量化:

      \[x_q = Q(x_f) := \text{sign}(x_f) \cdot \text{clip} \Bigg( \text{round}\bigg(\log_{\alpha} \bigg(\frac{|x_f|}{\Delta_f}\bigg) + 1 \bigg), 0, \Delta_q \Bigg). \]

    4. 反解的过程为:

      \[\hat{x}_f = \text{sign}(x_q) \cdot \alpha^{|x_q| - 1} \cdot \Delta_f. \]

注: 这里 \(+1, -1\) 是为了将 \(0\) 保留给真正的 0 值.


def quant(f: torch.Tensor, alpha: float, N: int = 8):sign, f = f.sign(), f.abs()delta_f = f.max()delta_q = 2 ** (N - 1) - 1logalpha = math.log2(alpha)return (f / delta_f).log2().div(logalpha).add(1).round().clip(0, delta_q).mul(sign).to(torch.int), delta_fdef dequant(q: torch.Tensor, alpha: float, delta_f: torch.Tensor, N: int = 8):sign, q = q.sign(), q.abs()return (alpha ** q.add(-1)).mul(delta_f).mul(sign)

  • 如上图所示, \(\alpha \rightarrow 0\), 不均匀性大大增加. 这个性质在有些时候会很有用, 因为很多数据的分布是形容高斯分布的, 此时采用不均匀的会更加高效.

  • 需要声明的一点是, \(\alpha \rightarrow 1\) 的时候, 整体会显得更加均匀一点, 但是并不能等价线性量化, 注意到:

    \[\alpha^{2^N} \mathop{\longrightarrow} \limits^{\alpha \rightarrow 1} 1. \]

    这意味着, 除了 \(0\) 之外, \(\mathcal{Q}\) 所能表示的最小值会随着 \(\alpha\) 增加逐步增大. 这其实是另一种极为严重的 '不均匀' 性质.

  • 此外 \(\alpha = 0.5\) 是比较特殊的一种情况, 可以通过位操作加速.

Rounding

有些时候 Rounding 的方式也很重要, 毕竟它是误差的来源.

Deterministic rounding

Stochastic rounding

  • 随机 rounding 形式如下:

    \[\text{round}(x) = \lfloor x \rfloor + \mathbb{I}\big[x - \lfloor x \rfloor \xi \big], \quad \xi \sim \mathcal{U}([0, 1]). \]

    其中 \(\lfloor x \rfloor\) 表示 round down 操作.

  • 举个例子, 对于 \(0.4\), 它有 0.4 的概率为 \(1\)\(0.6\) 的概率为 0. 对于 \(-1.6\), 它有 \(0.6\) 的概率为 \(-2\), 有 \(0.4\) 的概率为 \(-1\).

  • 一个比较好的性质是:

    \[\begin{array}{ll} \mathbb{E}[\text{round}(x)] &= \lfloor x \rfloor + \mathbb{E}\bigg[\mathbb{I}\big[x - \lfloor x \rfloor \xi \big] \bigg] \\ &= \lfloor x \rfloor + 1 \cdot (x - \lfloor x \rfloor) \\ &= x \end{array}. \]

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

H5-28 清除浮动

浮动元素会造成父元素高度塌陷后续元素也会受到影响 1、浮动的作用当元素设置fliat浮动后,该元素就会脱离文档流并向左/向右浮动①浮动元素会造成父元素高度塌陷②后续元素会受到影响 <div class="box"><div class="a"></div><div…

第58篇 Redis常用命令

1.基本操作2.字符串(Strings)3.列表()4.哈希(Hashes)5.位图(Bitmaps)6.位域(Bitfields)7.集合(Sets)8.有序集合(SortedSets)9.流(Streams)10。地理空间(Geospatial)11.HyperLogLog

位运算(未完成)

1、如果n & (n-1)=0,则n为2的幂 2、 题1:找出唯一成对的数 1-1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现? 性质:AA=0,B0=B …

seleniumwire获取请求头参数

selenium-wire扩展了 Selenium 的 Python 绑定,让您可以访问浏览器发出的底层请求。 您编写代码的方式与使用 Selenium 的方式相同,但您可以获得额外的 API 来检查请求和响应并动态更改它们 一:简介 selenium是爬虫常用的手段之一,由于是使用浏览器驱动模拟手动操作,所以只…

Confusion pg walkthrough Intermediate

namp ┌──(root㉿kali)-[~] └─# nmap -p- -A 192.168.188.99 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-12-04 04:50 UTC Nmap scan report for 192.168.188.99 Host is up (0.072s latency). Not shown: 65532 closed tcp ports (reset) PORT STATE SERVICE…

ESP32+micropython+作为WiFi热点与PC通信+TCP/IP接收并返回数据

ESP32+作为WiFi热点+接收并返回数据 ESP32代码# ESP32 作为AP # 作为服务器 接收数据 并echo# ESP32 作为AP 即wifi热点 import network import utime# 配置ESP32为AP模式 ssid = ESP32_AP password = 12345678 authmode = 4 # WPA2-PSK# 创建WLAN对象 wlan = network.W…

ESP32+micropython+作为WiFi热点+接收并返回数据

ESP32+作为WiFi热点+接收并返回数据# ESP32 作为AP # 作为服务器 接收数据 并echo# ESP32 作为AP 即wifi热点 import network import utime# 配置ESP32为AP模式 ssid = ESP32_AP password = 12345678 authmode = 4 # WPA2-PSK# 创建WLAN对象 wlan = network.WLAN(networ…

docker环境一个奇怪的问题,容器进程正常运行,但是docker ps -a却找不到容器,也找不到镜像

一: 问题: docker环境一个奇怪的问题,使用容器跑的进程正常提供服务,在服务器上也能看到对应的端口正在监听,但是docker ps -a却找不到容器,也找不到镜像. 查看我使用docker容器启动服务的端口 正在监听docker images 找不到对应的镜像docker ps -a 找不到任何容器二: 排查过…

coca phrase的collocates MI计算比较

declare|declared war declare war declared war

Prime1_解法一:cms渗透 内核漏洞提权

Prime1_解法一:cms渗透 & 内核漏洞提权目录Prime1_解法一:cms渗透 & 内核漏洞提权信息收集主机发现nmap扫描tcp扫描tcp详细扫描22,80端口udp扫描漏洞脚本扫描目录爆破dirsearchWeb渗透wfuzz常见的 wfuzz 过滤器:获得wordpress后台权限wordpress cms渗透WordPress…

Bitmap Indexing in DBMS Bitmap Index vs. B-tree Index low cardinality

1、 Similarly let us assume that the Job of the Employees is divided into 4 categories only i.e Manager, Analyst, Clerk, and Salesman. Such columns are called columns with low cardinality. 2、 SELECT * FROM Employee WHERE New_Emp = &qu…

windows AD域控密码过期企业微信推送告警

在写了windows AD域控密码过期邮件推送告警后,有网友问我能不能写一篇关于企业微信推送的文章 如果需要看邮件推送或者需要自定义脚本,可以参考我的文章 windows AD域控密码过期邮件通知迭代版本1.企业微信告警要求 1.1.企业微信推送需要具备的条件需要在企业微信中创建企业微…