从16-bit 到 1.58-bit :大模型内存效率和准确性之间的最佳权衡

本文涉及的产品
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时计算 Flink 版,5000CU*H 3个月
实时数仓Hologres,5000CU*H 100GB 3个月
简介: 通过量化可以减少大型语言模型的大小,但是量化是不准确的,因为它在过程中丢失了信息。通常较大的llm可以在精度损失很小的情况下量化到较低的精度,而较小的llm则很难精确量化。

什么时候使用一个小的LLM比量化一个大的LLM更好?

在本文中,我们将通过使用GPTQ对Mistral 7B、Llama 27b和Llama 13B进行8位、4位、3位和2位量化实验来回答这个问题。我们将使用optimum-benchmark比较它们的内存消耗,并使用LLM Evaluation Harness比较它们的准确性。

在最后我们还要介绍一个大模型的最新研究1.58 Bits,它只用 -1,0,1来保存权重,这样就不会再有浮点数,虽然不是量化的方法,但是这样保存模型的权重应该是模型极限了。

llm的核心是深度学习模型,本质上是深度神经网络。这些网络由多层神经元组成,深度堆叠在一起处理和解释大量数据。

这些网络的运作取决于一种叫做“权重”的东西。这些权重在训练过程中进行训练,以类似于矩阵乘法的方式进行相乘。

这个过程需要大量的计算资源,通常需要使用gpu,特别是那些配备了CUDA技术的Nvidia产品来处理密集的高性能矩阵乘法。

传统llm主要构建为32位或16位模型。这意味着模型中的每个参数都由32位或16位浮点数表示。浮点数本质上是小数点值,不同于表示整数的整数。位深度(32位或16位)表示这些浮点数的精度级别。但是这种高精确度是有代价的:它需要大量的计算能力和内存,使llm资源密集且不易访问。

为了进一步减少模型的存储需求和计算复杂度。量化意味着将参数表示为比32位或16位更少位的整数或小数。通过这种方式,可以在几乎不损失精度的情况下显著减少模型的大小,从而使得在嵌入式设备或边缘设备上部署深度学习模型变得更加可行。同时量化还可以提高模型的计算效率,因为在大多数硬件上,对整数操作的支持要优于浮点数操作。

下面我们先对比下目前经常用到的一些量化方法

目前量化方法的测试

我们这里使用GPTQ是因为AWQ虽然更准确能够产生更快的推理模型。但是它最低只能支持到只4位量化。

而AutoGPTQ支持使用GPTQ进行2、3、4和8位量化,为了对比测试,所以我们选择了GPTQ来进行这个测试,下面是量化的代码:

 fromtransformersimportAutoModelForCausalLM, AutoTokenizer
 fromoptimum.gptqimportGPTQQuantizer
 importtorch
 model_path='meta-llama/Llama-2-7b-hf'
 forwin [2,3,4,8]:
   quant_path='Llama-2-7b-hf-gptq-'+str(w)+'bit'
   # Load model and tokenizer
   tokenizer=AutoTokenizer.from_pretrained(model_path, use_fast=True)
   model=AutoModelForCausalLM.from_pretrained(model_path, torch_dtype=torch.float16)
   quantizer=GPTQQuantizer(bits=w, dataset="c4", model_seqlen=4096)
   quantized_model=quantizer.quantize_model(model, tokenizer)

这段代码将创建Llama 27b的2、3、4和8位GPTQ版本。

基准内存效率和准确性

对于量化来说我们主要想知道2个结果:

1、节省了多少内存;2、在下游任务中损失了多少准确性

为了回答第一个问题,我将使用Optimum-benchmark,我将使用它来测量量化模型的峰值内存消耗。

为了回答第二个问题,我将使用 Evaluation Harness,因为Evaluation Harness可以运行许多基准来评估llm在下游任务中的能力。它特别推动了Open LLM排行榜,所以说对于指标测试来说他还是非常有权威性的。

使用Optimum-benchmark进行基准测试,使用的是这个配置文件。

 defaults:
   - backend: pytorch # default backend
   - benchmark: inference # we will monitor the inference
   - launcher: process
   - experiment # inheriting from experiment config
   - _self_ # for hydra 1.1 compatibility
   - override hydra/job_logging: colorlog # colorful logging
   - override hydra/hydra_logging: colorlog # colorful logging
 hydra:
   run:
     dir: experiments_ob/${experiment_name} #The results will be reported in this directory. Note that "experiment_name" refers to the configuration field name "experiment_name" below
   sweep:
     dir: experiments_ob/${experiment_name}
   job:
     chdir: true
     env_set: #These are environment variable that you may want to set before running the benchmark
       CUDA_VISIBLE_DEVICES: 0
       CUDA_DEVICE_ORDER: PCI_BUS_ID
 experiment_name: Llama-2-13b-hf-16bit
 model: meta-llama/Llama-2-13b-hf #The model that we want to evaluate. It can be from the Hugging Face Hub or local directory
 device: cuda #Which device to use for the benchmark. We will use CUDA, i.e., the GPU
 backend:
   torch_dtype: float16
 benchmark:
   memory: true #We will monitor the memory usage
   warmup_runs: 10 #Before the monitoring starts, the inference will be run 10 times for warming up
   new_tokens: 1000 #Inference will generate 1000 tokens
   input_shapes:
     sequence_length: 512 #Prompt will have 512 tokens
     batch_size: 2

