文章目錄

  • 實戰量化Facebook OPT模型
  • Facebook OPT模型介紹
  • auto-gptq方式量化
  • 1、定義量化配置
  • 2、加載模型量化
  • 3、檢查量化正確性
  • 4、保存量化後的模型權重
  • 5、使用量化模型進行文本生成
  • 6、使用自定義的數據集進行量化
  • autoawq方式量化
  • 0、未量化時測試文本生成任務
  • 1、加載模型
  • 2、量化模型
  • 3、Transformers 兼容性配置
  • 4、保存模型權重
  • 5、加載使用量化模型
  • BitsAndBytes(BnB)方式量化
  • 1、介紹
  • 2、使用load加載模型量化使用
  • 1、加載
  • 2、查看加載耗盡的GPU顯存
  • 3、使用模型
  • 3、使用NF4方式加載模型量化使用
  • 4、使用雙重量化加載模型
  • 5、使用 QLoRA 所有量化技術加載模型

實戰量化Facebook OPT模型

Facebook OPT模型介紹

facebook/opt-2.7b 是 Meta AI 發佈的 OPT 系列模型中的一個成員。OPT 的全稱是 Open Pre-trained Transformer,其核心目標是為研究社區提供一個與 GPT-3 性能和規模相當,但完全開放(開源代碼和權重)的預訓練語言模型

auto-gptq方式量化

1、定義量化配置

通常有兩種方式構造數據集:

  • 量化器支持的默認數據集(包括 [‘wikitext2’, ‘c4’, ‘c4-new’, ‘ptb’, ‘ptb-new’])
  • 一個字符串列表(這些字符串將被用作數據集)
from transformers import AutoMode1ForCausalLM, AutoTokenizer, GPTQConfig
import torch

model_name_or_path = "facebook/opt-2.7b"

quantization_config = GPTQConfig(
    bits=4, # 量化精度
    group_size=128,
    dataset="wikitext2",
    desc_act=False,
)

2、加載模型量化

quant_model = AutoMode[ForCausalM.from_pretrained(
    model_name_or_path,
    quantization_config=quantization_config,
    device_map='auto')

3、檢查量化正確性

通過檢查模型的線性層屬性來驗證量化是否成功:

quant_model.model.decoder.layers[0].self_attn.q_proj.__dict__

正確量化的模型應該包含以下特殊屬性:這些屬性是GPTQ量化特有的,在原始FP32模型中不存在,屬性的存在表明模型已成功轉換為量化格式,可以使用更少的內存進行推理

  1. qweight - 量化後的權重
  • 數據類型:torch.int32
  • 存儲壓縮後的4位權重數據
  1. qzeros - 量化零點
  • 數據類型:torch.int32
  • 用於反量化計算
  1. scales - 縮放因子
  • 數據類型:浮點數
  • 用於將量化值轉換回原始數值範圍

4、保存量化後的模型權重

# 保存模型權重
quant_model.save_pretrained("models/opt-2.7b-gptq")

5、使用量化模型進行文本生成

# 使用 GPU 加載模型並生成文本
tokenizer = AutoTokenizer.from_pretrained(model_name_or_path)

text = "Merry Christmas! I'm glad to"
inputs = tokenizer(text, return_tensors="pt").to(0)

out = quant_model.generate(**inputs, max_new_tokens=64)
print(tokenizer.decode(out[0], skip_special_tokens=True))

輸出

Merry Christmas! I'm glad to see you're still here.
Thank you! I'm glad to be here too.

6、使用自定義的數據集進行量化

使用自定義數據集量化模型,靈活可擴展,前提是準備好數據,如果使用很少的數據會影響模型性能,建議樣本數不少於128,如下使用一句話作為數據集,使模型性能變得很差。

from transformers import AutoModelForCausalLM, GPTQCConfig, AutoTokenizer

model_name_or_path = "facebook/opt-2.7b"
custom_dataset = ["auto-gptq is an easy-to-use model quantization library with user-friendly apis, based on GPTQ at 1"]
custom_quantization_config = GPTQCConfig(
    bits=4,
    group_size=128,
    desc_act=False,
    dataset=custom_dataset
)
custom_quant_model = AutoModelForCausalLM.from_pretrained(model_name_or_path,
    quantization_config=custom_quantization_config,
    torch_dtype=torch.float16,
    device_map="auto")

相比使用默認數據集,未經精心準備的自定義數據集會明顯降低模型性能

text = "Merry Christmas! I'm glad to"
inputs = tokenizer(text, return_tensors="pt").to(0)

out = custom_quant_model.generate(inputs, max_new_tokens=64)
# 輸出的內容會很差
print(tokenizer.decode(out[0], skip_special_tokens=True))

autoawq方式量化

0、未量化時測試文本生成任務

from transforms import pipeline

model_path = "facebook/opt-125m"

# 使用 GPU 加載原始的 OPT-125m 模型
generator = pipeline('text-generation',
    model=model_path,
    device=0,
    do_sample=True, # 自動跑他的樣例
    num_return_sequences=3)

1、加載模型

from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer

# 定義路徑和配置
model_path = "facebook/opt-2.7b"  # 原始模型路徑
quant_path = "models/opt-2.7b-awq"  # 量化後保存路徑
quant_config = {"zero_point": True, "q_group_size": 128, "w_bit": 4, "version": "GEMM"}

# 加載模型和分詞器
model = AutoAWQForCausalLM.from_pretrained(model_path, device_map="cuda")
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)

