【大模型学习 | BERT 量化学习 (1)】

BERT 情感分析

一、 数据集加载与模型训练

from transformers import BertTokenizer, BertForSequenceClassification, Trainer, TrainingArguments
from datasets import load_dataset
import torch
import numpy as np
from sklearn.metrics import accuracy_score
mode_name_or_path = '/root/autodl-tmp/bert-base-uncased'# 1. 加载 SST-2 数据集
dataset = load_dataset("glue", "sst2")
model = BertForSequenceClassification.from_pretrained("bert-base-uncased").to('cuda')
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
model.save_pretrained(mode_name_or_path)
tokenizer.save_pretrained(mode_name_or_path)
# 2. 数据预处理(tokenization)
def preprocess(example):return tokenizer(example["sentence"], truncation=True, padding="max_length", max_length=128)encoded_dataset = dataset.map(preprocess, batched=True)
encoded_dataset = encoded_dataset.rename_column("label", "labels")
encoded_dataset.set_format(type="torch", columns=["input_ids", "attention_mask", "labels"])# 4. 训练参数
training_args = TrainingArguments(output_dir="./output",# evaluation_strategy="epoch",per_device_train_batch_size=16,per_device_eval_batch_size=32,num_train_epochs=1,logging_dir="./logs",
)# 5. 定义指标
def compute_metrics(p):preds = np.argmax(p.predictions, axis=1)return {"accuracy": accuracy_score(p.label_ids, preds)}print(encoded_dataset["train"])
# 6. 启动训练器
trainer = Trainer(model=model,args=training_args,train_dataset=encoded_dataset["train"],eval_dataset=encoded_dataset["validation"],compute_metrics=compute_metrics,
)trainer.train()
trainer.evaluate()

二、HUGGING FACE 量化

from transformers import AutoModelForSequenceClassification, AutoTokenizer
import torch
from analyze import *# 1. 加载训练后BERT模型和tokenizer
model_name = "./output/checkpoint-2105/"
tokenizer = AutoTokenizer.from_pretrained(model_name)
original_model = AutoModelForSequenceClassification.from_pretrained(model_name).to('cuda')# 2. 8-bit量化加载模型
quantized_model = AutoModelForSequenceClassification.from_pretrained(model_name,device_map="auto",  # 自动分配到可用设备load_in_8bit=True,  # 启用8-bit量化
)
  • 比较模型大小

模型大小大幅度降低,降低了近3-4倍;

def print_model_size(model, model_name):param_size = 0for param in model.parameters():param_size += param.nelement() * param.element_size()buffer_size = 0for buffer in model.buffers():buffer_size += buffer.nelement() * buffer.element_size()size_all_mb = (param_size + buffer_size) / 1024**2print(f"{model_name} size: {size_all_mb:.3f}MB")print_model_size(original_model, "Original BERT")
print_model_size(quantized_model, "Quantized 8-bit BERT")
#Original BERT size: 417.655MB
#Quantized 8-bit BERT size: 127.269MB
  • 模型精度比较

在大小降低的同时,在验证集上的精度也大幅度降低;

def evaluate(model, dataset, labels):model.eval()preds = []with torch.no_grad():for i in range(0, len(dataset), 32):  # batch size = 32batch = dataset[i:i + 32]input_ids = batch["input_ids"].to(model.device)attention_mask = batch["attention_mask"].to(model.device)outputs = model(input_ids=input_ids, attention_mask=attention_mask)logits = outputs.logitsbatch_preds = torch.argmax(logits, dim=1).cpu()preds.extend(batch_preds.tolist())correct = sum([int(p == t) for p, t in zip(preds, labels)])acc = correct / len(labels)return acc
def preprocess(example):return tokenizer(example["sentence"], truncation=True, padding="max_length", max_length=128)from datasets import load_dataset
dataset = load_dataset("glue", "sst2")
val_dataset = dataset["validation"]encoded_val_dataset = val_dataset.map(preprocess, batched=True)
encoded_val_dataset.set_format(type="torch", columns=["input_ids", "attention_mask"])
labels = torch.tensor(val_dataset["label"])acc_fp32 = evaluate(original_model, encoded_val_dataset, labels)
acc_int8 = evaluate(quantized_model, encoded_val_dataset, labels)print(f"Original FP32 model accuracy: {acc_fp32:.4f}")
print(f"Quantized INT8 model accuracy: {acc_int8:.4f}")#Original FP32 model accuracy: 0.9300
#Quantized INT8 model accuracy: 0.5482
  • 量化分析

👉 这种量化方式虽然简单,但存在一个明显的问题,这是方式是 HuggingFace 基于 bitsandbytes 库 实现的轻量量化方式,背后用的是:

  1. bitsandbytes8-bit optimizers
  2. 权重是 FP16 或 INT8 存储,但不是 PyTorch 的量化张量(QTensor)
  3. 目的是节省 显存内存

🎯 为此,该方法无法通过调用tensor.q_scale() , tensor.q_zero_point()进行逐层分析

三、PYTORCH Eager Mode 量化

