NLP(六十七)BERT模型训练后动态量化(PTDQ)

这篇具有很好参考价值的文章主要介绍了NLP(六十七)BERT模型训练后动态量化(PTDQ)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  本文将会介绍BERT模型训练后动态量化(Post Training Dynamic Quantization,PTDQ)。

量化

  在深度学习中,量化(Quantization)指的是使用更少的bit来存储原本以浮点数存储的tensor,以及使用更少的bit来完成原本以浮点数完成的计算。这么做的好处主要有如下几点:

  • 更少的模型体积,接近4倍的减少
  • 可以更快地计算,由于更少的内存访问和更快的int8计算,可以快2~4倍

  PyTorch中的模型参数默认以FP32精度储存。对于量化后的模型,其部分或者全部的tensor操作会使用int类型来计算,而不是使用量化之前的float类型。当然,量化还需要底层硬件支持,x86 CPU(支持AVX2)、ARM CPU、Google TPU、Nvidia Volta/Turing/Ampere、Qualcomm DSP这些主流硬件都对量化提供了支持。

NLP(六十七)BERT模型训练后动态量化(PTDQ),NLP,自然语言处理,bert,人工智能

PTDQ

  PyTorch对量化的支持目前有如下三种方式:

  • Post Training Dynamic Quantization:模型训练完毕后的动态量化
  • Post Training Static Quantization:模型训练完毕后的静态量化
  • QAT (Quantization Aware Training):模型训练中开启量化

  本文仅介绍Post Training Dynamic Quantization(PTDQ)
  对训练后的模型权重执行动态量化,将浮点模型转换为动态量化模型,仅对模型权重进行量化,偏置不会量化。默认情况下,仅对Linear和RNN变体量化 (因为这些layer的参数量很大,收益更高)。

torch.quantization.quantize_dynamic(model, qconfig_spec=None, dtype=torch.qint8, mapping=None, inplace=False)

参数解释:

  • model:模型(默认为FP32)
  • qconfig_spec:
  1. 集合:比如: qconfig_spec={nn.LSTM, nn.Linear} 。列出要量化的神经网络模块。
  2. 字典: qconfig_spec = {nn.Linear: default_dynamic_qconfig, nn.LSTM: default_dynamic_qconfig}
  • dtype: float16 或 qint8
  • mapping:就地执行模型转换,原始模块发生变异
  • inplace:将子模块的类型映射到需要替换子模块的相应动态量化版本的类型

例子:

# -*- coding: utf-8 -*-
# 动态量化模型,只量化权重
import torch
from torch import nn


class DemoModel(torch.nn.Module):
    def __init__(self):
        super(DemoModel, self).__init__()
        self.conv = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=1)
        self.relu = nn.ReLU()
        self.fc = torch.nn.Linear(2, 2)

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


if __name__ == "__main__":
    model_fp32 = DemoModel()
    # 创建一个量化的模型实例
    model_int8 = torch.quantization.quantize_dynamic(model=model_fp32,  # 原始模型
                                                     qconfig_spec={torch.nn.Linear},  # 要动态量化的算子
                                                     dtype=torch.qint8)  # 将权重量化为:qint8

    print(model_fp32)
    print(model_int8)

    # 运行模型
    input_fp32 = torch.randn(1, 1, 2, 2)
    output_fp32 = model_fp32(input_fp32)
    print(output_fp32)

    output_int8 = model_int8(input_fp32)
    print(output_int8)

输出结果如下:

DemoModel(
  (conv): Conv2d(1, 1, kernel_size=(1, 1), stride=(1, 1))
  (relu): ReLU()
  (fc): Linear(in_features=2, out_features=2, bias=True)
)
DemoModel(
  (conv): Conv2d(1, 1, kernel_size=(1, 1), stride=(1, 1))
  (relu): ReLU()
  (fc): DynamicQuantizedLinear(in_features=2, out_features=2, dtype=torch.qint8, qscheme=torch.per_tensor_affine)
)
tensor([[[[0.3120, 0.3042],
          [0.3120, 0.3042]]]], grad_fn=<AddBackward0>)
tensor([[[[0.3120, 0.3042],
          [0.3120, 0.3042]]]])

模型量化策略

  当前,由于量化算子的覆盖有限,因此,对于不同的深度学习模型,其量化策略不同,见下表:

模型 量化策略 原因
LSTM/RNN Dynamic Quantization 模型吞吐量由权重的计算/内存带宽决定
BERT/Transformer Dynamic Quantization 模型吞吐量由权重的计算/内存带宽决定
CNN Static Quantization 模型吞吐量由激活函数的内存带宽决定
CNN Quantization Aware Training 模型准确率不能由Static Quantization获取的情况

   下面对BERT模型进行训练后动态量化,分析模型在量化前后,推理效果和推理性能的变化。

实验

   我们使用的训练后的模型为中文文本分类模型,其训练过程可以参考文章:NLP(六十六)使用HuggingFace中的Trainer进行BERT模型微调 。
   训练后的BERT模型动态量化实验的设置如下:

  1. base model: bert-base-chinese
  2. CPU info: x86-64, Intel® Core™ i5-10210U CPU @ 1.60GHz
  3. batch size: 1
  4. thread: 1

   具体的实验过程如下

  • 加载模型及tokenizer
import torch
from transformers import AutoModelForSequenceClassification

MAX_LENGTH = 128
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
checkpoint = f"./sougou_test_trainer_{MAX_LENGTH}/checkpoint-96"
model = AutoModelForSequenceClassification.from_pretrained(checkpoint).to(device)
from transformers import AutoTokenizer, DataCollatorWithPadding

tokenizer = AutoTokenizer.from_pretrained(checkpoint)
  • 测试数据集
import pandas as pd

test_df = pd.read_csv("./data/sougou/test.csv")

test_df.head()
text label
0 届数比赛时间比赛地点参加国家和地区冠军亚军决赛成绩第一届1956-1957英国11美国丹麦6... 0
1 商品属性材质软橡胶带加浮雕工艺+合金彩色队徽吊牌规格162mm数量这一系列产品不限量发行图案... 0
2 今天下午,沈阳金德和长春亚泰队将在五里河相遇。在这两支球队中沈阳籍球员居多,因此这场比赛实际... 0
3 本报讯中国足协准备好了与特鲁西埃谈判的合同文本,也在北京给他预订好了房间,但特鲁西埃爽约了!... 0
4 网友点击发表评论祝贺中国队夺得五连冠搜狐体育讯北京时间5月6日,2006年尤伯杯羽毛球赛在日... 0
  • 量化前模型的推理时间及评估指标
import numpy as np
import time

s_time = time.time()
true_labels, pred_labels = [], [] 
for i, row in test_df.iterrows():
    row_s_time = time.time()
    true_labels.append(row["label"])
    encoded_text = tokenizer(row['text'], max_length=MAX_LENGTH, truncation=True, padding=True, return_tensors='pt').to(device)
    # print(encoded_text)
    logits = model(**encoded_text)
    label_id = np.argmax(logits[0].detach().cpu().numpy(), axis=1)[0]
    pred_labels.append(label_id)
    print(i, (time.time() - row_s_time)*1000, label_id)

print("avg time: ", (time.time() - s_time) * 1000 / test_df.shape[0])
0 229.3872833251953 0
100 362.0314598083496 1
200 311.16747856140137 2
300 324.13792610168457 3
400 406.9099426269531 4
avg time:  352.44047810332944
from sklearn.metrics import classification_report

print(classification_report(true_labels, pred_labels, digits=4))
              precision    recall  f1-score   support

           0     0.9900    1.0000    0.9950        99
           1     0.9691    0.9495    0.9592        99
           2     0.9900    1.0000    0.9950        99
           3     0.9320    0.9697    0.9505        99
           4     0.9895    0.9495    0.9691        99

    accuracy                         0.9737       495
   macro avg     0.9741    0.9737    0.9737       495
weighted avg     0.9741    0.9737    0.9737       495
  • 设置量化后端
# 模型量化
cpu_device = torch.device("cpu")
torch.backends.quantized.supported_engines
['none', 'onednn', 'x86', 'fbgemm']
torch.backends.quantized.engine = 'x86'
  • 量化后模型的推理时间及评估指标
# 8-bit 量化
quantized_model = torch.quantization.quantize_dynamic(
    model, {torch.nn.Linear}, dtype=torch.qint8
).to(cpu_device)
q_s_time = time.time()
q_true_labels, q_pred_labels = [], [] 

for i, row in test_df.iterrows():
    row_s_time = time.time()
    q_true_labels.append(row["label"])
    encoded_text = tokenizer(row['text'], max_length=MAX_LENGTH, truncation=True, padding=True, return_tensors='pt').to(cpu_device)
    logits = quantized_model(**encoded_text)
    label_id = np.argmax(logits[0].detach().numpy(), axis=1)[0]
    q_pred_labels.append(label_id)
    print(i, (time.time() - row_s_time) * 1000, label_id)
    
print("avg time: ", (time.time() - q_s_time) * 1000 / test_df.shape[0])
0 195.47462463378906 0
100 247.33805656433105 1
200 219.41304206848145 2
300 206.44831657409668 3
400 187.4992847442627 4
avg time:  217.63229466447928
from sklearn.metrics import classification_report

print(classification_report(q_true_labels, q_pred_labels, digits=4))
              precision    recall  f1-score   support

           0     0.9900    1.0000    0.9950        99
           1     0.9688    0.9394    0.9538        99
           2     0.9900    1.0000    0.9950        99
           3     0.9320    0.9697    0.9505        99
           4     0.9896    0.9596    0.9744        99

    accuracy                         0.9737       495
   macro avg     0.9741    0.9737    0.9737       495
weighted avg     0.9741    0.9737    0.9737       495
  • 量化前后模型大小对比
import os

def print_size_of_model(model):
    torch.save(model.state_dict(), "temp.p")
    print("Size (MB): ", os.path.getsize("temp.p")/1e6)
    os.remove("temp.p")

print_size_of_model(model)
print_size_of_model(quantized_model)
Size (MB):  409.155273
Size (MB):  152.627621

  量化后端(Quantization backend)取决于CPU架构,不同计算机的CPU架构不同,因此,默认的动态量化不一定在所有的CPU上都能生效,需根据自己计算机的CPU架构设置好对应的量化后端。另外,不同的量化后端也有些许差异。Linux服务器使用uname -a可查看CPU信息。
  重复上述实验过程,以模型的最大输入长度为变量,取值为128,256,384,每种情况各做3次实验,结果如下:

实验 最大长度 量化前平均推理时间(ms) 量化前weighted F1值 量化前平均推理时间(ms) 量化前weighted F1值
实验1 384 1066 0.9797 686 0.9838
实验2 384 1047.6 0.9899 738.1 0.9879
实验3 384 1020.9 0.9817 714.0 0.9838
实验1 256 668.7 0.9717 431.4 0.9718
实验2 256 675.1 0.9717 449.9 0.9718
实验3 256 656.0 0.9717 446.5 0.9718
实验1 128 335.8 0.9737 200.5 0.9737
实验2 128 336.5 0.9737 227.2 0.9737
实验3 128 352.4 0.9737 217.6 0.9737

  综上所述,对于训练后的BERT模型(文本分类模型)进行动态量化,其结论如下:

  • 模型推理效果:量化前后基本相同,量化后略有下降
  • 模型推理时间:量化后平均提速约1.52倍

总结

  本文介绍了量化基本概念,PyTorch模型量化方式,以及对BERT模型训练后进行动态量化后在推理效果和推理性能上的实验。
  本文项目已开源至Github项目:https://github.com/percent4/dynamic_quantization_on_bert 。
  本人已开通个人博客网站,网址为:https://percent4.github.io/ ,欢迎大家访问~

  欢迎关注我的公众号NLP奇幻之旅,原创技术文章第一时间推送。

NLP(六十七)BERT模型训练后动态量化(PTDQ),NLP,自然语言处理,bert,人工智能

  欢迎关注我的知识星球“自然语言处理奇幻之旅”,笔者正在努力构建自己的技术社区。文章来源地址https://www.toymoban.com/news/detail-698485.html

NLP(六十七)BERT模型训练后动态量化(PTDQ),NLP,自然语言处理,bert,人工智能

