PEFT库进行ChatGLM3-6B模型QLORA高效微调
QLORA微调ChatGLM3-6B模型
LoRA的核心思想是将可调整的低秩矩阵注入到Transformer架构的每一层中,充当"适配器"的作用。这样可以使模型针对特定任务进行调整和专门化,同时最大限度地减少额外的参数数量,提高参数效率。
QLoRA是LoRA的扩展版本,在微调过程中引入了量化技术,以进一步提高参数效率。QLoRA利用LoRA的原理,并引入了4位NormalFloat(NF4)量化和双重量化技术,进一步减少了存储和计算资源的使用。
安装相关库
pip install datasets==2.17.0 pandas transformers==4.37.2 peft==0.8.0 accelerate==0.27.0 bitsandbytes autoawq optimum
使用ChatGLM3-6B
直接调用ChatGLM3-6B模型来生成对话
from transformers import AutoTokenizer, AutoModel
model_id = "/root/work/chatglm3-6b"
tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
#model = AutoModel.from_pretrained(model_id, trust_remote_code=True).half().cuda()
model = AutoModel.from_pretrained(model_id, trust_remote_code=True, device='cuda')
model = model.eval()
response, history = model.chat(tokenizer, "你好", history=history)
print(response)
模型GPU显存占用
默认情况下,模型以半精度(float16)加载,模型权重需要大概 13GB显存。
获取当前模型占用的GPU显存
memory_bytes = model.get_memory_footprint()
# 转换为GB
memory_gb = memory_bytes / (1024 ** 3)
print(f"{
memory_gb :.2f}GB")
注意:
与实际进程占用有差异,差值为预留给PyTorch的显存
准备数据集
准备数据集其实就是指令集构建,LLM的微调一般指指令微调过程。所谓指令微调,就是使用的微调数据格式、形式。
训练目标是让模型具有理解并遵循用户指令的能力。因此在指令集构建时,应该针对目标任务,针对性的构建任务指令集。
[
{
"instruction": "用户指令(必填)",
"input": "用户输入(选填)",
"output": "模型回答(必填)",
}
]
instruction:用户指令,告知模型其需要完成的任务
input:用户输入,是完成用户指令所必须的输入内容
output:模型回答,模型应该给出的输出
这里根据企业私有文档数据,生成相关格式的训练数据集,大概格式如下:
[
{
"instruction": "内退条件是什么?",
"input": "",
"output": "内退条件包括与公司签订正式劳动合同并连续工作满20年及以上,以及距离法定退休年龄不足5年。特殊工种符合国家相关规定可提前退休的也可在退休前5年内提出内退申请。"
},
]
作者:CodeDevMaster
链接:https://juejin.cn/post/7384636970033938482
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
加载数据集
from datasets import load_dataset # 导入 load_dataset 函数
# 加载处理好的训练数据集
dataset = load_dataset("json", data_files="./train_data.json")
print(dataset) # 打印加载的数据集对象
DatasetDict({
train: Dataset({
features: ['instruction', 'output'],
num_rows: 20182
})
})
数据处理
Lora训练数据是需要经过tokenize编码处理,然后后再输入模型进行训练。一般需要将输入文本编码为input_ids,将输出文本编码为labels,编码之后的结果都是多维的向量。
加载AutoTokenizer
from transformers import AutoTokenizer # 导入 AutoTokenizer 类
# 使用 AutoTokenizer 类的 from_pretrained 方法加载指定模型的 tokenizer
tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm3-6b", trust_remote_code=True)
需要定义一个预处理函数,这个函数用于对每一个样本,编码其输入、输出文本并返回一个编码后的字典。
# tokenize_func 函数
def tokenize_func(example, tokenizer, ignore_label_id=-100):
"""
对单个数据样本进行tokenize处理。
参数:
example (dict): 包含'content'和'summary'键的字典,代表训练数据的一个样本。
tokenizer (transformers.PreTrainedTokenizer): 用于tokenize文本的tokenizer。
ignore_label_id (int, optional): 在label中用于填充的忽略ID,默认为-100。
返回:
dict: 包含'tokenized_input_ids'和'labels'的字典,用于模型训练。
"""
prompt_text = '' # 所有数据前的指令文本
max_input_length = 512 # 输入的最大长度
max_output_length = 1536 # 输出的最大长度
# 构建问题文本
question = prompt_text