import torch
from transformers import AutoModelForSequenceClassification, AutoTokenizer# 1. 加载原始模型
model_name = "./output/checkpoint-2105/"
model = AutoModelForSequenceClassification.from_pretrained(model_name).eval()
tokenizer = AutoTokenizer.from_pretrained(model_name)# 2. 将模型移到 CPU(Eager 模式量化推荐在 CPU 上执行)
model.to('cpu')# 3. 准备量化配置 (动态量化)
quantized_model = torch.quantization.quantize_dynamic(model,{torch.nn.Linear},  # 指定要量化的模块类型dtype=torch.qint8   # 量化类型
)
  • 量化后大小比较,结果比huggingface量化方式大一点
# 大小比较
# Original BERT size: 417.655MB
# Quantized 8-bit BERT size: 127.269MB# 精度比较
# Original FP32 model accuracy: 0.9300
# Quantized INT8 model accuracy: 0.5482 不变

四、PYTORCH EXPORT 量化 (存在bug)

目前的这种量化方式还有bug存在,并且还找不到错误,希望有大哥帮助一下,主要的问题是模型可以成功量化,但是量化后的模型推理时会报错误,而且量化结果的大小也很奇怪:Original BERT size: 417.655MB ; Quantized 8-bit BERT size: 0.001MB

import torch
from torch.export import export
from torch.ao.quantization.quantize_pt2e import prepare_pt2e, convert_pt2e
from torch.ao.quantization.quantizer.xnnpack_quantizer import get_symmetric_quantization_config
from torch.ao.quantization.quantizer.x86_inductor_quantizer import X86InductorQuantizer
from transformers import AutoModelForSequenceClassification, AutoTokenizer
model_name = "./output/checkpoint-2105/"
# 1. 加载原始模型
model = AutoModelForSequenceClassification.from_pretrained(model_name).eval().cuda()
tokenizer = AutoTokenizer.from_pretrained(model_name)# 2. 准备样例输入
example = tokenizer("This movie is great!", return_tensors="pt", padding="max_length", max_length=128)
example = {k: v.cuda() for k, v in example.items()}
example_inputs = (example["input_ids"], example["attention_mask"])# 3. 导出模型
ep = export(model, args=example_inputs,dynamic_shapes=None)
gm = ep.graph_module# 4. 准备量化器
quantizer = X86InductorQuantizer()
quantizer.set_global(get_symmetric_quantization_config(is_per_channel=True))# 5. 插入 observer
prepared = prepare_pt2e(gm, quantizer)
quantity_model = convert_pt2e(prepared)# 报错信息forward() missing 203 required positional arguments: 'p_bert_embeddings_position_embeddings_weight', 'p_bert_embeddings_layernorm_weight', 'p_bert_embeddings_layernorm_bias',  

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

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

相关文章

用低通滤波优化串口或485 通信指示灯电路

常见的通信指示灯电路就是简单的把LED 连到TXD 和RXD 上,一有动静就闪一下。问题是,如果波特率很高,一次通信时间很短,相当于占空比很低,LED 闪烁的亮度就很弱,不容易观察。比如MODBUS 通信,波特…

【纯干货】调整word目录中的行距以及右对齐页码

1.问题展现 目录生成会遇到一些奇葩现象 所以到了展现技术力的时候了【doge】 2.解决word目录中的行距问题 选中目录中的文字-》段落 此时你可能勾选了图片中的一个以上,把他们都取消了, 由于一个目录的标题对应一个样式,第一个也可以取消 …

pandas 优雅处理值类型为list的列的csv读写问题

文章目录 直接存储join list 变成字符串存储json.dumps序列化存储以及json.loads反序列化读取总结 之所以分析这个问题,是因为读者在跟第三方数据供应商对接数据的时候,老是会遇到数据加载都会出错的问题,其中一个原因就是list类型数据没有正确储存,于是笔者在这篇文章里面详细…

一种解决 OpenWrt 安装 docker 之后局域网的设备之间无法互相访问通信的方法

文章目录 一、问题背景二、解决方案(方法一)修改全局设置的 转发( forward) 为 接受(ACCEPT)(方法二)设置 net.bridge.bridge-nf-call-iptables0 并将 docker 的容器网络设置为host …

Leetcode百题斩-贪心

贪心也是一个很有意思的专题,能遇到很多神奇的思路。 但这个专题,leetcode也没放Hard,果然是怕这种玄学专题上点难度大家罩不住。那就很快了,直接过 763. Partition Labels[Medium] 思路:将字母串分组,相…

基于多径信道的分集接收技术性能优化与仿真分析

