You need to enable JavaScript to run this app.
导航
GPTQ量化 -- LlaMA3.1-8B 最佳实践文档
最近更新时间:2024.09.24 15:07:12首次发布时间:2024.09.24 15:07:12

机器学习平台是一套服务于专业算法工程师,整合云原生的工具+算力(GPU、CPU云服务器),进行一站式AI算法开发和迭代的平台。本方案将为您介绍如何在 MLP 对 Meta-Llama-3.1-8B 的开源模型进行GPTQ量化。

使用前提

说明

在实践过程中,如果因网络等问题导致模型、数据集或量化工具等无法下载到TOS bucket,建议您可以先将其下载到开发机云盘中,再自行拷贝到TOS路径下。

本方案以对 Meta-Llama-3.1-8B 模型进行GPTQ量化为例,在开始执行操作前,请确认您已经完成以下准备工作:

步骤一:准备 Llama-3.1-8B 模型
  1. 进入开发机。

    1. 登陆 账号登录-火山引擎

    2. 在左侧导航栏单击开发机,在开发机列表页面中单击待操作的开发机名称,进入对应开发机内。

    3. 通过 SSH 远程登录开发机,具体操作详见通过SSH远程连接开发机--机器学习平台-火山引擎

  2. 配置 volc configure。具体操作详见使用文档--机器学习平台-火山引擎

  3. 在 Terminal 中执行以下命令,通过镜像源下载 Llama-3.1-8B 模型,并打开挂载的存储桶路径。

cd /vemlp-demo-models
mkdir model-llama-gptq
cd model-llama-gptq
pip3 install -U huggingface_hub
export HF_ENDPOINT=https://hf-mirror.com
huggingface-cli download --token $HF_TOKEN --resume-download meta-llama/Meta-Llama-3.1-8B-Instruct --local-dir $ORIGINAL_MODEL_PATH

其中运行 huggingface-cli 需要传入的参数列表说明如下:

参数描述
hf_token具有llama使用权限的Huggingface账号的hf_token。
original_model_path源safetensor路径。

说明

  1. --token/--hf_username/--hf_token等参数非必须,仅为部分 Repo 有 license 限制,需登录申请许可。如果必要,请在 https://huggingface.co/settings/tokens 获取 token 后进行下载。
  2. 推荐您将模型文件、训练数据集的下载、存放地址都设置在 TOS/VEPFS/SCFS 等共享存储内,之后在进行训练、推理等跨节点的任务时,可以更加轻松地挂载到不同的机器上。
步骤二:准备数据集

在 Terminal 执行以下命令,可以直接下载开源的 wikitext2 数据集,来帮助 GPTQ 做量化校准。

cd /vemlp-demo-models
mkdir datasets-llama-gptq
cd datasets-llama-gptq
pip3 install -U huggingface_hub
export HF_ENDPOINT=https://hf-mirror.com
huggingface-cli download --repo-type dataset --resume-download carlosejimenez/wikitext__wikitext-2-raw-v1 --local-dir $CALIB_DATASET_PATH

参数说明如下:

参数描述
calib_dataset_path用来校验量化结果的数据集的路径。
步骤三:在开发机中执行量化

3.1 使用AutoGPTQ量化模型

  1. 在 Terminal 中执行以下命令,创建量化脚本 gptq-quant.py
cd /vemlp-demo-models
touch gptq-quant.py
  1. 编辑脚本内容,替换为需要配置的信息。
import os
from transformers import AutoTokenizer
from auto_gptq import AutoGPTQForCausalLM
from auto_gptq import BaseQuantizeConfig

def get_wikitext2_dataset(nsamples, seed, seqlen, tokenizer):
    import numpy as np
    import torch
    import torch.nn as nn
    from datasets import load_dataset

    traindata = load_dataset(dataset_path, split="train")
    testdata = load_dataset(dataset_path, split="test")

    trainenc = tokenizer("\n\n".join(traindata["text"]), return_tensors="pt")
    testenc = tokenizer("\n\n".join(testdata["text"]), return_tensors="pt")

    import random

    random.seed(seed)
    np.random.seed(0)
    torch.random.manual_seed(0)

    traindataset = []
    for _ in range(nsamples):
        i = random.randint(0, trainenc.input_ids.shape[1] - seqlen - 1)
        j = i + seqlen
        inp = trainenc.input_ids[:, i:j]
        attention_mask = torch.ones_like(inp)
        traindataset.append({"input_ids": inp, "attention_mask": attention_mask})
    return traindataset, testenc

# 配置模型、数据集地址
os.environ['BASE_MODEL_PATH'] = '/vemlp-demo-models/model-llama-gptq/Meta-Llama-3.1-8B'
os.environ['CALIB_DATASET_PATH'] = '/vemlp-demo-models/datasets-llama-gptq/'
os.environ['QUANT_MODEL_PATH'] = '/vemlp-demo-models/model-quant-gptq'

model_path = os.getenv('BASE_MODEL_PATH')
dataset_path = os.getenv('CALIB_DATASET_PATH')
quant_path = os.getenv('QUANT_MODEL_PATH')

