利用QLoRA实现低配置微调llama3.2

目录:

  1. Llama3.2与QLoRA介绍
  2. Llama3.2预训练模型参数获取
  3. 微调数据集准备
  4. 微调训练脚本搭建
  5. 低配置友好的调参心得
  6. 低配置微调的局限性

1.Llama3.2与QLoRA介绍

Llama3.2

Llama是Meta开发的大语言模型系列,其采用自回归架构,可以用于文本生成、对话、代码编写等功能,并且完全开源且免费。目前,Meta已经发布了其最新的Llama大模型系列——Llama-3.2系列。在HuggingFace上面已经可以从Meta的主页下载到以下模型的训练参数:

Llama-3.2-1B

Llama-3.2-1B-Instruct

Llama-3.2-1B-evals

Llama-3.2-1B-Instruct-evals

Llama-3.2-3B

Llama-3.2-3B-Instruct

Llama-3.2-3B-Instruct-evals

本文将介绍适合低配置本地环境微调Llama-3.2-3B的流程。

QLoRA

直接在低配置本地环境对大模型进行微调,即使只选用参数量最小的Llama-3.2-1B,要实现也是较为困难的。但是,当引入QLoRA算法后,微调参数较大的Llama-3.2-3B,也成为了可能。

【什么是LoRA?】

我们知道,不论是在大模型的训练中,还是在基于大模型的微调上,最核心的部分就是更新模型的权重矩阵,例如注意力机制中的Wq,Wk,Wv等等,下文统称为W。然而,对于B(十亿)数量级以上的模型,由于使用了海量数据进行训练,其权重矩阵的参数数量非常庞大。若直接对上述的大模型进行微调,意味着每一次都需要对其巨大的权重矩阵做出调整。

我们知道,对于形状为mr的矩阵B和rn的矩阵A,其秩都为r.现在令一个矩阵ΔW=BA,那么ΔW的大小为m*n,秩为r.

通过这个启发,我们可以令权重矩阵W(典型Transformer中的W形状为in_dim*out_dim)的更新方式从直接更新W所有参数(h=Wx),变为如下方法:

将原始权重矩阵W₀冻结。

设置一个可学习的矩阵B,大小为in_dim*r.

设置一个可学习的矩阵A,大小为r*out_dim.

ΔW=BA

h=W₀+α*ΔW

(其中,α为LoRA算法中预设好的权重)

img

这样一来,在微调时只需更新低秩矩阵A和B(他们的秩r通常设置<=64),这极大减少了显存使用、加速了训练速度。

这样做可行的原因:

神经网络权重矩阵通常具有高度冗余、少数主要维度集中大部分信息、存在“内在低秩”的特点,而实验证明LoRA压缩方法能够有效地捕捉微调时低维子空间中的参数变化,即使使用较低的秩,LoRA也能逐步减少误差,使低秩矩阵适应性地学习最重要的变化方向。由此,LoRA看似“抛弃”了原权重矩阵中的大部分信息,实际上训练还是能够高效进行的。

【QLoRA方法】

QLoRA = 量化基础模型 + LoRA微调 + 内存优化

​ └─ NF4量化 └─ FP16参数 └─ 分页管理

QLoRA方法相比LoRA方法,不仅在训练过程中使用了低秩矩阵,还对基础模型的精度进行削减,使权重矩阵的数据大小得到大幅度减小,同时使用了分页管理、优化器状态管理的方法来进一步减少对显存的消耗。

img

全量微调、LoRA方法、QLoRA方法对比

以下是大致流程:

<1>已知W₀为fp16(或者fp32)量化,QLoRA方法将其转化为nf4量化

W₀ = dequantize(W₀_nf4)

冻结通过nf4量化压缩得到的W₀,这个新的矩阵的数据量只有原先的1/4。

<2>对W₀添加LoRA层,开始训练,流程同之前提到的LoRA方法,使用低秩矩阵的更新来进行训练(精度为FP16量化)。训练过程中分页管理、优化器状态管理开始生效。

<3>模型微调完成后,可以将NF4量化存储的W₀16反量化为FP16存储,这样就可以正常使用这个权重矩阵来进行生成工作。

2.Llama3.2预训练模型参数获取

要使用Llama模型的预训练参数与分词器需要Meta授权,获得授权的步骤如下:

<1>登录HuggingFace,打开Meta团队页面,可以看到一系列的Llama模型资源

img

<2>选择需要的Llama版本,这里使用的是Llama-3.2-3B,在跳转出的页面中可以看到这个按钮

img

点击,完成填表

img

等待Meta团队审核通过后,刷新页面可以看到

img

这就说明已经获取了Meta的授权,可以使用这个版本的Llama模型的预训练参数和分词器了。

<3>接下来创建一个token,如下图勾选

img

之后就可以通过这个token在代码中获取需要的文件。

3.微调数据集准备

在网络上可以找到丰富的微调用数据集,这里推荐从HuggingFace获取。

需要注意的是,对于Llama大模型的微调,其对数据集格式有所要求:

<1>数据集文件通常要为.json或者.jsonl后缀形式。

<2>若要有效地进行微调,使用的数据集最好按照特定的模式设置。数据集文件内容分为两种模式,分别为对话格式和Alpaca格式.当然,字段名不同,但大体形式相同的数据集也可以使用,并非严格限定。

<3>仅限本文微调的3B模型来说:由于显存紧张、要求训练轮数比较少,因此最好使用质量较高的数据集,数据文件控制在20MB以内,否则会出现欠拟合现象。

[对话格式]

必须包含“conversation”字段数组,“conversation”字段数组中必须包含多组“from”和“value”字段,from 字段值只能是 "assistant"等能表明身份的词。

例如:

{
    "conversations": [  # 必需字段:对话数组
        {
            "from": "human",     # 必需字段:说话者身份
            "value": "问题内容"   # 必需字段:具体内容
        },
        {
            "from": "assistant", # 必需字段:说话者身份
            "value": "回答内容"   # 必需字段:具体内容
        }
    ]
}

[Alpaca格式]

必须包含“instruction”和“output”字段,可以包含“input”和“message”字段。

例如:

{
    "instruction": "任务指令",    # 必需字段:指令/任务描述
    "input": "输入内容",          # 可选字段:补充输入
    "output": "期望的输出内容"     # 必需字段:任务的答案/输出
}

4.微调训练脚本搭建

HuggingFace为模型微调提供了一套非常好用的库,下面的训练脚本将用主要使用HuggingFace的核心库transformers和datasets,同时还会使用到启用QLoRA的peft库和大模型工作必需的torch库。

值得说明的是,HuggingFace和QLoRA对其库都有详细的使用手册,读者完全可以通过阅读手册尝试自行编写训练脚本,当然,也可以按照下面的流程快速搭建脚本(推荐使用Jupyter搭建,便于逐步检查代码可行性):

训练环境:12GB显存

python版本:3.9

<1>首先导入必要的库,登录HuggingFace,并启用GPU

from datasets import load_dataset
from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments, Trainer
import torch
from huggingface_hub import login
import os #导入os库以本地保存一些预处理好的数据、模型训练参数,方便下次使用

login("Token")#Tokens替换为从HuggingFace上面生成的Token
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

<2>获取需要的文件

在HuggingFace任意一个数据集页面中,都可以看到如何使用此数据集

img

# 依照提示加载数据
dataset = load_dataset("bavest/fin-llama-dataset")
# 此处仅举例,可以换成任意所需的数据集

# 分割数据集为训练集和验证集
# 训练集和验证集的比例通常为9:1或者8:2
dataset = dataset["train"].train_test_split(test_size=0.1)
train_dataset = dataset["train"]
test_dataset = dataset["test"]

# 打印数据集以确认格式
print("测试集样本:", test_dataset[0])
print("训练集样本:", train_dataset[0])

# 加载分词器
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.2-3B")

# 设置pad_token
if tokenizer.pad_token is None:
    tokenizer.pad_token = tokenizer.eos_token

需要说明的是,由于Llama 等一些模型默认没有设置 pad_token(pad_token是用于填充序列的标记,保证一个批次(batch)中的所有序列长度相同),这可能会在批处理和训练时造成问题,因此可以将pad_token设置为eos_token。

<3>数据预处理

这里使用的数据集有三个字段"instruction"“output”"text"希望被使用,

使用Llama3.2-3B的tokenizer来对数据集进行token化。

一步一步编写下来即可