到了这里,关于NLP(六十七)BERT模型训练后动态量化(PTDQ)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 带你熟悉NLP预训练模型:BERT

    本文分享自华为云社区《【昇思技术公开课笔记-大模型】Bert理论知识》,作者: JeffDing。 语言模型演变经历的几个阶段 word2vec/Glove将离散的文本数据转换为固定长度的静态词向量,后根据下游任务训练不同的语言模型 ELMo预训练模型将文本数据结合上下文信息,转换为动态

    2024年01月22日
    浏览(71)
  • 【NLP】1、BERT | 双向 transformer 预训练语言模型

    论文:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding 出处:Google 在 BERT 之前的语言模型如 GPT 都是单向的模型,但 BERT 认为虽然单向(从左到右预测)预测任务符合语言模型的建模过程,但对一些语言理解任务不太友好,因为要理解一句话说的是什么意思的话

    2024年02月12日
    浏览(43)
  • 自然语言处理 Paddle NLP - 预训练语言模型及应用

    基础 自然语言处理(NLP) 自然语言处理PaddleNLP-词向量应用展示 自然语言处理(NLP)-前预训练时代的自监督学习 自然语言处理PaddleNLP-预训练语言模型及应用 自然语言处理PaddleNLP-文本语义相似度计算(ERNIE-Gram) 自然语言处理PaddleNLP-词法分析技术及其应用 自然语言处理Pa

    2024年02月08日
    浏览(76)
  • 2023年!自然语言处理(NLP)10 大预训练模型

    来源: AINLPer 公众号 (每日干货分享!!) 编辑: ShuYini 校稿: ShuYini 时间: 2022-10-23 语言模型是构建NLP应用程序的关键。现在人们普遍相信基于预训练模型来构建NLP语言模型是切实有效的方法。随着疫情阴霾的散去,相信NLP技术会继续渗透到众多行业中。在此过程中,肯定有很

    2024年02月16日
    浏览(57)
  • 自然语言处理 Paddle NLP - 基于预训练模型完成实体关系抽取

    基础 自然语言处理(NLP) 自然语言处理PaddleNLP-词向量应用展示 自然语言处理(NLP)-前预训练时代的自监督学习 自然语言处理PaddleNLP-预训练语言模型及应用 自然语言处理PaddleNLP-文本语义相似度计算(ERNIE-Gram) 自然语言处理PaddleNLP-词法分析技术及其应用 自然语言处理Pa

    2024年02月10日
    浏览(48)
  • 7个顶级开源数据集来训练自然语言处理(NLP)和文本模型

    推荐:使用 NSDT场景编辑器快速助你搭建可二次编辑的3D应用场景 NLP现在是一个令人兴奋的领域,特别是在像AutoNLP这样的用例中,但很难掌握。开始使用NLP的主要问题是缺乏适当的指导和该领域的过度广度。很容易迷失在各种论文和代码中,试图吸收所有内容。 要意识到的是

    2024年02月13日
    浏览(57)
  • 自然语言处理从入门到应用——动态词向量预训练:双向语言模型

    分类目录:《自然语言处理从入门到应用》总目录 对于给定的一段输入文本 w 1 w 2 ⋯ w n w_1w_2cdots w_n w 1 ​ w 2 ​ ⋯ w n ​ ,双向语言模型从前向(从左到右)和后向(从右到左)两个方向同时建立语言模型。这样做的好处在于,对于文本中任一时刻的词 w t w_t w t ​ ,可以

    2024年02月10日
    浏览(48)
  • 自然语言处理(八):预训练BERT

    BERT(Bidirectional Encoder Representations from Transformers)是一种预训练的自然语言处理模型,由Google于2018年提出。它是基于Transformer模型架构的深度双向(双向指同时考虑上下文信息)表示学习模型。 BERT的目标是通过在大规模文本语料上进行自监督学习来学习通用的语言表示。在预

    2024年02月09日
    浏览(49)
  • 自然语言处理(NLP)一直是人工智能领域的一项重要任务,其涉及到从文本中提取特征、组织数据、训练模型等诸多复杂任务。如何有效地进行文本理解和分析?

    作者:禅与计算机程序设计艺术 自然语言处理(NLP)一直是人工智能领域的一项重要任务,其涉及到从文本中提取特征、组织数据、训练模型等诸多复杂任务。如何有效地进行文本理解和分析,成为一个重要研究课题。近年来,随着计算能力的提升和硬件性能的增强,大规模

    2024年02月09日
    浏览(66)
  • 自然语言处理(NLP) - 前预训练时代的自监督学习

    基础 自然语言处理(NLP) 自然语言处理PaddleNLP-词向量应用展示 自然语言处理(NLP)-前预训练时代的自监督学习 自然语言处理PaddleNLP-预训练语言模型及应用 自然语言处理PaddleNLP-文本语义相似度计算(ERNIE-Gram) 自然语言处理PaddleNLP-词法分析技术及其应用 自然语言处理Pa

    2024年02月08日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包