在CPU上高效使用GGUF格式的LoRA Adapter

文摘   2024-11-15 14:31   新加坡  

本文涉及到的详细测试代码和测试步骤放置于:

https://github.com/xinyuwei-david/david-share.git下的:Deep-LearningsGGUF-LoRA

本文中不再赘述代码实现。欢迎给repo点亮Star,您的点赞是作者持续创作的动力。

近年来,大型语言模型(LLM)在自然语言处理领域取得了巨大进展。然而,这些模型通常拥有数以亿计甚至数以千亿计的参数,导致它们在训练和推理时对计算资源的需求非常高。这对于许多资源有限的开发者来说,是一个巨大的挑战。

为了解决这个问题,研究者们提出了多种方法来降低模型的计算和存储成本。其中,模型量化参数高效微调(如LoRA)是两种非常有用的技术。在本文中,我们将详细介绍如何在CPU上使用GGUF格式的LoRA适配器,以实现对大型语言模型的高效推理。

一、背景知识

 

1. GGUF格式是什么?

 
GGUF是一种用于存储量化大型语言模型的二进制文件格式,旨在高效存储模型并加速加载过程。它将模型推理所需的一切内容(包括模型权重、分词器、配置文件等)打包到一个文件中。这对于在**资源受限的环境(如CPU)**上进行快速推理非常有帮助。

2. 什么是LoRA?

 
LoRA(Low-Rank Adaptation)是一种参数高效的微调方法。传统的模型微调需要更新和存储模型的全部参数,这对大型模型来说非常耗费资源。LoRA通过引入低秩矩阵来更新模型的权重,大大减少了需要训练和存储的参数数量。这使得在普通硬件上微调大型模型成为可能。

3. 为什么要在CPU上使用GGUF格式的LoRA适配器?

 
将LoRA适配器转换为GGUF格式并与基础模型一起加载,有以下几个优点:

  • 高效存储:GGUF格式经过优化,可以更紧凑地存储模型。

  • 快速加载:在推理时,GGUF格式的模型可以更快速地加载,减少启动时间。

  • 资源节约:在CPU上进行推理,无需高端GPU,降低了硬件成本。

  • 推理速度快:GGUF格式对推理进行了优化,即使在CPU上也能获得较快的推理速度。

二、GGUF格式如何加速推理?

 
在深入实践之前,让我们先了解一下为什么GGUF格式能够显著提高推理速度。

1. 高效的二进制格式

 
GGUF采用了优化的二进制存储方式,能够快速读取和解析模型权重。这减少了模型加载的开销,加快了推理启动的速度。

2. 一体化的模型文件

 
GGUF格式将模型所需的所有组件(包括模型权重、分词器、配置文件等)打包在一个文件中。这避免了加载多个文件带来的I/O开销,进一步提升了加载速度。

3. 支持模型量化

 
GGUF格式支持多种量化精度(如FP16、INT8、INT4等)。通过量化,可以大幅减少模型权重的尺寸,降低内存占用和计算复杂度,从而加速推理过程。

4. 优化的内存访问

 
在推理过程中,GGUF格式的数据排列方式优化了内存访问模式,减少了缓存未命中和内存带宽的瓶颈,提高了CPU的计算效率。

5. 专为CPU推理设计

 
GGUF格式特别适合在CPU上运行模型,例如搭配
llama.cpp。它利用了CPU架构的特性,避免了一些GPU特有的优化,从而在CPU上获得更好的性能表现。

实际效果

  • 使用GGUF格式的模型时,模型加载速度更快,推理延迟更低。

  • 在没有高性能GPU的情况下,GGUF格式可以让我们在普通计算机上运行大型语言模型,获得可接受的响应速度。

  • 许多开发者报告称,在使用GGUF格式的量化模型(如INT4量化)时,能够在CPU上实现接近实时的推理。

三、传统方法:合并LoRA适配器并转换为GGUF格式

 
在实践中,最初使用LoRA适配器的流程通常是:

  1. 训练LoRA适配器:在基础模型上进行微调,得到LoRA适配器。

  2. 合并适配器和基础模型:使用工具将LoRA适配器的权重与基础模型的权重合并。

  3. 转换为GGUF格式:将合并后的模型转换为GGUF格式,供推理使用。

问题

 
这种方法的问题在于:

  • 不灵活:每当有新的LoRA适配器时,都需要重新进行合并和转换,耗时耗力。

  • 占用更多存储空间:每个合并后的模型都是完整的模型,占用大量磁盘空间。

  • 操作复杂:对于每个新任务,都需要重复类似的步骤,不利于快速迭代。

四、新方法:分别转换基础模型和LoRA适配器为GGUF格式

 
为了克服上述问题,我们可以采用一种更灵活的方法:

  1. 转换基础模型为GGUF格式:将基础模型转换为GGUF格式。

  2. 转换LoRA适配器为GGUF格式:单独将LoRA适配器转换为GGUF格式。

  3. 在推理时一起加载:在推理时,同时加载基础模型和LoRA适配器。

优点

  • 灵活性:可以在推理时自由切换不同的LoRA适配器,无需重新合并模型。

  • 节省存储空间:LoRA适配器通常很小,占用的存储空间可以忽略不计。

  • 操作简便:减少了合并模型的步骤,降低了操作复杂度。

  • 推理速度快:利用GGUF格式的优势,即使在CPU上也能获得较好的推理速度。