def preprocess_function(examples):
    # 拼接 instruction 和 text 字段作为输入
    inputs = [inst + "\n" + txt for inst, txt in zip(examples['instruction'], examples['text'])]
    outputs = examples['output']  # 模型需要生成的内容

    # 对输入进行分词
    model_inputs = tokenizer(inputs, max_length=256, truncation=True, padding='max_length')

    # 对输出进行分词,作为标签
    with tokenizer.as_target_tokenizer():
        labels = tokenizer(outputs, max_length=256, truncation=True, padding='max_length')

    # 将分词后的标签添加到模型输入中
    model_inputs['labels'] = labels['input_ids']
    return model_inputs


# 检查预处理后的数据集是否存在
if os.path.exists(train_dataset_path) and os.path.exists(test_dataset_path):
    # 加载预处理后的数据集
    train_dataset = load_from_disk(train_dataset_path)
    test_dataset = load_from_disk(test_dataset_path)
else:
# 将数据集映射到预处理函数
train_dataset = train_dataset.map(preprocess_function, batched=True)
test_dataset = test_dataset.map(preprocess_function, batched=True)

# 打印预处理后的数据集示例
print("预处理后的训练集样本:", train_dataset[0])

# 数据集文件路径
train_dataset_path = 'preprocessed_train_dataset'
test_dataset_path = 'preprocessed_test_dataset'

# 保存预处理后的数据集
train_dataset.save_to_disk(train_dataset_path)
test_dataset.save_to_disk(test_dataset_path)

<4>QLoRA配置,同样,手册给出了详细的配置方法

### 加载预训练模型并启用QLoRA
from peft import LoraConfig, get_peft_model
from transformers import BitsAndBytesConfig

# 配置4-bit量化
quantization_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_use_double_quant=True,
    bnb_4bit_compute_dtype=torch.float16
)

# 加载预训练模型(启用4-bit量化)
model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3.2-3B",
    quantization_config=quantization_config,
    device_map="auto",
)

# 配置QLoRA(LoRA参数)
lora_config = LoraConfig(
    r=8,  # LoRA 低秩参数
    lora_alpha=16,  # LoRA 权重因子
    target_modules=["q_proj", "v_proj"],  # 只在q_proj和v_proj上应用LoRA
    lora_dropout=0.1,  # LoRA dropout
    bias="none",  # 不训练偏置
    task_type="CAUSAL_LM"  # 自回归语言模型任务
)
# 将LoRA应用到模型
model = get_peft_model(model, lora_config)

# 检查LoRA参数
model.print_trainable_parameters()

<5>训练参数配置、优化器设置

以下参数设置仅供参考,要结合本地测试以及需求来调节参数

除此之外,还使用了torch优化器AdamW和Flash Attention(这两项可选)

# 按照手册配置训练参数
training_args = TrainingArguments(
    output_dir="./results",  # 保存模型的路径,可以自己指定
    eval_strategy="epoch",  # 每个epoch进行评估
    learning_rate=2e-4,  # QLoRA通常需要更高的学习率
    warmup_ratio=0.03,  # 学习率预热比例
    per_device_train_batch_size=8,# 每个设备的训练batch大小
    per_device_eval_batch_size=8,  # 每个设备的评估batch大小
    num_train_epochs=50,  # 训练的epoch数量
    weight_decay=0.01,  # 权重衰减
    logging_dir='./logs',  # 日志保存路径
    logging_steps=10,  # 每10步记录一次日志
    save_total_limit=2,  # 最多保存2个检查点
    save_steps=20,  # 每500步保存一次检查点
    fp16=True,  # 启用混合精度训练
    gradient_accumulation_steps=4,  # 梯度累积
    gradient_checkpointing=True, # 启用梯度检测
    optim="adamw_torch"   # 使用torch优化器,可选
)

from torch.optim import AdamW

# 初始化优化器 可选
optimizer = AdamW(model.parameters(), lr=5e-4, weight_decay=0.01)

# 按照手册初始化Trainer对象
trainer = Trainer(
    model=model,  
    args=training_args,  
    train_dataset=train_dataset,  
    eval_dataset=test_dataset, 
    optimizers=(optimizer, None)  
)

#  使用flash attention (如果模型支持)可选
model.config.use_flash_attention = True

<6>开始训练

# 调用trainer对象的train方法来开始训练
trainer.train()

# 注意保存训练结果
model.save_pretrained("./results/finetuned_model")
tokenizer.save_pretrained("./results/finetuned_model")

5.低配置友好调参心得

在实际训练过程中,一些参数的配置对训练速度影响非常大,下面给出简要的调参心得:

<1>最大序列长度

在预处理函数preprocess_function中,max_length的设置会显著影响显存使用,max_length越大,训练步数越少,显存占用最大。通过实践,对于12GB的GPU,本文建议设置为256,因为3B预训练模型的微调通常上只能实现较为简单的推理问题,256的序列长度就足够。序列小于256会显著降低模型的性能,大于256,例如使用512的序列长度,会导致显存告急,一旦显存爆满,批处理将会变无比缓慢,训练几乎无法进行。

<2>批次长度

在training_args中,per_device_train_batch_size和per_device_eval_batch_size对显存占用的影响是最大的。

就调参方法本文给出两个建议:

(1)保证per_device_train_batch_size和per_device_eval_batch_size的大小不要小于8,如果小于8,过短的批次长度那么很可能会使loss值无法下降。若两个参数等于8仍然无法进行训练,可以考虑调整最大序列长度和QLoRA的低秩r的大小。

(2)调参时观察显存占用情况,确保显存被充分使用,加快训练过程。若发现显存爆满(若发现开始占用共享GPU内存,就说明显存爆满),即使只是很小程度地利用内存充当显存,也要及时停机调参。由于内存频率和带宽相较于显存非常低,加上GPU到内存的通信延时,即使是很小程度的显存爆满也会导致批处理变得异常缓慢。

<3>低秩r

在lora_config中,低秩r的大小也会显著影响显存占用,这很直观,因为其决定了低秩权重矩阵AB的大小,建议设置为4~64,r小于4可能会导致插入的低秩矩阵容量不足,无法有效捕获任务相关的特征,而大于64之后r增大的收益十分微小,并且会增大显存占用。

<4>应用QLoRA的目标矩阵

注意到lora_config中的config_modules,这决定了参与训练的权重矩阵有哪些,如如 q, k, v, o 或 FFN 的某些权重,对于低配置环境,指定q和k权重矩阵进行训练足够,并且对能够减少显存的占用。

6.低配置环境局限性

最后,如果在所有配置都达到最低限度的情况下仍不能实现对1B模型的微调,或者是微调效果很差,考虑此方法的局限性:

(1)无法有效利用太大或者质量不高的数据集。

(2)无法进行任务过于复杂的微调。例如微调出一个简单的法律问答模型这是可行的,但如果是利用CoT方法微调一个数学解题模型,7B以上的大模型+算力更高的云平台更加适合。

如何学习大模型

现在社会上大模型越来越普及了,已经有很多人都想往这里面扎,但是却找不到适合的方法去学习。

作为一名资深码农,初入大模型时也吃了很多亏,踩了无数坑。现在我想把我的经验和知识分享给你们,帮助你们学习AI大模型,能够解决你们学习中的困难。

下面这些都是我当初辛苦整理和花钱购买的资料,现在我已将重要的AI大模型资料包括市面上AI大模型各大白皮书、AGI大模型系统学习路线、AI大模型视频教程、实战学习,等录播视频免费分享出来,需要的小伙伴可以扫取。

一、AGI大模型系统学习路线

很多人学习大模型的时候没有方向,东学一点西学一点,像只无头苍蝇乱撞,我下面分享的这个学习路线希望能够帮助到你们学习AI大模型。

在这里插入图片描述

二、AI大模型视频教程

在这里插入图片描述

三、AI大模型各大学习书籍

在这里插入图片描述

四、AI大模型各大场景实战案例

在这里插入图片描述

五、结束语

学习AI大模型是当前科技发展的趋势,它不仅能够为我们提供更多的机会和挑战,还能够让我们更好地理解和应用人工智能技术。通过学习AI大模型,我们可以深入了解深度学习、神经网络等核心概念,并将其应用于自然语言处理、计算机视觉、语音识别等领域。同时,掌握AI大模型还能够为我们的职业发展增添竞争力,成为未来技术领域的领导者。

再者,学习AI大模型也能为我们自己创造更多的价值,提供更多的岗位以及副业创收,让自己的生活更上一层楼。

因此,学习AI大模型是一项有前景且值得投入的时间和精力的重要选择。

