diff --git a/docs/zh_cn/tutorials/quant/advanced_quantization.md b/docs/zh_cn/tutorials/quant/advanced_quantization.md index b5cac2fca18fcc59728ffb3b7d022e9d370fb34c..0bb4d94cd15fd3cfa01a77c3742bdc7ad126115a 100644 --- a/docs/zh_cn/tutorials/quant/advanced_quantization.md +++ b/docs/zh_cn/tutorials/quant/advanced_quantization.md @@ -1,5 +1,54 @@ # 量化策略详细教程 -近年来,Transformer模型已在各个领域得到广泛采用,尤其是生成式语言大模型极大地推动了人工智能领域的发展。这些模型已经从数亿个参数发展到数千亿个参数,在有限的数据和 GPU 资源下运行,对于这些模型来说变得越来越具有挑战性。此时压缩技术变得格外重要,其中量化已成为减少内存占用和计算开销的通用和主要范例。然而,许多研究表明,Transformer模型往往会存在强烈的异常激活值,这使得它们难以量化。为了保持可接受的性能,这些异常值的存在要求激活具有更高的位宽或使用不同的数字格式、额外的微调或其他解决方法。本文档会介绍前沿的优化量化效果的几种策略,其中包括一些开源工作,也包括PaddleSlim自研的方法。以下方法暂时仅支持Transformer模型,具体示例使用方法可参考[PaddleNLP LLM示例](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/llm/causallm),以下教程仅详细介绍API接口。 +近年来,Transformer模型已在各个领域得到广泛采用,尤其是生成式语言大模型极大地推动了人工智能领域的发展。这些模型已经从数亿个参数发展到数千亿个参数,在有限的数据和 GPU 资源下运行,对于这些模型来说变得越来越具有挑战性。此时压缩技术变得格外重要,其中量化已成为减少内存占用和计算开销的通用和主要范例。然而,许多研究表明,Transformer模型往往会存在强烈的异常激活值,这使得它们难以量化。为了保持可接受的性能,这些异常值的存在要求激活具有更高的位宽或使用不同的数字格式、额外的微调或其他解决方法。本文档会介绍前沿的优化量化效果的几种策略,其中包括一些开源工作,也包括PaddleSlim自研的方法。 + +## **LLM量化效果Benchmark** + +1. LLama 13b 在不同量化策略下精度对比 + +| 量化策略 | 比特数 | ACC1/% | ACC2/% | +| --------------- | ---------- | ---------------- | ---------------- | +| Baseline | FP16 | 78.32 | 32.98 | +| RTN | W8A8 | 34.05 | 24.96 | +| SmoothQuant | W8A8 | 42.36 | 27.78 | +| ShiftQuant | W8A8 | 33.35 | 25.48 | +| Shift-SmoothQuant | W8A8 | 45.26 | 24.66 | +| 自适应Shift-SmoothQuant | W8A8 | **78.07** | **32.69** | +| | | | +| RTN | W4A16 | 75.48 | 29.27 | +| GPTQ | W4A16 | **77.55** | **32.32** | + +2. Bloom 7.1b 在不同量化策略下精度对比 + +| 量化策略 | 比特数 | ACC1/% | ACC2/% | +| --------------- | ---------- | ---------------- | ---------------- | +| Baseline | FP16 | 77.18 | 41.08 | +| RTN | W8A8 | 76.48 | 38.26 | +| SmoothQuant | W8A8 | 76.57 | 38.70 | +| ShiftQuant | W8A8 | 68.99 | 39.97 | +| Shift-SmoothQuant | W8A8 | 76.77 | 37.22 | +| 自适应Shift-SmoothQuant | W8A8 | **77.04** | **40.63** | +| | | | +| RTN | W4A16 | 75.18 | 38.03 | +| GPTQ | W4A16 | **76.82** | **39.37** | + +3. ChatGLM2 6b 在不同量化策略下精度对比 + +| 量化策略 | 比特数 | ACC1/% | ACC2/% | +| --------------- | ---------- | ---------------- | ---------------- | +| Baseline | FP16 | 76.46 | 31.57 | +| PTQ-INT8 | W8A8 | 64.08 | 29.94 | +| SmoothQuant | W8A8 | 64.29 | 29.86 | +| ShiftQuant | W8A8 | 57.83 | 27.26 | +| Shift-SmoothQuant | W8A8 | 58.89 | 24.29 | +| 自适应Shift-SmoothQuant | W8A8 | **76.89** | **34.55** | +| | | | +| RTN | W4A16 | 74.20 | 26.30 | +| GPTQ | W4A16 | **75.66** | **31.50** | + +- ACC1:Finetuned下游任务下,使用数据集nl2sql的指标 +- ACC2:Pretrained开源任务下,使用数据集C-eval的指标 + +以下方法暂时仅支持Transformer模型,具体示例使用方法可参考[PaddleNLP LLM示例](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/llm#6-%E9%87%8F%E5%8C%96),以下教程仅详细介绍API接口。 ## 1. Shift功能 diff --git a/paddleslim/quant/advanced/piecewise_search.py b/paddleslim/quant/advanced/piecewise_search.py index d8e4a1f2d734caf46f9a727dd2ec307099f35ce6..6b17286b74219449b808a992e292e3855ad6f918 100644 --- a/paddleslim/quant/advanced/piecewise_search.py +++ b/paddleslim/quant/advanced/piecewise_search.py @@ -84,7 +84,7 @@ class PieceWiseSearch(): # print('search for piece {}; centroids value is {}'.format( # piece[i], centroids[centroids.argsort()[i]].numpy())) alpha = self.search_alpha_min - alpha_max = self.search_scale_max + alpha_max = self.search_scale_max if self.search_scale_max is not None else self.search_alpha_max calibration_loss = float('inf') final_alpha = None mask_for_search = paddle.where(labels == centroids.argsort()[i], @@ -95,7 +95,9 @@ class PieceWiseSearch(): if alpha < 1: alpha += 0.01 if alpha >= self.search_alpha_max: - alpha = 1. + alpha = self.search_scale_min + if alpha is None: + break else: alpha += 0.5 diff --git a/paddleslim/quant/observers/abs_max_weight.py b/paddleslim/quant/observers/abs_max_weight.py index 021ce57759d51f16b605c766baaad5086293cdd6..1381cd23d8cdd37be8a303805c2538d33b44c5b3 100644 --- a/paddleslim/quant/observers/abs_max_weight.py +++ b/paddleslim/quant/observers/abs_max_weight.py @@ -67,8 +67,9 @@ class AbsMaxChannelWiseWeightObserverLayer(ChannelWiseObserver): [i for i in range(len(inputs.shape)) if i != self.quant_axis()]) abs_max_values = paddle.max( paddle.abs(inputs), axis=reduce_axis).cast("float32") - abs_max_values = paddle.where(abs_max_values == np.float32(0.0), - np.float32(1e-8), abs_max_values) + abs_max_values = paddle.where( + abs_max_values == paddle.to_tensor(0, dtype=inputs.dtype), + paddle.to_tensor(1e-8, dtype=inputs.dtype), abs_max_values) return abs_max_values def min_value(self) -> float: