[大模型]大语言模型量化方法对比:GPTQ、GGUF、AWQ

在过去的一年里,大型语言模型(llm)有了飞速的发展,在本文中,我们将探讨几种(量化)的方式,除此以外,还会介绍分片及不同的保存和压缩策略。

说明:每次加载LLM示例后,建议清除缓存,以防止出现OutOfMemory错误。

del model, tokenizer, pipe import torch 
torch.cuda.empty_cache()

如果在jupyter中无法释放显存,请重启这个jupyter notebook。

模型加载

加载LLM的最直接、最普通的方式是通过 Transformers。HuggingFace已经创建了一个套件,我们能够直接使用

pip install git+https://github.com/huggingface/transformers.git 
pip install accelerate bitsandbytes xformers

安装完成后,我们可以使用以下管道轻松加载LLM:

from torch import bfloat16
from transformers import pipeline# Load in your LLM without any compression tricks
pipe = pipeline("text-generation", model="HuggingFaceH4/zephyr-7b-beta", torch_dtype=bfloat16, device_map="auto"
)

我们这里使用zephyr-7b-beta作为示例

这种加载LLM的方法通常不会执行任何压缩技巧。我们来做个使用的示例

messages = [{"role": "system","content": "You are a friendly chatbot.",},{"role": "user", "content": "Tell me a funny joke about Large Language Models."},
]
prompt = pipe.tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True
)

使用内部提示模板生成的提示是这样构造的:

 

然后,我们可将提示传递给LLM来生成答案:

outputs = pipe(prompt, max_new_tokens=256, do_sample=True, temperature=0.1, top_p=0.95
)
print(outputs[0]["generated_text"])

这是一个最直接的使用流程,但是对于纯推理,这种方法效率是最低的,因为在没有任何压缩或量化策略的情况下加载整个模型。

分片

在我们进入量化策略之前,我们先介绍一个前置的方法:分片。通过分片可以将模型分割成小块,每个分片包含模型的较小部分,通过在不同设备上分配模型权重来解决GPU内存限制。

虽然它没有任何的压缩和量化,但是这种方法算是一个最简单的加载大模型的方案。

比如Zephyr-7B-β,实际上已经分片了!如果进入模型并点击“Files and versions”链接,可以看到模型被分成了8个部分。

 

 

模型的分片非常简单,可以直接使用Accelerate 包:

from accelerate import Accelerator# Shard our model into pieces of 1GB
accelerator = Accelerator()
accelerator.save_model(model=pipe.model, save_directory="/content/model", max_shard_size="4GB"
)

这样将模型分成4GB的分片

量化

大型语言模型由一堆权重和激活表示。这些值通常由通常的32位浮点(float32)数据类型表示。

比特的数量告诉你它可以表示多少个值。Float32可以表示1.18e-38和3.4e38之间的值,相当多的值!比特数越少,它能表示的值就越少。

如果我们选择较低的位大小,那么模型就会变得不那么准确,但它表示更少的值,从而降低其大小和内存需求。

 

量化是指将LLM从其原始Float32表示转换为更小的表示。我们不希望简单地使用较小的位变体,而是希望在不丢失太多信息的情况下将较大的位表示映射到较小的位。

所以一般情况下,我们经常使用一种名为4bit-NormalFloat (NF4)的新格式来实现这一点。这个数据类型做了一些特殊的技巧,以便有效地表示更大的位数据类型。它包括三个步骤:

归一化:将模型的权重归一化,以便我们期望权重落在一定范围内。这允许更有效地表示更常见的值。

量化:将权重量化为4位。在NF4中,量化级别相对于归一化权重是均匀间隔的,从而有效地表示原始的32位权重。

去量化:虽然权重以4位存储,但它们在计算期间被去量化,从而在推理期间提高性能。

我们可以直接使用Bitsandbytes库进行量化操作:

from transformers import BitsAndBytesConfig
from torch import bfloat16# Our 4-bit configuration to load the LLM with less GPU memory
bnb_config = BitsAndBytesConfig(load_in_4bit=True,  # 4-bit quantizationbnb_4bit_quant_type='nf4',  # Normalized float 4bnb_4bit_use_double_quant=True,  # Second quantization after the firstbnb_4bit_compute_dtype=bfloat16  # Computation type
)

上面的配置指定要使用的量化级别。比如4位量化表示权重,但用16位进行推理。

然后在管道中加载模型就很简单了:

from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline# Zephyr with BitsAndBytes Configuration
tokenizer = AutoTokenizer.from_pretrained("HuggingFaceH4/zephyr-7b-alpha")
model = AutoModelForCausalLM.from_pretrained("HuggingFaceH4/zephyr-7b-alpha",quantization_config=bnb_config,device_map='auto',
)# Create a pipeline
pipe = pipeline(model=model, tokenizer=tokenizer, task='text-generation')

接下来使用与之前相同的提示:

outputs = pipe(prompt, max_new_tokens=256, do_sample=True, temperature=0.7, top_p=0.95
)
print(outputs[0]["generated_text"])

量化是一种强大的技术,可以减少模型的内存需求,同时保持性能相似。它允许更快的加载、使用和微调llm,即使使用较小的gpu。

预量化(GPTQ、AWQ、GGUF)

我们已经探索了分片和量化技术。但是量化是在每次加载模型时进行的,这是非常耗时的操作,有没有办法直接保存量化后的模型,并且在使用时直接加载呢?

TheBloke是HuggingFace上的一个用户,它为我们执行了一系列量化操作,我想用过大模型的人一定对它非常的熟悉吧

 

这些量化模型包含了很多格式GPTQ、GGUF和AWQ,我们来进行介绍

1、GPTQ: Post-Training Quantization for GPT Models

GPTQ是一种4位量化的训练后量化(PTQ)方法,主要关注GPU推理和性能。

该方法背后的思想是,尝试通过最小化该权重的均方误差将所有权重压缩到4位。在推理过程中,它将动态地将其权重去量化为float16,以提高性能,同时保持低内存。

我们需要在HuggingFace Transformers中的gptq类模型中加载:

pip install optimum
pip install auto-gptq --extra-index-url https://huggingface.github.io/autogptq-index/whl/cu118/

然后找到需要加载的模型,比如“TheBloke/zephyr-7B-beta-GPTQ”,进行加载

from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline# Load LLM and Tokenizer
model_id = "TheBloke/zephyr-7B-beta-GPTQ"
tokenizer = AutoTokenizer.from_pretrained(model_id, use_fast=True)
model = AutoModelForCausalLM.from_pretrained(model_id,device_map="auto",trust_remote_code=False,revision="main"
)# Create a pipeline
pipe = pipeline(model=model, tokenizer=tokenizer, task='text-generation')

尽管我们安装了一些额外的依赖项,但我们可以使用与之前相同的管道,也就是是不需要修改代码,这是使用GPTQ的一大好处。

GPTQ是最常用的压缩方法,因为它针对GPU使用进行了优化。但是如果你的GPU无法处理如此大的模型,那么从GPTQ开始切换到以cpu为中心的方法(如GGUF)是绝对值得的。

2、GPT-Generated Unified Format

尽管GPTQ在压缩方面做得很好,但如果没有运行它的硬件,那么就需要使用其他的方法。

GGUF(以前称为GGML)是一种量化方法,允许用户使用CPU来运行LLM,但也可以将其某些层加载到GPU以提高速度。

虽然使用CPU进行推理通常比使用GPU慢,但对于那些在CPU或苹果设备上运行模型的人来说,这是一种非常好的格式。

使用GGUF非常简单,我们需要先安装ctransformers包:

pip install ctransformers[cuda]

然后加载模型“TheBloke/zephyr-7B-beta-GGUF”,

from ctransformers import AutoModelForCausalLM
from transformers import AutoTokenizer, pipeline# Load LLM and Tokenizer
# Use `gpu_layers` to specify how many layers will be offloaded to the GPU.
model = AutoModelForCausalLM.from_pretrained("TheBloke/zephyr-7B-beta-GGUF",model_file="zephyr-7b-beta.Q4_K_M.gguf",model_type="mistral", gpu_layers=50, hf=True
)
tokenizer = AutoTokenizer.from_pretrained("HuggingFaceH4/zephyr-7b-beta", use_fast=True
)# Create a pipeline
pipe = pipeline(model=model, tokenizer=tokenizer, task='text-generation')

加载模型后,我们可以运行如下提示:

outputs = pipe(prompt, max_new_tokens=256)
print(outputs[0]["generated_text"])

如果你想同时利用CPU和GPU, GGUF是一个非常好的格式。

3、AWQ: Activation-aware Weight Quantization

除了上面两种以外,一种新格式是AWQ(激活感知权重量化),它是一种类似于GPTQ的量化方法。AWQ和GPTQ作为方法有几个不同之处,但最重要的是AWQ假设并非所有权重对LLM的性能都同等重要。

也就是说在量化过程中会跳过一小部分权重,这有助于减轻量化损失。所以他们的论文提到了与GPTQ相比的可以由显著加速,同时保持了相似的,有时甚至更好的性能。

该方法还是比较新的,还没有被采用到GPTQ和GGUF的程度。

对于AWQ,我们将使用vLLM包:

pip install vllm

使用vLLM可以直接加载模型:

from vllm import LLM, SamplingParams # Load the LLM 
sampling_params = SamplingParams(temperature=0.0, top_p=1.0, max_tokens=256) 
llm = LLM( model="TheBloke/zephyr-7B-beta-AWQ",  quantization='awq',  dtype='half',  gpu_memory_utilization=.95,  max_model_len=4096 
)

然后使用.generate运行模型:

output = llm.generate(prompt, sampling_params) 
print(output[0].outputs[0].text)

就是这样

 

 

 

 

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

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

相关文章

如何远程监控员工的电脑

如何远程监控员工的电脑 为什么要对员工使用电脑的行为进行监控呢?对企业来说是有其必要性的。其必要性主要体现以下4个方面。 1.数据安全与知识产权保护 防止数据泄露:企业内部往往存储着大量的敏感信息,如客户数据、财务资料、商业秘密、…

23linux 自定义shell文件系统

