模型量化(一)—— 非对称量化、对称量化(全代码)

模型量化是一种减少深度学习模型大小和提高推理速度的技术,通过降低模型参数的精度(例如,从32位浮点数减少到8位整数)来实现。

量化三个好处:

  • 更少的内存消耗(对于智能手机等端侧设备很重要)
  • 更少的推断时间,因为数据类型更简单。
  • 更少的能量消耗,因为推断需要更少的计算。

在这里插入图片描述
在这里插入图片描述
(题外话:反量化操作是为了让量化后的神经元输出与量化前的输出变化不大,不然整型变换后相乘的参数值会与原本的浮点值差很多,对于后面的神经元来说输入相当于就变了,模型准确率自然大打折扣,所以激活值需要经过反量化,从而使得后面的神经元察觉不到输入发生变化,对于整个神经网络来说,输入什么就输出什么,仿佛没有量化操作参与,精度自然能保持。)

 

量化可以应用于模型的权重和激活(即中间输出值)上。在量化方法中,非对称量化对称量化是两种常见的量化策略,它们各有特点和应用场景。白话说就是对称量化时0点对齐

 

在这里插入图片描述

贴上一个自己总结的笔记,看完本文回过头来看这个会很清晰。

在这里插入图片描述

 
具体的模型量化方法分为
post-training quantization(训练后量化)和quantization-aware training(量化感知训练),在之后的博客中详细讨论,本文先打好量化的基础。

目录

  • 非对称量化
  • 对称量化
  • Python全代码
  • 如何选 𝛼, β
  • 浮点数存储格式(IEEE-754)

 

非对称量化

非对称量化不要求量化后的值中零点对应于原始值中的零。这意味着量化操作可以有一个任意的零点,这个零点被映射到量化范围内的某个整数值上。因此,非对称量化使用三个参数(量化最小值、量化最大值和零点)来定义从原始数值到量化数值的映射关系。

在这里插入图片描述

缺点是执行量化和反量化操作可能需要更多的计算

 

对称量化

对称量化要求量化后的值中零点必须对应于原始值中的零,这意味着量化操作的零点固定不变。因此,对称量化通常使用两个参数(量化的最小值和最大值)来定义量化的范围,而这个范围是以零为中心对称的。

在这里插入图片描述

缺点是很少有参数矩阵是很对称的,无法像非对称量化那样精确地表示数据范围,导致量化误差增加

 

Python全代码

#1. Create a simple tensor with random items

import numpy as np

# Suppress scientific notation
np.set_printoptions(suppress=True)

# Generate randomly distributed parameters
params = np.random.uniform(low=-50, high=150, size=20)

# Make sure important values are at the beginning for better debugging
params[0] = params.max()
params[1] = params.min()
params[2] = 0

# Round each number to the second decimal place
params = np.round(params, 2)

# Print the parameters
print(params)



#2. Define the quantization methods and quantize

def clamp(params_q: np.array, lower_bound: int, upper_bound: int) -> np.array:
    params_q[params_q < lower_bound] = lower_bound
    params_q[params_q > upper_bound] = upper_bound
    return params_q

def asymmetric_quantization(params: np.array, bits: int) -> tuple[np.array, float, int]:
    # Calculate the scale and zero point
    alpha = np.max(params)
    beta = np.min(params)
    scale = (alpha - beta) / (2**bits-1)
    zero = -1*np.round(beta / scale)
    lower_bound, upper_bound = 0, 2**bits-1
    # Quantize the parameters
    quantized = clamp(np.round(params / scale + zero), lower_bound, upper_bound).astype(np.int32)
    return quantized, scale, zero

def asymmetric_dequantize(params_q: np.array, scale: float, zero: int) -> np.array:
    return (params_q - zero) * scale

def symmetric_dequantize(params_q: np.array, scale: float) -> np.array:
    return params_q * scale

def symmetric_quantization(params: np.array, bits: int) -> tuple[np.array, float]:
    # Calculate the scale
    alpha = np.max(np.abs(params))
    scale = alpha / (2**(bits-1)-1)
    lower_bound = -2**(bits-1)
    upper_bound = 2**(bits-1)-1
    # Quantize the parameters
    quantized = clamp(np.round(params / scale), lower_bound, upper_bound).astype(np.int32)
    return quantized, scale

def quantization_error(params: np.array, params_q: np.array):
    # calculate the MSE
    return np.mean((params - params_q)**2)