基于多径信道的分集接收技术性能优化与仿真分析 一、多径信道建模与仿真 1. 多径信道建模(MATLAB实现) classdef MultipathChannel < handlepropertiesSampleRate = 1e6; % 采样率 (Hz)MaxDoppler = 100; % 最大多普勒频移 (Hz)DelayVector = [0

LeetCode 713.乘积小于K的子数组

给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回子数组内所有元素的乘积严格小于 k 的连续子数组的数目。 示例 1&#xff1a; 输入&#xff1a;nums [10,5,2,6], k 100 输出&#xff1a;8 解释&#xff1a;8 个乘积小于 100 的子数组分别为&#xff1a;[10]、[5…

打破网络安全孤岛:实现防御数据协作

作者&#xff1a;来自 Elastic Crossley McEwen, Oksana Abramovych 现代网络战场不再受组织边界的限制。在各类防御网络中&#xff0c;关键的结构化、非结构化和半结构化数据分布在不同的专业环境中&#xff0c;形成孤岛 —— 从机密情报系统到作战指挥平台&#xff0c;再到战…

给定一个没有重复元素的数组,写出生成这个数组的MaxTree的函数

题目&#xff1a; 给定一个没有重复元素的数组arr&#xff0c;写出生成这个数组的MaxTree的 函数&#xff0c;要求如果数组长度为N&#xff0c;则时间复杂度为O(N)、额外空间复杂度 为O(N)。 一个数组的MaxTree定义如下。 ● 数组必须没有重复元素。 ● MaxTree是一棵二叉…

iOS 抓包实战:时间戳偏差导致的数据同步异常排查记录

“这条数据不是我填的”“我的更新被覆盖了”“两个设备显示不一致”——这些是产品上线后最令人头疼的反馈。 最近我们在一次用户同步问题排查中&#xff0c;发现表面是“数据丢失”问题&#xff0c;实则是多端数据提交时间戳处理不一致&#xff0c;导致后台认为老数据为新&a…

一款支持多日志器、多级别、多落地方式的同异步日志系统

文章目录 简介项目特点项目实现基础功能模块实现文件操作以及日期时间获取日志等级日志信息描述 异步功能模块实现缓冲区实现异步线程实现 核心功能模块实现日志格式解析落地操作实现日志器实现 测试测试环境测试参数测试结果性能分析 附件 简介 在现代软件开发与系统运维领域…

加固笔记本在户外勘探行业的应用:探索与科技的融合

在自然资源勘探、地质调查、石油天然气开发、矿产资源测绘等户外勘探行业中&#xff0c;作业环境常常复杂多变&#xff1a;风沙漫天的戈壁、雨雪交加的山区、湿热潮湿的丛林&#xff0c;甚至是极寒与高温并存的极端气候条件。面对这些挑战&#xff0c;普通的办公设备早已无法胜…

MySQL 连接指定端口后,为什么实际仍是 3306?

文章目录 MySQL 连接指定端口后&#xff0c;为什么实际仍是 3306&#xff1f;问题现象复现原因分析没有指定 -h&#xff0c;默认走的是本地 Unix Socket多实例环境中未显式指定目标地址 正确的连接方法方法一&#xff1a;添加 -h 127.0.0.1方法二&#xff1a;添加 --protocolTC…

【Android当用户两次打断息屏操作后,屏幕将会在10分钟内无法熄灭并持续点亮(关闭Android13新增的dim功能)】

UndimDetectorWakeLock持锁导致屏幕不灭问题处理SOP 问题描述 在Android T版本中&#xff0c;系统新增了SCREEN_BRIGHT_WAKE_LOCK&#xff08;UndimDetectorWakeLock&#xff09;机制。当设备处于低亮度&#xff08;dim&#xff09;状态时&#xff0c;用户两次打断屏幕熄灭操…

Tailwind CSS自定义用法

文章目录 前言✅ 一、集成 Tailwind CSS 到 React 项目1. 安装依赖2. 配置 tailwind.config.js3. 创建全局样式文件&#xff08;如 src/index.css&#xff09;tailwind base;tailwind components;tailwind utilities; 4. 在 main.tsx 或 main.jsx 中引入样式 ✅ 二、自定义样式…

linux面试常考

常用指令 常见题

Spring Boot 2.2.6调用DeepSeek API并通过SSE将流式响应推送给前端的完整实现

1. 添加依赖 (pom.xml) <dependencies><!-- Spring Boot Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- SSE 支持 --><depe…

LM1117-ADJ 简单介绍

LM1117-ADJ是一款可调输出电压的低压差线性稳压器&#xff08;LDO&#xff09;&#xff0c;具有以下关键特性和应用要点&#xff1a; 核心特性 可调输出电压 通过外部分压电阻&#xff08;R1和R2&#xff09;调节输出电压&#xff0c;范围为1.25V至13.8V。输出电压公式&#…

知名流体控制解决方案供应商“永盛科技”与商派ShopeX达成B2B商城项目合作

2025年6月&#xff0c;全球知名的工业流体控制解决方案服务商——永盛科技&#xff08;股票&#xff1a;874497&#xff09;&#xff0c;与商派ShopeX正式达成B2B商城项目合作。 此次合作将共同推动永盛科技B2B业务的数字化变革&#xff0c;提高B2B业务运营效率&#xff0c;同…

jvm简单八股

1、jvm中内存分为那几个区域&#xff0c;1.7和1.8 jvm 中主要有 程序计数器、虚拟机栈、本地方法栈、堆、方法区、直接内存。 线程私有的有&#xff1a;程序计数器、虚拟机栈、本地方法栈 线程共有的有&#xff1a;堆、方法区、直接内存 堆空间又可以分为&#xff1a;新时代、…