打印环境变量,把当前子进程所有环境变量打印出来 环境变量也是一张表(指针数组以null结尾,最后条件不满足就退出了 ) 用子进程调用 结论1 当我们进行程序替换的时候 ,子进程对应的环境变量(子进程的环境变…

蓝桥杯第六届c++大学B组详解

前言: 看了很多博客以及视频讲解,感觉都不是很清楚,比较模棱两可,所以干脆自己一边想,一边写博客,也可帮助到其他人,都是根据自己的逻辑来尽量清楚简单的讲清楚题目,喜欢的不要吝啬三…

RISC-V/ARM mcu OpenOCD 调试架构解析

Risc-v/ARM mcu OpenOCD 调试架构解析 最近有使用到risc-v的单片机,所以了解了下risc-v单片机的编译与调试环境的搭建,面试时问到risc-v的调试可参看以下内容。 risc-v根据官方的推荐,调试器服务是选择OpenOCD,DopenOCD(开放片上…

ros小问题之rosdep update time out问题

在另外一篇ROS 2边学边练系列的文章里有写碰到这种问题的解决方法(主要参考了其他博主的文章,只是针对ROS 2做了些修改调整),此处单拎出来方便查找。 在ROS 2中执行rosdep update时,报出如下错误: 其实原因…

Java设计模式:外观模式之优雅门面(九)

码到三十五 : 个人主页 心中有诗画,指尖舞代码,目光览世界,步履越千山,人间尽值得 ! 在软件工程中,设计模式是解决常见设计问题的经验总结,它为开发者提供了一种通用的、可复用的解决方案。外…

根证书和中间证书安装配置

下载根证书 根证书是建立信任链的基础。一旦客户端安装了根证书,它即可验证由该根证书签发的所有证书。这使得客户端可以信任与该根证书相关的所有服务器和应用程序,从而建立起一个完整的信任链。 如果您的业务用户通过浏览器访问您的Web业务&#xff…

鸿蒙TypeScript学习第10天:【String(字符串)】

1、TypeScript String(字符串) String 对象用于处理文本(字符串)。 语法 var txt new String("string"); 或者更简单方式: var txt "string"; 2、String 对象属性 下表列出了 String 对象支…

QA测试开发工程师面试题满分问答8: mysql数据库的索引定义、用途和使用场景

MySQL数据库索引是一种数据结构,用于提高数据库的查询效率。索引是基于表中的一个或多个列构建的,它们允许数据库系统快速定位和访问表中的特定数据,而无需扫描整个表。 索引的定义 在MySQL中,可以使用CREATE INDEX语句定义索引…

前端| 富文本显示不全的解决方法

背景 前置条件:编辑器wangEditor vue项目 在pc端进行了富文本操作, 将word内容复制到编辑器中, 进行发布, pc端正常, 在手机端展示的时候 显示不全 分析 根据h5端编辑器内容的数据展示, 看到有一些样式造…

OpenHarmony实战:轻量系统STM32F407芯片移植案例

介绍基于STM32F407IGT6芯片在拓维信息Niobe407开发板上移植OpenHarmony LiteOS-M轻量系统,提供交通、工业领域开发板解决方案。 移植架构采用Board与SoC分离方案,使用arm gcc工具链Newlib C库,实现了lwip、littlefs、hdf等子系统及组件的适配…

字符串...

String概述: java.lang.String类代表字符串,Java程序中的所有字符串文字(列如"abc")都为此类的对象. String name "我是一个小仙女"; String schoolName "天才程序员"; String的注意点 字符串的内容是不会发生改变的,它的对象在创建后不能…

实验 10_IPSEC Over GRE 实验

实验拓扑 实验需求 按照拓扑配置 IP 地址。AR1 与 AR3 部署静态路由。对 192.168.1.0/24 和 192.168.2.0/24 的流量进行数据 IPSCE 加密处理。部署 GRE 隧道和静态路由实现 PC1 与 PC2 通过加密 GRE 隧道实现互通。 实验配置之及其验证 (1)根据拓扑配置IP地址 (2)实现需求 2…

【安全工具】信息收集——ENScan_GO

1.初次使用 运行命令生成配置文件 ./enscan -v 2.配置cookie 参考介绍 wgpsec/ENScan_GO: 一款基于各大企业信息API的工具,解决在遇到的各种针对国内企业信息收集难题。一键收集控股公司ICP备案、APP、小程序、微信公众号等信息聚合导出。 (github.com) 3.友情提…

mac | Windows 本地部署 Seata2.0.0,Nacos 作为配置中心、注册中心,MySQL 存储信息

1、本人环境介绍 系统 macOS sonama 14.1.1 MySQL 8.2.0 (官方默认是5.7版本) Seata 2.0.0 Nacos 2.2.3 2、下载&数据库初始化 默认你已经有 Nacos、MySQL,如果没有 Nacos 请参考我的文章 : Docker 部署 Nacos(单机…

Redis的三种部署方案

文章目录 单机模式主从复制哨兵模式分片集群 在Redis中提供的集群方案总共有三种:单机模式,主从复制集群、哨兵模式,Redis分片集群 单机模式 Redis 只运行在一台服务器上,并且所有的数据都存储在这一台服务器的内存中。 主从复制…

小红不想做完全背包 (hard)(BFS最少操作)

本题链接:登录—专业IT笔试面试备考平台_牛客网 样例: 输入 4 3 1 2 3 4 输出 1 思路: 根据题意,要求拿去物品数量的最小值,也可以看作是最少操作拿取的次数。 所以我们应该联想到 BFS 搜索,以后遇到最小值…

推动科技创新润德生物邀您到场参观2024第13届生物发酵展

参展企业介绍 山东润德生物科技有限公司成立于2014年10月17日,是一家围绕生物制品的研发、生产、营销、国际贸易、技术服务为核心业务的国家高新技术企业,近年来荣获国家制造业单项冠军示范企业、国家级绿色工厂、国家知识产权优势企业、国家工业产品绿…

YOLOV8注意力改进方法:DoubleAttention(附代码)

原论文地址:原论文地址 DoubleAttention网络结构的优点在于,它能够有效地捕获图像中不同位置和不同特征的重要性,从而提高了图像识别和分割的性能。 论文相关内容介绍: 论文摘要:学习捕捉远程关系是图像/视频识别的…

【线段树】【前缀和】:1687从仓库到码头运输箱子

本题简单解法 C前缀和算法的应用:1687从仓库到码头运输箱子 本文涉及的基础知识点 C算法:前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 线段树 LeetCode1687从仓库到码头运输箱子 你有一辆货运卡车,你需要用这一辆车…