而运行Evaluation Harness,则只要运行下面的命令:

 lm_eval --model hf --model_args pretrained=meta-llama/Llama-2-13b-hf --tasks winogrande,hellaswag,arc_challenge --device cuda:0 --num_fewshot 5 --batch_size 2 --output_path ./eval_harness/Llama-2-13b-hf-16b

让我们来看看峰值内存使用情况,即模型在GPU上运行所需的最大内存,对于Llama 27b, 13B和Mistral 7B,使用2,3,4,8和16位精度。

精度降低1倍但是内存峰值消耗并不会降低1倍。这是因为并不是所有的参数都是量化的,而且内存也会被推理批数据消耗(不仅仅是加载模型)。例如,对于Llama 27b, 16位消耗15.5 GB, 8位消耗9.0 GB, 4位消耗5.9 GB。Mistral 7B在8位(9.5 GB)和16位(16.5 GB)精度上比Llama 27b稍微消耗更多的VRAM。

对于下游任务上的准确性,我选择了3个任务:

  • Winogrande:评估常识性推理的基准。
  • Arc挑战:一组小学科学问题。
  • HellaSwag:评估常识性推理的基准。

这三个基准也被Open LLM排行榜使用。

结果如下:



对于这三种模型,从16位到8位,这些任务的准确率没有下降,从8位到4位,准确率也是只有略有下降。它很好地说明了今天的4位量化算法还是非常给力的。并且这里我们用的是GPTQ,AWQ会产生更接近8位量化的结果。

选择4而不选择3位量化是非常好i的选择,因为峰值内存消耗只减少了一点点,但是准确性就显著降低了。对于2位量化,模型基本已经不能用了。

可以说目前来说量化的极限是4bit,因为使用4bit准确性不会有太多的损失。但是4bit并不是模型的极限,这就引出了我们要介绍的这篇新的论文

The Era of 1-bit LLMs:All Large Language Models are in 1.58 Bits

这是一项非常令人兴奋的技术。这种由微软开发的创新方法有望显著改变处理大型语言模型(llm)的计算效率和能耗。与将每个参数表示为32位或16位浮点数不同,1-bit 将llm的权重表示为三元值:-1、0或+1。

论文里面最主要内容是1-bit 的llm的性能与传统llm相当。这意味着我们可以用更少的资源支出达到相似的效率和准确性水平。

论文通过将0与+1和-1一起作为潜在值,我们从纯二进制表示(论文:1-bit LLMs)转换为三元表示。这种从1bit到1.58bit的转变不仅仅是数值上的调整;它给模型的学习能力带来了根本性的改变。

数学解释

在传统的深度学习神经网络中,计算的关键在于矩阵乘法,通常表示为点积。这涉及到将模型的权重(W)与输入(X)相乘和相加,按照方程Y = f(W, X)。这个过程虽然有效,但计算量很大,并且构成了传统llm中GPU依赖的支柱。

三元值(+1,-1,0)的引入从根本上改变了这个方式。使用这些整数表示,模型可以显著减少,或者在某些情况下完全消除对乘法的需要,主要依赖于加法。这种简化不仅仅是计算上的方便;它代表了LLM结构和执行方式的范式转变。

另外就是包含零作为值允许参数的更细微的表示,导致潜在的更有效的学习过程。这种效率并不是以性能为代价的;这些1.58位模型的性能可以与更高位的模型相媲美。

我们来看看性能、延迟和能效测试

研究人员将1.58位模型与基于llama架构的LLM进行了比较。为了确保公平性,他们在类似于Llama数据集的数据集上从头开始训练模型。在分析1.58位llm的性能时,不仅在生成连贯的文本(以困惑度来衡量)方面,而且在执行诸如问答之类的下游任务方面,1.58位模型不仅匹配甚至超过了等效Llama模型的性能。

还使用ARCe、HS等指标在各种下游任务(如问答和文本摘要)上进行了测试。1.58位模型在这些方面也表现出优异的性能。

bitnet模型架构

Llama和1.58位模型都是基于Transformer架构的。关键的区别在于权重内的数字表示和计算方法。1.58位模型使用所谓的“位线性”来代替传统的矩阵乘法大大简化了计算过程。

延迟和吞吐量的改进