2、量化模型

model.quantize(tokenizer, quant_config=quant_config)

3、Transformers 兼容性配置

為了使 quant_config 與 transformers 兼容,我們需要修改配置文件:使用 Transformers.AwqConfig 來實例化量化模型配置

from transformers import AwqConfig, AutoConfig

# 修改配置文件以使其編譯到transformers集成兼容
quantization_config = AwqConfig(
    bits=quant_config["w_bit"],
    group_size=quant_config["q_group_size"],
    zero_point=quant_config["zero_point"],
    version=quant_config["version"].lower(),
).to_dict()

# 預訓練的transformers模型存儲在model屬性中,我們需要傳遞一個字典
model.model.config.quantization_config = quantization_config

4、保存模型權重

model.save_quantized(quant_path)
tokenizer.save_pretrained(quant_path)  # 保存分詞器

5、加載使用量化模型

from transformers import AutoTokenizer, AutoModelForCausalLM

tokenizer = AutoTokenizer.from_pretrained(quant_path)
model = AutoModelForCausalLM.from_pretrained(quant_path, device_map="cuda").to(0)

def generate_text(text):
    inputs = tokenizer(text, return_tensors="pt").to(0)

    out = model.generate(inputs, max_new_tokens=64)
    return tokenizer.decode(out[0], skip_special_tokens=True)

result = generate_text("Merry ChristrHS! I'm glad to")
print(result)

BitsAndBytes(BnB)方式量化

1、介紹

bitsandbytes 是將模型量化為8位和4位的最簡單選擇。

2、使用load加載模型量化使用

1、加載

使用 Transformers 庫的 model.from_pretrained() 方法中的 load_in_8bit 或 load_in_4bit 參數,便可以對模型進行量化。只要模型支持使用Accelerate加載幷包含torch.nn.Linear層,這幾乎適用於任何模態的任何模型。

from transformers import AutoModelForCausalLM

model_id = "facebook/opt-2.7b" 

model_4bit = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", load_in_4bit=True)
2、查看加載耗盡的GPU顯存

計算 GPU 內存佔用(使用 PyTorch 模型)

memory_footprint_bytes = model_4bit.get_memory_footprint()
memory_footprint_mib = memory_footprint_bytes / (1024 ** 2) # 轉換為 MiB

print(f"{memory_footprint_mib:.2f}MiB")
3、使用模型
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained(model_id)
text = "Merry Christmas! I'm glad to"
inputs = tokenizer(text, return_tensors="pt").to(0)

out = model_4bit.generate(inputs, max_new_tokens=64)
print(tokenizer.decode(out[0], skip_special_tokens=True))

3、使用NF4方式加載模型量化使用

from transformers import BitsAndBytesConfig

nf4_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
)

model_nf4 = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=nf4_config)

# 獲取當前模型佔用的 GPU顯存(差值為預留給 PyTorch 的顯存)
memory_footprint_bytes = model_nf4.get_memory_footprint()
memory_footprint_mib = memory_footprint_bytes / (1024 ** 2) # 轉換為 MiB

print(f"{memory_footprint_mib:.2f}MiB")

4、使用雙重量化加載模型

# 使用雙重量化加載模型

double_quant_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
)

model_double_quant = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=double_quant_config)

# 獲取當前模型佔用的 GPU 內存(差值為預留給 PyTorch 的顯存)
memory_footprint_bytes = model_double_quant.get_memory_footprint()
memory_footprint_mib = memory_footprint_bytes / (1024 ** 2) # 轉換為 MiB

print(f"{memory_footprint_mib:.2f}MiB")

5、使用 QLoRA 所有量化技術加載模型

# 使用 QLoRA 所有量化技術加載模型

import torch

qlora_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16
)

model_qlora = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=qlora_config)

# 獲取當前模型佔用的 GPU 顯存(差值為預留給 PyTorch 的顯存)
memory_footprint_bytes = model_qlora.get_memory_footprint()
memory_footprint_mib = memory_footprint_bytes / (1024 ** 2) # 轉換為 MiB

print(f"{memory_footprint_mib:.2f}MiB")