# 设置量化超参数
quantize_config = BaseQuantizeConfig(
    bits=4,  # 使用GPTQ INT4量化
    group_size=128,  # GPTQ推荐的分组大小为128
    desc_act=False,  # 设置为False,可以显著加速推理,但模型困惑度可能会稍微变差
)


model = AutoGPTQForCausalLM.from_pretrained(model_path, quantize_config)
tokenizer = AutoTokenizer.from_pretrained(model_path)

traindataset, testenc = get_wikitext2_dataset(128, 0, 2048, tokenizer)


model.quantize(traindataset)


model.save_quantized(quant_path, use_safetensors=True)
tokenizer.save_pretrained(quant_path)

3.2 创建Shell脚本并执行

  1. 在 Terminal 中执行以下命令,创建 shell 脚本 qptq-quant.sh。请确保 qptq-quant.sh 与 qptq-quant.py 两个文件在同一层级目录。
cd /vemlp-demo-models/
touch gptq-quant.sh
  1. 编辑脚本内容,替换为需要配置的信息。
set  -ex
pip install git+https://gh-proxy.com/https://github.com/AutoGPTQ/AutoGPTQ.git@097dd04e2f
python3 gptq-quant.py
echo "Finished Model Quantization Task"
  1. 执行脚本。
cd /vemlp-demo-models/
bash ./gptq-quant.sh

执行完成后,输出路径文件如下。

3.3 量化后模型对比

  1. 在 Terminal 中执行以下命令,对量化前的基础模型和量化模型进行对比。
du -sh $BASE_MODEL_PATH $QUANT_MODEL_PATH

其中需要传入的参数列表说明如下:

参数描述
base_model_pathllama3-8b模型路径。
quant_model_path经过GPTQ量化后的模型路径。

对比结果如下:可见在模型容量上,经过 GPTQ 4bit 量化后模型大小约为量化前模型的1/3。

  1. 在 Terminal 中执行以下命令,对量化前后的 config.json 文件进行对比。
diff $QUANT_MODEL_PATH/config.json $BASE_MODEL_PATH/config.json

对比结果如下:可见量化后模型多了关于量化的信息 -- quantization_config。

步骤四:在自定义任务中执行量化

方式一:控制台

  1. 进入自定义任务控制台

  2. 配置环境

    1. 在自定义镜像处配置镜像。
    vemlp-demo-cn-shanghai.cr.volces.com/demo/quantization:1.0
    
    1. 填写入口命令。请注意 TOS 在开发机上挂载的路径与自定义任务中挂载的路径不一致,在入口命令填写数据集路径环境变量中填写模型路径时,需确保为自定义任务中挂载的路径。
    cat > gptq-quant.py <<EOF
    import os
    from transformers import AutoTokenizer
    from auto_gptq import AutoGPTQForCausalLM
    from auto_gptq import BaseQuantizeConfig
    
    def get_wikitext2_dataset(nsamples, seed, seqlen, tokenizer):
        import numpy as np
        import torch
        import torch.nn as nn
        from datasets import load_dataset
    
        traindata = load_dataset(dataset_path, split="train")
        testdata = load_dataset(dataset_path, split="test")
    
        trainenc = tokenizer("\n\n".join(traindata["text"]), return_tensors="pt")
        testenc = tokenizer("\n\n".join(testdata["text"]), return_tensors="pt")
    
        import random
    
        random.seed(seed)
        np.random.seed(0)
        torch.random.manual_seed(0)
    
        traindataset = []
        for _ in range(nsamples):
            i = random.randint(0, trainenc.input_ids.shape[1] - seqlen - 1)
            j = i + seqlen
            inp = trainenc.input_ids[:, i:j]
            attention_mask = torch.ones_like(inp)
            traindataset.append({"input_ids": inp, "attention_mask": attention_mask})
        return traindataset, testenc
    
    
    # 模型、数据集地址配置
    os.environ['BASE_MODEL_PATH'] = '/vemlp-demo-models/model-llama/Meta-Llama-3.1-8B'
    os.environ['CALIB_DATASET_PATH'] = '/vemlp-demo-models/datasets-llama-quant/'
    os.environ['QUANT_MODEL_PATH'] = '/vemlp-demo-models/model-quant-gptq'
    
    model_path = os.getenv('BASE_MODEL_PATH')
    dataset_path = os.getenv('CALIB_DATASET_PATH')
    quant_path = os.getenv('QUANT_MODEL_PATH')
    
    # 设置量化超参数
    quantize_config = BaseQuantizeConfig(
        bits=4,  # 使用GPTQ INT4量化
        group_size=128,  # GPTQ推荐的分组大小为128
        desc_act=False,  # 设置为False,可以显著加速推理,但模型困惑度可能会稍微变差
    )
    
    model = AutoGPTQForCausalLM.from_pretrained(model_path, quantize_config)
    tokenizer = AutoTokenizer.from_pretrained(model_path)
    
    traindataset, testenc = get_wikitext2_dataset(128, 0, 2048, tokenizer)
    
    model.quantize(traindataset)
    
    model.save_quantized(quant_path, use_safetensors=True)
    tokenizer.save_pretrained(quant_path)
    
    EOF
    
    pip install git+https://gh-proxy.com/https://github.com/AutoGPTQ/AutoGPTQ.git@097dd04e2f
    python3 gptq-quant.py
    

  1. 配置资源
    1. 选择合适的资源,最佳实践所用机器为单机 8 卡 ml.gni3cgd。

    2. 挂载 TOS 和 CFS。需要注意:tos在开发机上挂载的路径与自定义任务中挂载的路径不一致,在环境变量中填写模型路径时需确保为自定义任务中挂载的路径。