(asymmetric_q, asymmetric_scale, asymmetric_zero) = asymmetric_quantization(params, 8)
(symmetric_q, symmetric_scale) = symmetric_quantization(params, 8)

print(f'Original:')
print(np.round(params, 2))
print('')
print(f'Asymmetric scale: {asymmetric_scale}, zero: {asymmetric_zero}')
print(asymmetric_q)
print('')
print(f'Symmetric scale: {symmetric_scale}')
print(symmetric_q)

#2.1 Dequantize the parameters back to 32 bits
params_deq_asymmetric = asymmetric_dequantize(asymmetric_q, asymmetric_scale, asymmetric_zero)
params_deq_symmetric = symmetric_dequantize(symmetric_q, symmetric_scale)

print(f'Original:')
print(np.round(params, 2))
print('')
print(f'Dequantize Asymmetric:')
print(np.round(params_deq_asymmetric,2))
print('')
print(f'Dequantize Symmetric:')
print(np.round(params_deq_symmetric, 2))

#2.2 Calculate the quantization error
print(f'{"Asymmetric error: ":>20}{np.round(quantization_error(params, params_deq_asymmetric), 2)}')
print(f'{"Symmetric error: ":>20}{np.round(quantization_error(params, params_deq_symmetric), 2)}')

 

如何选 𝛼, β

Min-Max很简单不谈了,就取列表中的最大和最小值当作 𝛼, β,确实是如果出现outlier,量化误差就很大。

Percentile为了规避outlier的影响,选择列表比绝大部分数据都大的数为𝛼,但这个比例不是100%哦,不然过滤不掉outlier,可以选99%或99.9%。
np.percentile是NumPy库中的一个函数,用于计算给定数据集在指定百分位数下的值。百分位数是一种统计度量,表示在一个数据集中,有多少比例的数据点小于或等于这个值

在这里插入图片描述

下面用代码对比两种方式:


#1. Create a simple tensor with random items

import numpy as np

# Suppress scientific notation
np.set_printoptions(suppress=True)

# Generate randomly distributed parameters
params = np.random.uniform(low=-50, high=150, size=10000)

# Introduce an outlier
params[-1] = 1000

# Round each number to the second decimal place
params = np.round(params, 2)

# Print the parameters
print(params)


#2. Define the quantization methods and quantize
#2.1 Compare min-max and percentile range selection strategies

def clamp(params_q: np.array, lower_bound: int, upper_bound: int) -> np.array:
    params_q[params_q < lower_bound] = lower_bound
    params_q[params_q > upper_bound] = upper_bound
    return params_q

def asymmetric_quantization(params: np.array, bits: int) -> tuple[np.array, float, int]:
    alpha = np.max(params)
    beta = np.min(params)
    scale = (alpha - beta) / (2**bits-1)
    zero = -1*np.round(beta / scale)
    lower_bound, upper_bound = 0, 2**bits-1
    quantized = clamp(np.round(params / scale + zero), lower_bound, upper_bound).astype(np.int32)
    return quantized, scale, zero

def asymmetric_quantization_percentile(params: np.array, bits: int, percentile: float = 99.99) -> tuple[np.array, float, int]:
    # find the percentile value
    alpha = np.percentile(params, percentile)
    beta = np.percentile(params, 100-percentile)
    scale = (alpha - beta) / (2**bits-1)
    zero = -1*np.round(beta / scale)
    lower_bound, upper_bound = 0, 2**bits-1
    quantized = clamp(np.round(params / scale + zero), lower_bound, upper_bound).astype(np.int32)
    return quantized, scale, zero


def asymmetric_dequantize(params_q: np.array, scale: float, zero: int) -> np.array:
    return (params_q - zero) * scale

def quantization_error(params: np.array, params_q: np.array):
    # calculate the MSE
    return np.mean((params - params_q)**2)

(asymmetric_q, asymmetric_scale, asymmetric_zero) = asymmetric_quantization(params, 8)
(asymmetric_q_percentile, asymmetric_scale_percentile, asymmetric_zero_percentile) = asymmetric_quantization_percentile(params, 8)

print(f'Original:')
print(np.round(params, 2))
print('')
print(f'Asymmetric (min-max) scale: {asymmetric_scale}, zero: {asymmetric_zero}')
print(asymmetric_q)
print(f'')
print(f'Asymmetric (percentile) scale: {asymmetric_scale_percentile}, zero: {asymmetric_zero_percentile}')
print(asymmetric_q_percentile)

