一步步量化LLM:将FP16模型转换为GGUF

5 阅读6分钟

一步步量化LLM:将FP16模型转换为GGUF

在本篇文章中,你将学习量化如何缩小大型语言模型的体积,以及如何将一个FP16的模型检查点转换为高效的GGUF文件,以便在本地分享和运行。

我们将涵盖的主题包括:

  • 不同精度类型(FP32, FP16, 8位, 4位)对模型大小和速度意味着什么
  • 如何使用huggingface_hub获取模型并进行身份验证
  • 如何使用llama.cpp转换为GGUF格式,并将结果上传至模型中心

让我们开始吧。

引言

像LLaMA、Mistral和Qwen这样的大型语言模型拥有数十亿参数,需要大量内存和计算能力。例如,以全精度运行LLaMA 7B可能需要超过12 GB的显存,这对许多用户来说并不现实。你可以在此模型中心讨论中查看详细信息。暂时不必担心“全精度”意味着什么;我们很快就会解释清楚。核心思想是:这些模型在没有帮助的情况下,对于标准硬件来说太大了。量化就是这种帮助。

量化允许独立研究人员和爱好者通过缩小模型体积而不严重影响性能的方式,在个人计算机上运行大型模型。在本指南中,我们将探讨量化的工作原理、不同精度格式的含义,然后逐步演示如何将示例FP16模型量化为GGUF格式并上传至模型中心。

什么是量化?

在最基本的层面上,量化就是使模型变小而不破坏它。大型语言模型由数十亿个称为权重的数值组成。这些数字控制在产生输出时网络不同部分的相互影响强度。默认情况下,这些权重使用高精度格式(如FP32或FP16)存储,这意味着每个数字都占用大量内存,而当你拥有数十亿个这样的数字时,情况很快就会失控。以一个像2.31384这样的数字为例。在FP32格式中,仅这一个数字就占用32位内存。现在想象一下存储数十亿个这样的数字。这就是为什么一个7B模型在FP32下很容易占用约28 GB,即使在FP16下也大约需要14 GB。对于大多数笔记本电脑和GPU来说,这已经太多了。

量化通过以下方式解决这个问题:我们实际上不再需要那么高的精度。我们使用更少的比特来存储接近原值的近似值。也许它变成了2.3,或者在底层变成了附近的整数值。这个数字稍微不那么精确,但模型在实际表现上仍然相同。神经网络可以容忍这些小误差,因为最终输出取决于数十亿次计算,而不是单个数字。小的差异会相互平均抵消,就像图像压缩减小文件大小而不会破坏图像观感一样。但回报是巨大的。一个在FP16下需要14 GB的模型,通常可以通过8位量化在约7 GB内存中运行,甚至通过4位量化在约4 GB内存中运行。这正是使得在本地运行大型语言模型成为可能,而无需依赖昂贵服务器的原因。

量化之后,我们通常将模型存储在统一的文件格式中。一种流行的格式是GGUF,由Georgi Gerganov(llama.cpp的作者)创建。GGUF是一个单一文件格式,包含量化后的权重和有用的元数据。它针对CPU或其他轻量级运行时的快速加载和推理进行了优化。GGUF还支持多种量化类型(如Q4_0、Q8_0),并且在CPU和低端GPU上运行良好。希望这能阐明量化的概念及其背后的动机。现在让我们继续编写一些代码。

逐步指南:将模型量化为GGUF

1. 安装依赖项并登录模型中心

在下载或转换任何模型之前,我们需要安装所需的Python包并使用模型中心进行身份验证。我们将使用huggingface_hub、Transformers和SentencePiece。这确保我们可以访问公共或受保护模型而不会出错:

!pip install -U huggingface_hub transformers sentencepiece -q

from huggingface_hub import login
login()

2. 下载预训练模型

我们将从模型中心选取一个小的FP16模型。这里我们使用TinyLlama 1.1B,它足够小,可以在Colab中运行,但仍然能很好地演示。使用Python,我们可以通过huggingface_hub下载它:

from huggingface_hub import snapshot_download

model_id = "TinyLlama/TinyLlama-1.1B-Chat-v1.0"
snapshot_download(
    repo_id=model_id,
    local_dir="model_folder",
    local_dir_use_symlinks=False
)

此命令将模型文件保存到model_folder目录中。你可以将model_id替换为你想要量化的任何模型中心模型ID。(如果需要,你也可以先使用AutoModel.from_pretrainedtorch.float16加载它,但snapshot_download对于获取文件来说更直接。)

3. 设置转换工具

接下来,我们克隆llama.cpp仓库,其中包含转换脚本。在Colab中:

!git clone https://github.com/ggml-org/llama.cpp
!pip install -r llama.cpp/requirements.txt -q

这将让你能够访问convert_hf_to_gguf.py。Python依赖项确保你拥有运行脚本所需的所有库。

4. 使用量化将模型转换为GGUF

现在,运行转换脚本,指定输入文件夹、输出文件名和量化类型。我们将使用q8_0(8位量化)。这将大致将模型的内存占用减半:

!python3 llama.cpp/convert_hf_to_gguf.py /content/model_folder \
    --outfile /content/tinyllama-1.1b-chat.Q8_0.gguf \
    --outtype q8_0

这里/content/model_folder是我们下载模型的路径,/content/tinyllama-1.1b-chat.Q8_0.gguf是输出的GGUF文件,--outtype q8_0标志意味着“量化为8位”。脚本加载FP16权重,将它们转换为8位数值,并写入一个单独的GGUF文件。这个文件现在小得多,并且可以使用GGUF兼容工具进行推理。

输出:

INFO:gguf.gguf_writer:Writing the following files:
INFO:gguf.gguf_writer:/content/tinyllama-1.1b-chat.Q8_0.gguf: n_tensors = 201, total_size = 1.2G
Writing: 100% 1.17G/1.17G [00:26<00:00, 44.5Mbyte/s]
INFO:hf-to-gguf:Model successfully exported to /content/tinyllama-1.1b-chat.Q8_0.gguf

你可以验证输出:

!ls -lh /content/tinyllama-1.1b-chat.Q8_0.gguf

你应该会看到一个大小为几GB的文件,比原始的FP16模型小。

-rw-r--r-- 1 root root 1.1G Dec 30 20:23 /content/tinyllama-1.1b-chat.Q8_0.gguf

5. 将量化后的模型上传至模型中心

最后,你可以发布GGUF模型,以便其他人可以轻松下载和使用它。使用huggingface_hub Python库:

from huggingface_hub import HfApi

api = HfApi()
repo_id = "kanwal-mehreen18/tinyllama-1.1b-gguf"
api.create_repo(repo_id, exist_ok=True)

api.upload_file(
    path_or_fileobj="/content/tinyllama-1.1b-chat.Q8_0.gguf",
    path_in_repo="tinyllama-1.1b-chat.Q8_0.gguf",
    repo_id=repo_id
)

这将创建一个新的仓库(如果它不存在),并上传你量化后的GGUF文件。现在任何人都可以使用llama.cpp、llama-cpp-python或Ollama加载它。你可以在此处访问我们创建的量化GGUF文件。

总结

通过遵循上述步骤,你可以获取任何受支持的模型中心模型,将其量化(例如到4位或8位),并保存为GGUF格式。然后将其推送到模型中心进行分享或部署。这使得压缩大型语言模型并在日常硬件上使用变得比以往任何时候都更加容易。FINISHED