使用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 
  • 18
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeDevMaster

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值