<think>嗯,用户想要微调unsloth/llama-3.2-1b-instruct-bnb-4bit模型,我需要先理解他们的需求。首先,这个模型是基于Llama 3.2架构的1B参数版本,并且已经使用了4位量化技术,可能是通过BitsAndBytes库实现的。用户可能希望在自己的数据集上进行微调,以适应特定的任务,比如指令跟随或者领域特定问题。 接下来,我需要回忆一下微调量化模型的一般步骤。通常,使用QLoRA(Quantized Low-Rank Adaptation)方法可以在保持模型量化的同时,通过低秩适配器进行微调,这样可以节省内存而不影响太多性能。不过,用户提到的模型名称中有“bnb-4bit”,这可能意味着模型已经用BitsAndBytes的4位量化进行了预处理,所以可能需要检查是否支持进一步的微调。 然后,我需要考虑用户可能使用的工具。他们提到了unsloth这个库,可能是一个优化训练速度的库,比如Unsloth专注于高效微调,减少内存使用并加速训练过程。因此,在回答中需要结合unsloth和BitsAndBytes的使用方法。 接下来,步骤应该是环境准备,安装必要的库,比如unsloth、transformers、bitsandbytes等。然后加载模型,这里可能需要使用FastLanguageModel.from_pretrained方法,并指定load_in_4bit=True来保持4位量化状态。同时,需要配置LoRA参数,添加适配器层。 数据准备部分,用户需要提供自己的数据集,并格式化为模型接受的输入,比如指令-响应对。训练参数方面,学习率、批量大小、优化器选择(如AdamW)都是关键点。使用Hugging Face的Trainer类来简化训练流程,同时启用梯度检查点和4位量化训练可以节省资源。 验证和保存模型部分,确保模型在测试集上表现良好,并正确保存适配器权重,以便后续加载使用。最后,生成相关问题,帮助用户进一步理解微调中的其他考虑因素,比如数据集处理、超参数调整、评估方法以及量化模型微调的限制。 需要确保所有步骤中的代码示例正确,特别是模型加载和训练循环部分,引用的文献要对应到用户提供的参考内容。同时,提醒用户注意硬件要求和可能的常见错误,比如内存不足或版本兼容性问题。</think>以下是如何微调`unsloth/llama-3.2-1b-instruct-bnb-4bit`模型的逐步指南: ### 一、环境准备 1. 安装必要库(需满足版本兼容性): ```bash pip install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git" pip install transformers==4.40.0 bitsandbytes==0.43.1 accelerate==0.29.3 ``` ### 二、模型加载 ```python from unsloth import FastLanguageModel model, tokenizer = FastLanguageModel.from_pretrained( model_name = "unsloth/llama-3.2-1b-instruct-bnb-4bit", max_seq_length = 4096, dtype = None, load_in_4bit = True, # 保持4位量化状态[^2] token = "hf_your_token", # HuggingFace访问令牌 ) ``` ### 三、配置LoRA适配器 ```python model = FastLanguageModel.get_peft_model( model, r=16, # LoRA秩 target_modules=["q_proj", "k_proj", "v_proj", "o_proj"], lora_alpha=16, lora_dropout=0.1, bias="none", use_gradient_checkpointing=True, # 激活梯度检查点[^1] ) ``` ### 四、数据准备 需准备JSON格式数据集(示例结构): ```json [ { "instruction": "解释量子计算", "input": "", "output": "量子计算利用量子力学原理..." }, { "instruction": "翻译为法语", "input": "你好,世界", "output": "Bonjour le monde" } ] ``` ### 五、训练配置 ```python from transformers import TrainingArguments training_args = TrainingArguments( output_dir="./results", per_device_train_batch_size=2, gradient_accumulation_steps=4, learning_rate=2e-5, num_train_epochs=3, fp16=True, # 混合精度训练 logging_steps=10, optim="adamw_8bit", # 8位优化器[^2] save_strategy="epoch", ) ``` ### 六、执行训练 ```python from trl import SFTTrainer trainer = SFTTrainer( model=model, train_dataset=dataset, dataset_text_field="text", max_seq_length=4096, tokenizer=tokenizer, args=training_args, ) trainer.train() ``` ### 七、模型保存与验证 ```python model.save_pretrained_merged("llama-3.2-1b-finetuned", tokenizer, save_method="merged_4bit") ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值