使用 Imatrix 和 K-Quantization 进行 GGUF 量化以在 CPU 上运行 LLM

适用于您的 CPU 的快速而准确的 GGUF 模型。欢迎来到雲闪世界

添加图片注释,不超过 140 字(可选)

GGUF 是一种二进制文件格式,旨在使用 GGML(一种基于 C 的机器学习张量库)进行高效存储和快速大型语言模型 (LLM) 加载。

GGUF 将推理所需的所有组件(包括标记器和代码)封装在一个文件中。它支持各种语言模型的转换,例如 Llama 3、Phi 和 Qwen2。此外,它还有助于将模型量化为较低的精度,以提高 CPU 的速度和内存效率。

我们经常写“GGUF 量化”,但 GGUF 本身只是一种文件格式,而不是量化方法。llama.cpp 中实现了几种量化算法,用于减小模型大小并以 GGUF 格式序列化生成的模型。

在本文中,我们将了解如何使用重要性矩阵 (imatrix) 和 K-Quantization 方法准确量化 LLM 并将其转换为 GGUF。我使用 imatrix 为 Gemma 2 Instruct 提供了 GGUF 转换代码。它与 llama.cpp 支持的其他模型的工作方式相同:Qwen2、Llama 3、Phi-3 等。我们还将了解如何评估量化的准确性和生成模型的推理吞吐量。

本文介绍了使用重要矩阵和 K 量化的量化、基准测试和 GGUF 转换的代码,并在此笔记本中实现:

使用 Imatrix 和 K-Quantization 实现精确的 GGUF 量化

K 量化实现更准确的 GGUF

K 量化(又称 K-Quants)涉及将模型的权重拆分为“超级块”,然后进一步细分为更小的子块。每个子块都有自己的比例和最小值,这些比例和最小值被量化为有限数量的位 - 通常为 8、6 或 4,具体取决于特定的量化方法,例如 Q2_K、Q4_K 或 Q5_K。这些比例和最小值有助于确保模型在精度降低时也能保持准确性。

虽然该方法比较复杂,量化速度也比较慢(特别是与没有 K-Quants 的 GGUF 量化相比),但所得到的量化模型在推理过程中效率很高。

一旦模型被量化,反量化(将量化权重转换回 fp16 的过程)就会变得简单。它只需要乘以预定的比例并添加最小值,并且可以一次对整个子块进行此操作。这种方法非常适合硬件加速,如 SIMD(单指令、多数据)和 GPU 计算。

来源:有关其工作原理的更多详细信息,我推荐Reddit 上的这个精彩解释。

我们可以使用llama.cpp (MIT 许可证)通过 K-Quantization 量化模型,如下所示:

 
./llama.cpp/llama-quantize {original_model} {iqtype} {m}

其中 {original_model} 是 GGUF 格式的原始模型,{iqtype} 是量化模型的保存位置,{m} 是量化方法,例如,Q4_K_S 表示使用 k 量化的较小 4 位模型。

GGUF 量化的重要性矩阵 (imatrix)

在 LLM 中,权重的使用或多或少取决于任务。有些权重也是异常值,因此很难量化。我们不应该试图降低它们的精度,因为它们会产生很大的量化误差。

利用校准数据集,我们可以检查模型中最“活跃”的权重是什么,然后将其保留下来,避免量化。这类似于 AWQ 所做的。

测量权重的重要性可能代价高昂,因为它需要模型对整个校准数据集进行前向传递。我建议使用 GPU 来完成。

应谨慎选择用于校准的数据集。如果您知道将使用该模型执行的任务类型,则应使用一个稍大的数据集来说明该任务。另一方面,如果您计划使用该模型而不针对特定领域或任务,则应使用一般领域中的数据集,例如 Wikipedia。

我使用维基百科作为笔记本中的量化示例。

要使用 llama.cpp 计算重要性矩阵,请运行以下命令:

./llama.cpp/llama-imatrix -m {original_model} -f en-h10000.txt -o imatrix.dat -ngl 99

这将在您当前目录中生成一个重要性矩阵文件 imatrix.dat,使用来自英文维基百科的数据集“en-h10000.txt”(10000 行)进行校准。

使用较慢的 GPU(例如 Google Colab 的 T4),这只需要几分钟就可以完成 2B 参数模型。

接下来,我们可以使用 K-Quants 量化模型,使用这个重要性矩阵:

./llama.cpp/llama-quantize --imatrix imatrix.dat {original_model} {iqtype} {m}

与标准 k 量化的唯一区别是我们提供了 imatrix 文件。

GGUF K-量化 Gemma 2 的重要性矩阵

我们将量化google/gemma-2–2b-it。首先,安装 llama.cpp:

git clone https://github.com/ggerganov/llama.cpp 
cd llama.cpp && GGML_CUDA=1 make && pip install -r requirements.txt

如果您想使用 GPU 进行量化(比使用 CPU 快得多),请设置“GGML_CUDA=1”以使用 CUDA 后端。编译将需要一些时间(超过 10 分钟)。

然后,我们设置以下变量并创建目录:

从huggingface_hub导入快照下载
model_name = "google/gemma-2-2b-it"  # 我们想要量化的模型
methods = [ 'Q4_K_S' , 'Q4_K_M' ] # 用于量化的方法
base_model = "./original_model_gemma2-2b/"  # FP16 GGUF 模型的存储位置
quantized_pa​​th = "./quantized_model_gemma2-2b/"  # 量化的 GGUF 模型的存储位置
original_model = quantized_pa​​th+ 'FP16.gguf'  #FP16 GGUF 文件的路径
mkdir {quantized_pa​​th}

我们需要下载要量化的模型:

 
 

快照下载(repo_id = model_name,local_dir = base_model,local_dir_use_symlinks = False)

然后,将模型转换为GGUF,无需量化(fp16):

快照下载(repo_id = model_name,local_dir = base_model,local_dir_use_symlinks = False)

接下来,我们下载用于校准和评估的数据集:

wget https://object.pouta.csc.fi/OPUS-Wikipedia/v1.0/mono/en.txt.gz 
Gunzip en.txt.gz 
head -n 10000 en.txt > en-h10000.txt 
sh llama. cpp/scripts/get-wikitext-2.sh

我将使用 10000 行 OPUS-Wikipedia 来计算重要性矩阵和 wikitext-2 的测试集来评估模型的困惑度。

然后,我们可以按如下方式计算重要性矩阵:

./llama.cpp/llama-imatrix -m {original_model} -f en-h10000.txt -o {quantized_pa​​th}/imatrix.dat --verbosity 1 -ngl 99

接下来,我们使用重要性矩阵和不重要性矩阵对模型进行量化,以进行比较,并使用两种不同的方法“Q4_K_S”和“Q4_K_M”。Q4_K_S 产生的模型比 Q4_K_M 略小,但准确性较低。

对于方法中的m : 
    qtype = f“ {quantized_pa​​th} / {m.upper()} .gguf”
     iqtype = f“ {quantized_pa​​th} / {m.upper()} _I.gguf”./
     llama.cpp/llama-quantize {original_model} {qtype} {m} 
    ./llama.cpp/llama-quantize --imatrix {quantized_pa​​th}/imatrix.dat {original_model} {iqtype} {m}

我发布了几个使用我的笔记本制作的 gemma-2–2b-it 的 GGUF 模型:

  • kaitchup/gemma-2–2b-it-GGUF

使用 Imatrix 对 GGUF K 量化的推理吞吐量和困惑度进行基准测试

对 GGUF 模型的困惑度进行基准测试

完美准确的量化应该产生一个模型,该模型与给定文本上未量化的模型具有相同的困惑度。这里,给定的文本将是“wiki.test.raw”。

llama.cpp 提供了一个实用程序来计算 GGUF 模型的困惑度。您可以按如下方式运行它:

./llama.cpp/llama-perplexity -m {qtype} -f wikitext-2-raw/wiki.test.raw

其中 {qtype} 是您的 GGUF 文件的路径。

我计算了 Q4_K_M 和 Q4_K_S 的困惑度(使用和未使用重要性矩阵),并将其与 FP16(即未量化)模型的困惑度进行了比较。注意:在这里,我们可以比较所有这些模型的困惑度,因为它们是由同一模型制成的。但是,请注意,我们无法比较两个不同模型的困惑度,例如 Gemma 与 Llama 3.1。我在这里写到了这一点:

Gemma 2 2B Instruct 的结果:

注意:困惑度越低越好。

我们可以看到,量化模型的困惑度接近 FP16 模型。使用重要性矩阵会有所帮助。

对 GGUF 模型的推理吞吐量和内存消耗进行基准测试

我使用 llama.cpp 提供的另一个实用程序 llama-bench 对推理吞吐量进行了基准测试:

 
./llama.cpp/llama-bench -m {原始模型} -m {量化路径}/Q4_K_M.gguf -m {量化路径}/Q4_K_M_I.gguf -m {量化路径}/Q4_K_S.gguf -m {量化路径}/Q4_K_S_I.gguf -n 128,256,512

我使用了 CPU 后端。

要仅使用 CPU 对模型进行基准测试,请在没有 CUDA 的情况下编译 llama.cpp:

git clone https://github.com/ggerganov/llama.cpp 
cd llama.cpp && make && pip install -r requirements.txt

结果:

添加图片注释,不超过 140 字(可选)

量化模型在 CPU 上的速度明显快于 FP16 模型(大约 19 个 token/秒,而 9 个 token/秒)。小型和中型版本的性能大致相同。使用重要矩阵量化的模型表现并无不同。对于像 Gemma 2 2B 这样的小型 LLM,我认为使用中型版本(Q4_K_M)更好,因为它只比小型版本大 70 MB。

结论

K 量化通过将权重量化为具有单独尺度和最小值的较小块,提供了一种更精确的减小模型大小的方法,从而实现高效的推理。虽然这种方法在量化过程中更复杂且更慢,但它可以产生高度优化的推理模型。重要性矩阵进一步提高了量化的准确性。

基准测试结果表明,使用 K-Quantization 和重要性矩阵量化的模型可以产生准确且快速的模型。

量化过程本身也足够快和节省内存,从而成本低廉。

感谢关注雲闪世界。(Aws解决方案架构师vs开发人员&GCP解决方案架构师vs开发人员)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值