doc
: Dynamic Quantization — PyTorch Tutorials 1.11.0+cu102 documentation
2022年5月24日
tag : 翻译学习
topic : Pytorch 量化
在本配方中,将介绍如何利用动态量化来加速 LSTM 风格的 递归神经网络 上的推理。
减小了模型权重的大小并加快了模型的执行速度。
在设计神经网络时,进行许多权衡。在模型开发和训练期间,可以更改递归神经网络中的层数和参数数,并根据模型大小和/或模型延迟或吞吐量权衡准确性。此类更改可能需要大量时间和计算资源,因为正在迭代模型训练。量化提供了一种在训练完成后使用已知模型在性能和模型准确性之间进行类似权衡的方法。
可在单个会话中进行尝试,肯定可以看到模型大小显著减小,并且可以在不损失很多准确性的情况下显著减少延迟。
量化网络意味着将其转换为对权重和/或激活使用精度较低的整数表示。这样可以降低模型大小,并允许在 CPU 或 GPU 上使用更高吞吐量的数学运算。
从浮点值转换为整数值时,实质上是将浮点值乘以某个比例因子,并将结果舍入为整数。各种量化方法的不同之处在于它们确定该比例因子的方式。
此处所述的动态量化的关键思想是,将根据运行时观察到的数据范围动态确定激活的比例因子。这可确保“调整”比例因子,以便保留有关每个观测数据集的尽可能多的信号。
另一方面,模型参数在模型转换期间是已知的,它们会提前转换并以INT8形式存储。
量化模型中的算术是使用矢量化的INT8指令完成的。通常使用 INT16 或 INT32 进行累积,以避免溢出。如果量化下一层或转换为FP32以进行输出,则此高精度值将缩小到INT8。
**动态量化相对不需要调整参数,**这使得它非常适合作为将LSTM模型转换为部署的标准部分添加到生产pipeline中。
注意
此处所采用方法的限制
此配方简要介绍了 PyTorch 中的动态量化功能以及使用它的工作流程。我们的重点是解释用于转换模型的特定函数。为了简洁明了,我们将进行一些重大的简化
将看到如何完成动态量化,并能够看到内存使用和延迟时间的潜在减少。证明该技术可以在经过训练的LSTM上保持高水平的模型准确性,留给更高级的教程。如果想立即进行更高级的处理,请继续学习高级动态量化教程 advanced dynamic quantization tutorial.
这个食谱有5个步骤。
这是为配方的其余部分设置的简单代码。
在此处导入的唯一模块是 torch.quantization,其中包括 PyTorch 的量化运算符和转换函数。 我们还定义了一个非常简单的 LSTM 模型并设置了一些输入。
# import the modules used here in this recipe
import torch
import torch.quantization
import torch.nn as nn
import copy
import os
import time
# define a very, very simple LSTM for demonstration purposes
# in this case, we are wrapping nn.LSTM, one layer, no pre or post processing
# inspired by
# https://pytorch.org/tutorials/beginner/nlp/sequence_models_tutorial.html, by Robert Guthrie
# and https://pytorch.org/tutorials/advanced/dynamic_quantization_tutorial.html
class lstm_for_demonstration(nn.Module):
"""Elementary Long Short Term Memory style model which simply wraps nn.LSTM
Not to be used for anything other than demonstration.
"""
def __init__(self,in_dim,out_dim,depth):
super(lstm_for_demonstration,self).__init__()
self.lstm = nn.LSTM(in_dim,out_dim,depth)
def forward(self,inputs,hidden):
out,hidden = self.lstm(inputs,hidden)
return out, hidden
torch.manual_seed(29592) # set the seed for reproducibility
#shape parameters
model_dimension=8
sequence_length=20
batch_size=1
lstm_depth=1
# random data for input
inputs = torch.randn(sequence_length,batch_size,model_dimension)
# hidden is actually is a tuple of the initial hidden state and the initial cell state
hidden = (torch.randn(lstm_depth,batch_size,model_dimension), torch.randn(lstm_depth,batch_size,model_dimension))
现在我们进入有趣的部分。首先创建一个名为float_lstm模型实例,然后对其进行量化。将使用
torch.quantization.quantize_dynamic()
此处的函数(see documentation) 获取模型,然后是我们希望量化的子模块的列表(如果它们出现),然后是我们的目标数据类型。 此函数将原始模型的量化版本作为新模块返回。
这就是它所需要的一切。
# here is our floating point instance
float_lstm = lstm_for_demonstration(model_dimension, model_dimension,lstm_depth)
# this is the call that does the work
quantized_lstm = torch.quantization.quantize_dynamic(
float_lstm, {nn.LSTM, nn.Linear}, dtype=torch.qint8
)
# show the changes that were made
print('Here is the floating point version of this module:')
print(float_lstm)
print('')
print('and now the quantized version:')
print(quantized_lstm)
现在已经量化好了模型带来了什么好处?
def print_size_of_model(model, label=""):
torch.save(model.state_dict(), "temp.p")
size=os.path.getsize("temp.p")
print("model: ",label,' \t','Size (KB):', size/1e3)
os.remove('temp.p')
return size
# compare the sizes
f=print_size_of_model(float_lstm,"fp32")
q=print_size_of_model(quantized_lstm,"int8")
print("{0:.2f} times smaller".format(f/q))
正如将看到的,这个超级简单网络的量化版本运行得更快。这通常适用于更复杂的网络,但正如他们所说,““你的旅费可能会 不同”,这取决于许多因素,包括模型的结构和您正在运行的硬件。
# compare the performance
print("Floating point FP32")
# %timeit float_lstm.forward(inputs, hidden)
print("Quantized INT8")
# %timeit quantized_lstm.forward(inputs,hidden)
不打算在这里详细对比准确性,因为我们使用的是随机初始化的网络,而不是经过适当训练的网络。但是,我认为值得快速证明的是,量化网络确实产生了与原始网络“in the same ballpark” 的输出张量。
更详细的分析,请参阅本配方末尾引用的更高级教程。
# run the float model
out1, hidden1 = float_lstm(inputs, hidden)
mag1 = torch.mean(abs(out1)).item()
print('mean absolute value of output tensor values in the FP32 model is {0:.5f} '.format(mag1))
# run the quantized model
out2, hidden2 = quantized_lstm(inputs, hidden)
mag2 = torch.mean(abs(out2)).item()
print('mean absolute value of output tensor values in the INT8 model is {0:.5f}'.format(mag2))
# compare them
mag3 = torch.mean(abs(out1-out2)).item()
print('mean absolute value of the difference between the output tensors is {0:.5f} or {1:.2f} percent'.format(mag3,mag3/mag1*100))
解释了什么是动态量化,它带来了什么好处,并且使用该函数快速量化了一个简单的LSTM模型。
torch.quantization.quantize_dynamic()
更多信息 : LSTM Word语言模型教程中的(测试版)动态量化。
Quantization API Documentaion
(beta) Dynamic Quantization on BERT
(beta) Dynamic Quantization on an LSTM Word Language Model
ps://pytorch.org/tutorials/intermediate/dynamic_quantization_bert_tutorial.html)
(beta) Dynamic Quantization on an LSTM Word Language Model
Introduction to Quantization on PyTorch