#2.2 Dequantize the parameters back to 32 bits

params_deq_asymmetric = asymmetric_dequantize(asymmetric_q, asymmetric_scale, asymmetric_zero)
params_deq_asymmetric_percentile = asymmetric_dequantize(asymmetric_q_percentile, asymmetric_scale_percentile, asymmetric_zero_percentile)

print(f'Original:')
print(np.round(params, 2))
print('')
print(f'Dequantized (min-max):')
print(np.round(params_deq_asymmetric,2))
print('')
print(f'Dequantized (percentile):')
print(np.round(params_deq_asymmetric_percentile,2))

#3. Evaluate the quantization error (excluding the outlier)

# Calculate the quantization error
print(f'{"Error (min-max) excluding outlier: ":>40}{np.round(quantization_error(params[:-1], params_deq_asymmetric[:-1]),2)}')
print(f'{"Error (percentile) excluding outlier: ":>40}{np.round(quantization_error(params[:-1], params_deq_asymmetric_percentile[:-1]),2)}')

 

浮点数存储格式(IEEE-754)

题外话,浮点数的存储格式

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一道AI做过的小学奥数题,结果表明:今天的AI已经达到精神病人的智力水平

重庆家长找AI计算的小学奥数题&#xff0c;AI没有找到答案。也就是被吹上天的AI其实根本不具有人类智能。但不妨把AI理解为精神病人&#xff0c;因为他们有异常的艺术天赋。 两地A、B之间相距4000m&#xff1b;甲从A地以匀速60m/min向B出发&#xff0c;同时乙从B地出发以匀速26…

toJSONString空值被忽略解决办法 toJSONString过程中时间格式丢失问题解决办法

toJSONString空值被忽略解决办法 原代码&#xff1a; GcGarbageBuildingDO data gcGarbageBuildingService.get(id); result.putAll(JSON.parseObject(JSON.toJSONString(data), Map.class));查询出来的data中部分字段值为null&#xff0c;在toJSONString的过程中会把null值…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的车牌检测系统(Python+PySide6界面+训练代码)

摘要&#xff1a;本篇博客详细介绍了如何利用深度学习技术开发一个先进的车牌检测系统&#xff0c;并附上了完整的实现代码。系统核心采用了强大的YOLOv8算法&#xff0c;并对前代版本如YOLOv7、YOLOv6、YOLOv5进行了详尽的性能评估&#xff0c;包括mAP和F1 Score等关键指标的对…

重建大师模型构建精细网格失败是什么原因导致的呢?(如下图)

出现图中的报错一般是显存溢出、瓦块过大造成的。 重建大师是一款专为超大规模实景三维数据生产而设计的集群并行处理软件&#xff0c;输入倾斜照片&#xff0c;激光点云&#xff0c;POS信息及像控点&#xff0c;输出高精度彩色网格模型&#xff0c;可一键完成空三、自动建模和…

如何获取免费格式转换器MP3?全平台最新的20款软件推荐

随着数字音乐的普及&#xff0c;MP3格式已经成为了最为常见的音频格式之一。然而&#xff0c;有时我们可能会遇到需要转换音频格式的情况&#xff0c;比如将其他格式的音频文件转换为MP3格式。在这种情况下&#xff0c;一款好用的格式转换器就显得尤为重要。本文将为您推荐20款…

第14届环境与农业工程国际会议(ICEAE 2024)即将召开!

2024年第14届环境与农业工程国际会议&#xff08;ICEAE 2024&#xff09;将于6月7日至9日在泰国曼谷召开。本次会议旨在促进环境与农业工程的研究和开发活动&#xff0c;共同探讨领域内最新以及具有根本性的进展突破。热忱欢迎从事相关领域研究的专家&#xff0c;学者和专业技术…

YOLOv9改进项目|关于本周更新计划的说明24/3/12

目前售价售价59.9&#xff0c;改进点30个 专栏地址&#xff1a; 专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;主力高效涨点&#xff01;&#xff01;&#xff01; 日期&#xff1a;24/3/12 本周更新计划说明&#xff1a; 1. 更新华为Gold YOLO中的…

人工智能迷惑行为大赏!

目录 人工智能迷惑行为大赏 一&#xff1a;人工智能的“幽默”瞬间 1. 图像识别出现AI的极限 2. 小批量梯度下降优化器 3. 智能聊天机器人的冰雹问题 4. 大语言模型-3经典语录 二&#xff1a;技术原理探究 1. 深度学习 2. 机器学习 3. 自然语言处理 4. 计算机视觉 三…

[Java、Android面试]_02_HashMap的原理

本人今年参加了很多面试&#xff0c;也有幸拿到了一些大厂的offer&#xff0c;整理了众多面试资料&#xff0c;后续还会分享众多面试资料&#xff0c;感兴趣的朋友可收藏关注。由于时间有限&#xff0c;只能每天整理一点&#xff0c;分享一点儿&#xff01; 现分享如下&#xf…

读西游记第一回:西游记世界格局

天地之数&#xff1a; 元&#xff1a;十二万九千六百岁&#xff08;129600年&#xff09; 1元12会&#xff1a;子、丑、寅、卯、巳、午、未、申、酉、戌、亥。每会18000年。与12地支对应。 亥会期&#xff1a;前5400年混沌期&#xff0c;后5400年&#xff0c;盘古开天辟地&am…

【STL】stack栈容器与list链表容器

1.栈stack 栈具有先进后出的特性&#xff0c;最先进入的数据压在最底下&#xff0c;最后出来 2.list链表容器 list链表容器是一种双向链表&#xff0c;两端都可插入与删除&#xff0c;是双向访问迭代器&#xff0c;与vertor随机访问迭代器有不同的区别 reverse&#xff08;&…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Toggle)

组件提供勾选框样式、状态按钮样式及开关样式。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 仅当ToggleType为Button时可包含子组件。 接口 Toggle(options: { type: ToggleType, is…

2024-Android大厂(字节跳动,腾讯

PS&#xff1a;全文点击蓝色文字&#xff0c;即可跳转链接 【字节面试官&#xff1a;看了3000多份简历&#xff0c;面试1000场后&#xff0c;想给金九银十找工作的程序员几点建议附大厂真题面经】 本文主要介绍校招&#xff0c;上半年疫情原因真正面试的时间和机会也不多&#…

网络流量监控软件AnaTraf:优化性能、排除故障的最佳选择

目录 导言 网络流量监控的重要性 AnaTraf网络万用表的功能与优势 网络故障排除与优化网络性能 结论 导言 在当今数字化时代&#xff0c;计算机网络已经成为企业和组织的核心基础设施。然而&#xff0c;网络流量的管理和监控对于确保网络性能的稳定和优化至关重要。本文将介…

11双体系Java学习之方法

方法简述 package method;public class Demo01 {//main 方法public static void main(String[] args) {//实际参数&#xff1a;实际调用传递给他的参数int sum add (1,2);System.out.println(sum);//test();}//加法//形式参数&#xff0c;用来定义作用的public static int add…

工作中常用的git命令

git 分布式版本控制系统。 使用远程仓库时候会有多个协议可以选择&#xff0c;使用https不仅仅速度慢&#xff0c;而且每次push都要输入口令。 HEAD 当前版本的指针&#xff0c;当切换本地版本的时候会快速指向指定版本文件 master git为我们创建主分支 origin 远程仓库的名…

以102flowers数据集为例训练ResNet50模型

以102flowers数据集为例训练ResNet50模型 使用飞桨高阶API&#xff0c;使用最少的代码量&#xff0c;实现在102flowers数据集训练ResNet50模型。同时可以一条命令修改成Mnist、Cifar10、Cifar100等数据集&#xff0c;换成其它模型也是只需要一句话代码。 数据集介绍 102flowe…

合并 K 个升序链表

题目&#xff1a; class Solution { public://合并两个升序链表ListNode* mergetwo(ListNode* l1, ListNode* l2){if(!l1 || !l2) return l1 ? l1 : l2;ListNode* dummy new ListNode(0);ListNode* cur dummy;while(l1&&l2){if(l1->val < l2->val){cur-&…

【SQL Server安装绊脚石】排除报错的终极指南

&#x1f6a9;本文介绍 ​ 在迈向数据库管理系统的世界时&#xff0c;SQL server的安装过程往往是我们踌躇的绊脚石。一不小心&#xff0c;就可能陷入各种报错的困境中。然而&#xff0c;正是这些挑战&#xff0c;让我们更加升入地了解SQL server地安装与配置&#xff0c;也让…

Redis缓存问题详解和处理

缓存更新策略 缓存穿透 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库. 常见的解决方案: 缓存空对象 优点: 实现简单, 维护方便缺点: 额外的内存消耗, 可能造成短期的不一致 布隆过滤 优点: 内存占用较少(保存的是数据…