操作步骤详解

 
以下,我们将详细介绍如何在实践中实现上述流程。

1. 将基础模型转换为GGUF格式

 
步骤:

  • 下载基础模型:从Hugging Face或其他平台下载预训练的基础模型。

  • 使用转换脚本:使用llama.cpp提供的convert_hf_to_gguf.py脚本。

    示例代码:

python convert_hf_to_gguf.py /path/to/your/base_model \
--outfile /path/to/output/base_model.gguf \
--outtype f16

 

  • /path/to/your/base_model:您的基础模型的目录路径。

  • /path/to/output/base_model.gguf:转换后GGUF模型的保存路径。

  • --outtype f16:指定模型的精度为FP16。

2. 将LoRA适配器转换为GGUF格式

 
步骤:

  • 训练LoRA适配器:使用PyTorch等深度学习框架,在基础模型上进行LoRA微调。

  • 使用转换脚本:使用llama.cpp提供的convert_lora_to_gguf.py脚本。

    示例代码:

# 转换LoRA适配器为GGUF格式
python convert_lora_to_gguf.py \
--outfile /path/to/output/lora_adapter.gguf \
--outtype f16 \
/path/to/your/lora_adapter

 

  • /path/to/your/lora_adapter:您的LoRA适配器的目录路径。

  • /path/to/output/lora_adapter.gguf:转换后GGUF LoRA适配器的保存路径。

    注意事项:

  • 确保LoRA适配器和基础模型是兼容的,即基于同一架构和版本。

  • 当前的转换脚本不支持包含词嵌入和语言模型头的LoRA适配器。

3. 在推理时一起加载基础模型和LoRA适配器

 
步骤:

  • 使用llama.cpp进行推理:llama.cpp支持同时加载基础模型和LoRA适配器。

    示例代码:

# 使用llama.cpp的推理程序
./main \
-m /path/to/output/base_model.gguf \
--lora /path/to/output/lora_adapter.gguf

 
解释:

  • -m指定基础模型的路径。

  • --lora指定LoRA适配器的路径。

当使用 GGUF 格式的基础模型和 LoRA 适配器时,二者的数据类型(例如精度或量化级别)最好保持一致

五、两种方法的对比

 

1. 灵活性

  • 分别转换并加载:可以随时更换LoRA适配器,适用于需要频繁切换任务的场景。

  • 合并后转换:每次更换适配器都需要重新合并,不够灵活。

2. 存储空间

 

  • 分别转换并加载:只需存储一个基础模型和多个小的LoRA适配器文件。

  • 合并后转换:每个合并后的模型都是完整的模型,占用大量存储空间。

3. 操作复杂度

 

  • 分别转换并加载:减少了合并模型的步骤,操作更简便。

  • 合并后转换:需要更多的步骤,操作复杂度更高。

4. 推理速度

 

  • 两种方法在推理速度和性能上基本一致。由于GGUF格式优化了推理速度,无论是否合并,加载到内存后的计算都是高效的。

5. 适用场景

  • 分别转换并加载:适用于不包含词嵌入和语言模型头的LoRA适配器,以及需要经常更换适配器的场景。

  • 合并后转换:适用于包含额外模块的LoRA适配器,或只针对特定任务的场景。

六、注意事项和建议

1. LoRA适配器的限制

 
当前的
convert_lora_to_gguf.py脚本不支持包含embed_tokenslm_head模块的LoRA适配器。如果您的适配器包含这些模块,建议使用合并后转换的方法。

2. 关于QLoRA适配器

 
如果您的LoRA适配器是使用QLoRA方法微调的(即在量化的基础模型上进行微调),直接将适配器转换为GGUF并与不同量化配置的基础模型一起加载,可能会导致性能下降。建议在与微调时相同的量化配置下进行操作。

3. 模型和适配器的兼容性

 
确保您的基础模型和LoRA适配器基于相同的模型架构和版本。如果不兼容,可能会导致推理失败或结果不准确。

4. 量化和精度选择

 

  • 基础模型:可以选择适当的量化方案(如q4_0q5_1等)以减少内存占用。

  • LoRA适配器:由于体积较小,通常使用FP16精度,无需进一步量化。

5. GGUF的优势

 
正如前文提到的,GGUF格式在推理速度方面具有显著的优势。通过优化的存储方式和对量化的支持,GGUF能够让大型语言模型在CPU上实现快速、高效的推理。这使得在资源受限的环境中运行复杂的模型成为可能。

七、实践案例

 
假设您有一个基础模型和多个LoRA适配器,希望在CPU上高效地进行不同任务的推理。

步骤:

  1. 将基础模型转换为GGUF格式,并存储在固定位置。

  2. 将所有的LoRA适配器分别转换为GGUF格式

  3. 在需要进行推理时,根据任务加载对应的LoRA适配器,无需重新合并模型。

    优势:

  • 您只需要保存一个基础模型,节省了存储空间。

  • 可以快速切换任务,提升了开发和部署的效率。

  • 由于GGUF格式的优化,即使在CPU上,推理速度也能满足需求。


大魏分享
https://github.com/davidsajare/david-share.git
 最新文章