方式二:命令行

  1. 在 Terminal 中执行以下命令,编辑 gptq-quant.py。将开发机中的云盘访问路径变更为自定义任务中的访问路径。
import os
from transformers import AutoTokenizer
from auto_gptq import AutoGPTQForCausalLM
from auto_gptq import BaseQuantizeConfig

def get_wikitext2_dataset(nsamples, seed, seqlen, tokenizer):
    import numpy as np
    import torch
    import torch.nn as nn
    from datasets import load_dataset

    traindata = load_dataset(dataset_path, split="train")
    testdata = load_dataset(dataset_path, split="test")

    trainenc = tokenizer("\n\n".join(traindata["text"]), return_tensors="pt")
    testenc = tokenizer("\n\n".join(testdata["text"]), return_tensors="pt")

    import random

    random.seed(seed)
    np.random.seed(0)
    torch.random.manual_seed(0)

    traindataset = []
    for _ in range(nsamples):
        i = random.randint(0, trainenc.input_ids.shape[1] - seqlen - 1)
        j = i + seqlen
        inp = trainenc.input_ids[:, i:j]
        attention_mask = torch.ones_like(inp)
        traindataset.append({"input_ids": inp, "attention_mask": attention_mask})
    return traindataset, testenc

# 配置模型、数据集地址
os.environ['BASE_MODEL_PATH'] = '/data/model-llama-gptq/Meta-Llama-3.1-8B'
os.environ['CALIB_DATASET_PATH'] = '/data/datasets-llama-gptq/'
os.environ['QUANT_MODEL_PATH'] = '/data/model-quant-gptq'

model_path = os.getenv('BASE_MODEL_PATH')
dataset_path = os.getenv('CALIB_DATASET_PATH')
quant_path = os.getenv('QUANT_MODEL_PATH')

# 设置量化超参数
quantize_config = BaseQuantizeConfig(
    bits=4,  # 使用GPTQ INT4量化
    group_size=128,  # GPTQ推荐的分组大小为128
    desc_act=False,  # 设置为False,可以显著加速推理,但模型困惑度可能会稍微变差
)


model = AutoGPTQForCausalLM.from_pretrained(model_path, quantize_config)
tokenizer = AutoTokenizer.from_pretrained(model_path)

traindataset, testenc = get_wikitext2_dataset(128, 0, 2048, tokenizer)


model.quantize(traindataset)


model.save_quantized(quant_path, use_safetensors=True)
tokenizer.save_pretrained(quant_path)
  1. 在 Terminal 中执行以下命令,创建一个用于执行量化的自定义任务的 gptq-quantization-task.yaml 文件。
cd /vemlp-demo-models/
touch gptq-quantization-task.yaml
  1. 编辑量化任务提交的 yaml 文件。
TaskName:  "Quant-Meta-Llama-3-1-8B-Instruct-GPTQ-INT4"
Description:  "Use GPTQ to quantize Meta-Llama-3.1-8B-Instruct in INT4 format"
Entrypoint: |
    cd  /data && bash ./gptq-quant.sh

Tags: []

Envs: []

ResourceQueueID:  "q-**************"        #请替换为您自己的ResourceQueueID
Framework:  "PyTorchDDP"
TaskRoleSpecs:                                                              #请替换为您自己的TaskRoleSpecs
        - RoleName:  "worker"
            RoleReplicas: 1
            Flavor:  "custom"
            ResourceSpec:
                    Family:  "ml.gni3cgd"
                    CPU: 165.000
                    Memory: 865.000
                    GPUNum: 8

ActiveDeadlineSeconds: 3600

EnableTensorBoard: False

Storages:                                                                #请替换为您自己的Storages
        - Type:  "Tos"
            MountPath:  "/data"
            Bucket:  "vemlp-demo-models"
            FsName": "testmodel"
            MetaCacheExpiryMinutes: "-1"

ImageUrl: "vemlp-demo-cn-shanghai.cr.volces.com/demo/quantization:1.0"

CacheType: "Cloudfs"

RetryOptions:
        EnableRetry: False
        MaxRetryTimes: 5
        IntervalSeconds: 120
        PolicySets: []
  1. 在 Terminal 中执行以下命令,进行自定义任务提交。
volc ml_task submit --conf=/vemlp-demo-models/gptq-quantization-task.yaml
  1. 量化模型前后对比查看可参考上文。