torch量化接口深度解读-eager模式-fx模式

news2024/9/27 23:32:26

一、定义

  1. 接口总结
  2. 量化模式解读

二、实现

  1. 接口总结
    1. PyTorch提供了三种不同的量化模式:Eager模式量化、FX图模式量化(维护)和PyTorch 2导出量化。
    2. Eager Mode Quantization是一个测试版功能。用户需要进行融合,并手动指定量化和去量化发生的位置,而且它只支持模块,不支持函数。
    3. FX图形模式量化是PyTorch中的一个自动量化工作流程,目前它是一个原型功能,由于我们有. PyTorch 2导出量化,它处于维护模式。它通过添加对泛函的支持和自动化量化过程来改进Eager Mode Quantization,尽管人们可能需要重构模型以使模型与FX Graph Mode Quantizations兼容(可通过torch.FX进行象征性跟踪)。请注意,FX Graph Mode Quantization预计不会在任意模型上工作,因为该模型可能无法进行符号追踪,我们将把它集成到torchvision等领域库中,用户将能够使用FX Graph Mode Quantization量化与支持的领域库中类似的模型。对于任意模型,我们将提供一般指导方针,但要真正使其工作,用户可能需要熟悉torch.fx,特别是如何使模型具有符号可追溯性。
    4. PyTorch 2导出量化是新的全图模式量化工作流程,作为PyTorch 2.1中的原型功能发布。使用PyTorch 2,我们正在转向更好的完整程序捕获解决方案(torch.export),因为它可以捕获更高比例的模型(在14K型号上为88.8%),而fx Graph Mode Quantization使用的程序捕获方案torch.fx.symbolic_trace(在14K型号上为72.7%)。torch.export在某些python构造方面仍然存在局限性,需要用户参与以支持导出模型中的动态性,但总体而言,它比之前的程序捕获解决方案有所改进。PyTorch 2导出量化是为torch.Export捕获的模型构建的,考虑了建模用户和后端开发人员的灵活性和生产力。主要特点是(1)。可编程API,用于配置如何量化模型,可以扩展到更多的用例(2)。简化了建模用户和后端开发人员的用户体验,因为他们只需要与单个对象(量化器)交互,就可以表达用户对如何量化模型以及后端支持什么的意图。3.可选的参考量化模型表示,可以用整数运算表示量化计算,该运算更接近硬件中发生的实际量化计算。
    5. 鼓励量化的新用户首先尝试PyTorch 2导出量化,如果效果不佳,用户可以尝试渴望模式量化。
    下表比较了Eager模式量化、FX图形模式量化和PyTorch 2导出量化之间的差异:
    在这里插入图片描述
    支持三种类型的量化:

    1. 动态量化(当网络训练完成后,其权重值已经确定,故权重的量化因子已经确定,但是对于不同的输入值来说,其缩放因子是动态计算的)------------训练后量化
    2. 静态量化(静态量化的模型在使用前有fine-tuning的过程(校准缩放因子):准备部分输入(对于图像分类模型就是准备一些图片,其他任务类似),使用静态量化后的模型进行预测,在此过程中量化模型的缩放因子会根据输入数据的分布进行调整。) -------------训练后量化
    3. 静态量化感知训练(它将静态量化直接插入到网络的训练过程中,消除了网络训练后的校准过程。)---------训练时量化
  2. 量化模式解读
    量化模式分为: eager 模式, fx 模式 ,pytorch 2 模式
    eager 模式下量化
    1. PTQ–动态量化

import torch
# define a floating point model
class M(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.fc = torch.nn.Linear(4, 4)

    def forward(self, x):
        x = self.fc(x)
        return x

# create a model instance
model_fp32 = M()
# create a quantized model instance
model_int8 = torch.ao.quantization.quantize_dynamic(
    model_fp32,  # the original model
    {torch.nn.Linear},  # a set of layers to dynamically quantize   #量化的层
    dtype=torch.qint8)  # the target dtype for quantized weights

# run the model
input_fp32 = torch.randn(4, 4, 4, 4)
res = model_int8(input_fp32)

PTQ—静态量化

import torch

# define a floating point model where some layers could be statically quantized
class M(torch.nn.Module):
    def __init__(self):
        super().__init__()
        # QuantStub converts tensors from floating point to quantized
        self.quant = torch.ao.quantization.QuantStub()
        self.conv = torch.nn.Conv2d(1, 1, 1)
        self.relu = torch.nn.ReLU()
        # DeQuantStub converts tensors from quantized to floating point
        self.dequant = torch.ao.quantization.DeQuantStub()

    def forward(self, x):
        # manually specify where tensors will be converted from floating
        # point to quantized in the quantized model
        x = self.quant(x)
        x = self.conv(x)
        x = self.relu(x)
        # manually specify where tensors will be converted from quantized
        # to floating point in the quantized model
        x = self.dequant(x)
        return x

# create a model instance
model_fp32 = M()

# model must be set to eval mode for static quantization logic to work
model_fp32.eval()


model_fp32.qconfig = torch.ao.quantization.get_default_qconfig('x86')


model_fp32_fused = torch.ao.quantization.fuse_modules(model_fp32, [['conv', 'relu']])    #手动融合


model_fp32_prepared = torch.ao.quantization.prepare(model_fp32_fused)

# calibrate the prepared model to determine quantization parameters for activations
# in a real world setting, the calibration would be done with a representative dataset
input_fp32 = torch.randn(4, 1, 4, 4)
model_fp32_prepared(input_fp32)

# Convert the observed model to a quantized model. This does several things:
# quantizes the weights, computes and stores the scale and bias value to be
# used with each activation tensor, and replaces key operators with quantized
# implementations.
model_int8 = torch.ao.quantization.convert(model_fp32_prepared)    #量化

# run the model, relevant calculations will happen in int8
res = model_int8(input_fp32)

ATQ:

import torch

# define a floating point model where some layers could benefit from QAT
class M(torch.nn.Module):
    def __init__(self):
        super().__init__()
        # QuantStub converts tensors from floating point to quantized
        self.quant = torch.ao.quantization.QuantStub()
        self.conv = torch.nn.Conv2d(1, 1, 1)
        self.bn = torch.nn.BatchNorm2d(1)
        self.relu = torch.nn.ReLU()
        # DeQuantStub converts tensors from quantized to floating point
        self.dequant = torch.ao.quantization.DeQuantStub()

    def forward(self, x):
        x = self.quant(x)
        x = self.conv(x)
        x = self.bn(x)
        x = self.relu(x)
        x = self.dequant(x)
        return x

# create a model instance
model_fp32 = M()

# model must be set to eval for fusion to work
model_fp32.eval()

# attach a global qconfig, which contains information about what kind
# of observers to attach. Use 'x86' for server inference and 'qnnpack'
# for mobile inference. Other quantization configurations such as selecting
# symmetric or asymmetric quantization and MinMax or L2Norm calibration techniques
# can be specified here.
# Note: the old 'fbgemm' is still available but 'x86' is the recommended default
# for server inference.
# model_fp32.qconfig = torch.ao.quantization.get_default_qconfig('fbgemm')
model_fp32.qconfig = torch.ao.quantization.get_default_qat_qconfig('x86')

# fuse the activations to preceding layers, where applicable
# this needs to be done manually depending on the model architecture
model_fp32_fused = torch.ao.quantization.fuse_modules(model_fp32,
    [['conv', 'bn', 'relu']])

# Prepare the model for QAT. This inserts observers and fake_quants in
# the model needs to be set to train for QAT logic to work
# the model that will observe weight and activation tensors during calibration.
model_fp32_prepared = torch.ao.quantization.prepare_qat(model_fp32_fused.train())

# run the training loop (not shown)
num_train_batches = 20

# QAT takes time and one needs to train over a few epochs.
# Train and check accuracy after each epoch
for nepoch in range(8):
    train_one_epoch(qat_model, criterion, optimizer, data_loader, torch.device('cpu'), num_train_batches)
    if nepoch > 3:
        # Freeze quantizer parameters
        qat_model.apply(torch.ao.quantization.disable_observer)
    if nepoch > 2:
        # Freeze batch norm mean and variance estimates
        qat_model.apply(torch.nn.intrinsic.qat.freeze_bn_stats)

    # Check the accuracy after each epoch
    quantized_model = torch.ao.quantization.convert(qat_model.eval(), inplace=False)
    quantized_model.eval()
    top1, top5 = evaluate(quantized_model,criterion, data_loader_test, neval_batches=num_eval_batches)
    print('Epoch %d :Evaluation accuracy on %d images, %2.2f'%(nepoch, num_eval_batches * eval_batch_size, top1.avg))

fx 模式下量化:优点:自动融合算子-量化
PTQ-静态量化

import torch
from torch.ao.quantization import get_default_qconfig
from torch.ao.quantization.quantize_fx import prepare_fx, convert_fx
from torch.ao.quantization import QConfigMapping
float_model.eval()
# The old 'fbgemm' is still available but 'x86' is the recommended default.
qconfig = get_default_qconfig("x86")
qconfig_mapping = QConfigMapping().set_global(qconfig)
def calibrate(model, data_loader):
    model.eval()
    with torch.no_grad():
        for image, target in data_loader:
            model(image)
example_inputs = (next(iter(data_loader))[0]) # get an example input   
prepared_model = prepare_fx(float_model, qconfig_mapping, example_inputs)  # fuse modules and insert observers  融合算子,插入观测
calibrate(prepared_model, data_loader_test)  # run calibration on sample data
     记录校对
quantized_model = convert_fx(prepared_model)  # convert the calibrated model to a quantized model         #量化

具体见:https://pytorch.org/tutorials/prototype/fx_graph_mode_ptq_static.html
PTQ–动态量化

import torch
from torch.ao.quantization import default_dynamic_qconfig, QConfigMapping
# Note that this is temporary, we'll expose these functions to torch.ao.quantization after official releasee
from torch.quantization.quantize_fx import prepare_fx, convert_fx

float_model.eval()
# The old 'fbgemm' is still available but 'x86' is the recommended default.
qconfig = get_default_qconfig("x86")
qconfig_mapping = QConfigMapping().set_global(qconfig)
prepared_model = prepare_fx(float_model, qconfig_mapping, example_inputs)  # fuse modules and insert observers
# no calibration is required for dynamic quantization
quantized_model = convert_fx(prepared_model)  # convert the model to a dynamically quantized model

pytorch2 模式下量化
1. 训练后量化ptq模式

import torch

from torch._export import capture_pre_autograd_graph
class M(torch.nn.Module):
   def __init__(self):
      super().__init__()
      self.linear = torch.nn.Linear(5, 10)

   def forward(self, x):
      return self.linear(x)


example_inputs = (torch.randn(1, 5),)
m = M().eval()

# Step 1. program capture
# NOTE: this API will be updated to torch.export API in the future, but the captured
# result shoud mostly stay the same
m = capture_pre_autograd_graph(m, *example_inputs)         #获取动态图
# we get a model with aten ops


# Step 2. quantization
from torch.ao.quantization.quantize_pt2e import (
  prepare_pt2e,
  convert_pt2e,
)

from torch.ao.quantization.quantizer import (
  XNNPACKQuantizer,
  get_symmetric_quantization_config,
)
# backend developer will write their own Quantizer and expose methods to allow
# users to express how they
# want the model to be quantized       #获取量化器, int8
quantizer = XNNPACKQuantizer().set_global(get_symmetric_quantization_config())
m = prepare_pt2e(m, quantizer)

# calibration omitted
def calibrate(model, data_loader):
    model.eval()
    with torch.no_grad():
        for image, target in data_loader:
            model(image)
calibrate(m, example_inputs)

m = convert_pt2e(m)
# we have a model with aten ops doing integer computations when possible


########################扩展至c++
import torch._inductor.config as config
config.cpp_wrapper = True

with torch.no_grad():
    optimized_model = torch.compile(m)

    # Running some benchmark
    optimized_model(*example_inputs)


    res=optimized_model(example_inputs[0])
    print(res)

    # tensor([[0.0312, 0.0998, -0.7920, 0.0748, 0.7982, 0.1808, 0.4365, 0.0998,
    #          0.5800, 0.4428]])

QAT:量化感知训练

#简化基本步骤
import torch
from torch._export import capture_pre_autograd_graph
from torch.ao.quantization.quantize_pt2e import (
  prepare_qat_pt2e,
  convert_pt2e,
)
from torch.ao.quantization.quantizer import (
  XNNPACKQuantizer,
  get_symmetric_quantization_config,
)

class M(torch.nn.Module):
   def __init__(self):
      super().__init__()
      self.linear = torch.nn.Linear(5, 10)

   def forward(self, x):
      return self.linear(x)


example_inputs = (torch.randn(1, 5),)
m = M()

# Step 1. program capture
# NOTE: this API will be updated to torch.export API in the future, but the captured
# result shoud mostly stay the same
m = capture_pre_autograd_graph(m, *example_inputs)
# we get a model with aten ops

# Step 2. quantization-aware training
# backend developer will write their own Quantizer and expose methods to allow
# users to express how they want the model to be quantized
quantizer = XNNPACKQuantizer().set_global(get_symmetric_quantization_config())
m = prepare_qat_pt2e(m, quantizer)

# train omitted

m = convert_pt2e(m)
# we have a model with aten ops doing integer computations when possible

# move the quantized model to eval mode, equivalent to `m.eval()`
torch.ao.quantization.move_exported_model_to_eval(m)

https://pytorch.org/tutorials/prototype/pt2e_quant_qat.html

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

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

相关文章

2024年AWS云服务器选择哪个区域最好?

在选择2024年AWS云服务器区域时,您需要根据您的业务需求、目标用户群体的位置、数据合规性要求、延迟需求以及成本预算等因素综合考虑。以下是九河云针对不同需求的建议: 北美区域 优势:北美区域,尤其是弗吉尼亚北部&#xff0c…

工业和信息化部明确四方面举措优化信息通信行业营商环境

根据工业和信息化部6日发布的消息,该部门已正式下发《关于创新信息通信行业管理 优化营商环境的意见》。 此意见旨在通过四项主要措施优化行业管理制度和手段,以促进信息通信行业的高质量发展。 这些措施包括:持续改进高效、开放、统一的准…

vue项目部署在子路径中前端配置

vue.config.JS router/index.js或者是man.js

Docker-数据卷指令

数据卷挂载修改内容

Java批量查询CSDN质量分

文章目录 前言代码实现pom.xml实体类工具类质量分查询 效果开源仓库 前言 在CSDN平台申请“专家博主”、“优质创作者”等称号的时候,往往会对博客的质量分有一定的要求,这时候我们需要审视以往所发表的博客,找出质量分较低的博客&#xff0…

春秋云境 | 文件上传 | CVE-2022-23880

靶标介绍 taoCMS v3.0.2 文件管理处存在任意文件上传漏洞,攻击者可执行任意代码 开启靶场 点击下面的“管理” 发现是一个登录页面 右击点检查 发现默认账号和密码,登录进去的页面如图所示 创建一句话木马 找到了文件管理功能,新建一个 sh…

正则表达式测试工具

前言 正则表达式测试工具可供您输入正则表达式和测试文本,立即查看匹配结果. 下面是离线的HTML文件,同样可以提供相同的服务. 目录 使用说明 HTML代码 正则表达式的编写经验和方法 总结 使用说明 1.先将HTML代码存储成.html为后缀的文件; 2.然后用浏览器打开这个…

企业需要了解的平滑替代FTP 的文件传输软件知识

虽然传统的FTP曾经是行业的标准,但随着技术的发展,其局限性逐渐出现,促使各行业寻求更高效、更安全的解决方案。然而,面对市场上许多替代FTP软件,测试也消耗了人力和物质资源。今天,小编将分析市场上企业寻…

前端性能优化-图片优化

前言 本文总结 web 性能优化中图片优化的相关知识点。 一些背景知识 有损压缩(Lossy Compression) 有损压缩是一种图像压缩方法,通过牺牲一些图像细节以减小文件大小。JPEG 是一种常见的有损压缩图像格式。在压缩过程中,一些数…

火柴游戏(match)-2022蜀山区赛初中组第3题

题目描述 锤锤和柯西在玩火柴棒游戏,他们用火柴棒拼成不同的数字。规则如下: 这是火柴所形成10个数字的方式,每个数字所需的火柴数量不一样。现在给两人每人发N根火柴棒。锤锤要用所有火柴棒摆出其所能摆出最小的数,而柯西则需要…

【简历】吉林某985大学:Java简历指导,面试通过率低

注:为保证用户信息安全,姓名和学校等信息已经进行同层次变更,内容部分细节也进行了部分隐藏 简历说明 这是一份顶级985的25届Java简历。顶级985现在的目标只有一个,就是大厂秋招。那么这位同学跟211和普通同学比,优势还…

【JVM】Java内存区域图文详解

1.JVM运行时区域总览 Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域。 JVM运行时区域也成为Java内存区域。 在讨论Java内存模型时,通常将其分为线程共享区域和线程私有区域: 2.线程私有区域 2.1.程序计数器 程序计…

springboot船舶维保管理系统--论文源码调试讲解

第二章 相关技术 本次开发船舶维保管理系统使用的是Vue进行程序开发,船舶维保管理系统的数据信息选择MySQL数据库进行存放。 2.1 VUE介绍 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue…

Unity入门1——基本操作

VIew工具 选中View工具后,按住鼠标左键,即可实现拖拽 按住Alt鼠标右键,移动鼠标即可实现缩放(或使用鼠标滚轮) Move工具 选中移动工具,即可对界面中的物品进行移动。快捷键W 快速定位物体 在层级管理器中…

回溯分割+子集篇--代码随想录算法训练营第二十二天| 131.分割回文串,93.复原IP地址,78.子集,90.子集II

131.分割回文串 题目链接:. - 力扣(LeetCode) 讲解视频:131.分割回文串 题目描述: 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文串 。返回 s 所有可能的分割方案。 示例 …

2.3 Python 基本运算符

欢迎来到我的博客,很高兴能够在这里和您见面!欢迎订阅相关专栏: 工💗重💗hao💗:野老杂谈 ⭐️ 全网最全IT互联网公司面试宝典:收集整理全网各大IT互联网公司技术、项目、HR面试真题.…

C++ STL专题 list的讲解

目录 1.list的介绍和使用 1.1 list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 list element access 1.2.5 list modifiers 1.list的介绍和使用 1.1 list的介绍 1.list是可以在常数范围内任意位置进行插入和删除的序…

git系统学习

git系统学习 git命令行获取git 版本号 创建初始版本库创建git库初始化用户名和密码查看用户名和邮箱修改用户名和密码 将文件添加到版本库中删除暂存文件提交代码查看提交信息查看更加详细的信息查看提交差异版本库内文件的删除和重命名删除库里的文件重命名库里的文件 打标签查…

【RunnerGo】离线安装成功版本

目录 一、下载 二、解压安装包 三、修改安装配置 3.1 编辑修改安装参数(我没有改,默认安装即可) 3.2 安装目录结构说明 四、执行安装 五、检查服务并使用 六、访问 前言:最近在调研一个新工具,发现RunnerGo&…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《考虑通信-物理耦合的有源配网故障后协调恢复策略 》

本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…