1.58位模型最显著的优点之一是延迟和吞吐量的改进。延迟提高了2.7到2.4倍,吞吐量提高了惊人的9倍,能够为700亿个参数模型每秒生成2,977个令牌。这一性能明显高于目前的行业标准,包括Groq设定的标准。

总结

模型量化是深度学习领域一个重要的研究方向,它不仅可以帮助减小模型的存储和计算开销,还可以使得深度学习模型更容易在资源有限的设备上部署,推动了深度学习技术在边缘计算和物联网等领域的应用。但是目前4位的量化是目前研究的极限了,如果再缩小精度,会导致准确率大幅降低。

但是1.58位llm的出现标志着人工智能技术发展又出现了一个新的方向。这些模型具有令人印象深刻的性能指标、更低的硬件要求,虽然这种方法还无法应用到现有的模型上,我想以后如果有什么方法能将其应用到现有的模型上那么对于人工智能来说将是一个巨大的飞跃。

以下是2篇微软的论文:

https://avoid.overfit.cn/post/9a067e1d895240e9a82827edab45549f

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
2月前
|
程序员 编译器 C++
【C++核心】C++内存分区模型分析
这篇文章详细解释了C++程序执行时内存的四个区域:代码区、全局区、栈区和堆区,以及如何在这些区域中分配和释放内存。
52 2
|
25天前
|
机器学习/深度学习 算法 物联网
大模型进阶微调篇(一):以定制化3B模型为例,各种微调方法对比-选LoRA还是PPO,所需显存内存资源为多少?
本文介绍了两种大模型微调方法——LoRA(低秩适应)和PPO(近端策略优化)。LoRA通过引入低秩矩阵微调部分权重,适合资源受限环境,具有资源节省和训练速度快的优势,适用于监督学习和简单交互场景。PPO基于策略优化,适合需要用户交互反馈的场景,能够适应复杂反馈并动态调整策略,适用于强化学习和复杂用户交互。文章还对比了两者的资源消耗和适用数据规模,帮助读者根据具体需求选择最合适的微调策略。
101 5
|
1月前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。
|
5月前
|
NoSQL Java Redis
Redis系列学习文章分享---第十八篇(Redis原理篇--网络模型,通讯协议,内存回收)
Redis系列学习文章分享---第十八篇(Redis原理篇--网络模型,通讯协议,内存回收)
84 0
|
3月前
|
机器学习/深度学习 数据采集 PyTorch
构建高效 PyTorch 模型:内存管理和优化技巧
【8月更文第27天】PyTorch 是一个强大的深度学习框架,被广泛用于构建复杂的神经网络模型。然而,在处理大规模数据集或使用高性能 GPU 进行训练时,有效的内存管理对于提升模型训练效率至关重要。本文将探讨如何在 PyTorch 中有效地管理内存,并提供一些优化技巧及代码示例。
138 1
|
4月前
|
机器学习/深度学习 自然语言处理 算法
ICML 2024:零阶优化器微调大模型,大幅降低内存
【7月更文挑战第14天】ICML 2024研究表明,零阶优化用于大模型微调能大幅降低内存需求。该论文通过避免反向传播,减少LLM(大型语言模型)微调的内存开销,提出新方法,适用于资源受限环境。虽然性能可能不及一阶优化器,但为高效NLP计算开辟了新途径。论文链接:[arxiv.org/abs/2402.11592](https://arxiv.org/abs/2402.11592)**
86 3
|
4月前
|
存储 算法 安全
Java面试题:给定一个可能产生内存泄漏的场景,如何诊断并解决?实现一个生产者-消费者模型,使用适当的同步机制与并发工具类,Java并发工具包与框架:性能与调优
Java面试题:给定一个可能产生内存泄漏的场景,如何诊断并解决?实现一个生产者-消费者模型,使用适当的同步机制与并发工具类,Java并发工具包与框架:性能与调优
35 0
|
5月前
|
机器学习/深度学习 算法 存储
Bengio等人新作:注意力可被视为RNN,新模型媲美Transformer,但超级省内存
【6月更文挑战第3天】Bengio等人提出的新模型Aaren视注意力为特殊RNN,以解决Transformer在资源受限环境中的计算成本高和内存使用问题。Aaren模型通过并行前缀和算法实现高效计算和常数级内存使用,性能接近Transformer,同时在时间序列任务中表现优秀,尤其适合移动设备和嵌入式系统。尽管可能在某些复杂任务上不如Transformer,但其高效性为实时数据处理提供了潜力。论文链接:[https://arxiv.org/pdf/2405.13956](https://arxiv.org/pdf/2405.13956)
101 2
|
5月前
|
程序员 编译器 C++
C++内存分区模型(代码区、全局区、栈区、堆区)
C++内存分区模型(代码区、全局区、栈区、堆区)
|
6月前
|
程序员 编译器 C++
内存分区模型(代码区、全局区、栈区、堆区)
内存分区模型(代码区、全局区、栈区、堆区)