一、LoRA微调
1. 什么是LoRA微调
LoRA微调的全程是Low-Rank Adaptation,这种方法通过引入低秩矩阵分解,可以通过仅训练少量参数实现大模型的适配。
2. 全参数微调的缺陷
2.1 训练成本高
全参数微调,需要更新千亿甚至万亿级别的参数,会消耗大量计算资源,为了调整海量参数时不跑偏,还需要准备相当规模的数据集,费时费力。
2.2 训练时间长
全参数微调训练时间会比较长,有些场合需要快速迭代,跟不上业务的节奏
2.3 灾难性遗忘
全参数微调需要根据新任务,调整和重构预训练模型的所有参数,有可能导致原有的知识表征被破坏,导致新任务上表现虽好,但是旧任务上的表现急剧下降,这就是大模型的灾难性遗忘。
3 LoRA微调怎样避免这些问题?
需要训练一个巨大的参数矩阵$W{M*N}$,为了避免灾难性遗忘,训练的时候,我们不能调整原始矩阵,而是要调整一个同样大小的矩阵$ΔW{MN}$,使得推理时可以用$W_{MN}+αΔW{M*N}$代替原来的$W{M*N}$。
此时训练的参数量仍未M*N,如何改善?机器学习里的PCA使用过一个思路:矩阵分解。很多算法都使用类似的方法降低计算量(潜在语义分析LSA,推荐系统里的协同过滤)
Lora微调不是真正地训练一个巨大的矩阵$ΔW{M*N}$,而是训练两个小型矩阵$A{Mr}$和$B_{rN}$,使得$A{Mr}B{rN}≈ΔW_{MN}$,只要这两个结果足够近似,在工程上就是可行的。
如果r远小于M 、N,就可以极大地压缩参数量。假设M=300000,N=500000,那么$ΔW{MN}$的总参数量为MN=1500亿。如果取r=16,那么$A{Mr}$的参数量为Mk=480万,同理$B{rN}$的参数量为kN=800万,总参数量为1280万,仅为$ΔW{M*N}$总参数量的0.000085,即不到万分之一。
4 实际做法
- 每个transformer都添加低秩旁路
- 矩阵A高斯初始化
- 矩阵B初始化为全0矩阵
二、获取基座模型
1、搜索想要的模型:
huggingface
modelscope
2、 使用–local_dir指定本地存储位置
modelscope download --model Qwen/Qwen2.5-3B-Instruct-GPTQ-Int4 --local_dir /workspace/deepseekDistllation/models/Qwen/Qwen2.5-3B-Instruct-GPTQ-Int4
三、 使用训练工具LLaMA-Factory
1、 LLaMA-Factory简介
实际工作中,会用一些工具提升工作效率。LLaMA-Factory 是一个封装比较完善的LLM微调工具,可以仅使用命令行与web UI 微调大模型,对微调工作提供了各种支持。
1、支持的模型:
LLaMA、LLaVA、Mistral、Mixtral-MoE、Qwen、Qwen2-VL、DeepSeek、Yi、Gemma、ChatGLM、Phi 等等100+。
2、集成方法:
(增量)预训练、(多模态)指令监督微调、奖励模型训练、PPO 训练、DPO 训练、KTO 训练、ORPO 训练等等。
3、多种精度:
16 bit全参数微调、冻结微调、LoRA 微调和基于 AQLM/AWQ/GPTQ/LLM.int8/HQQ/EETQ 的 2/3/4/5/6/8 比特 QLoRA 微调。
4、先进算法:
GaLore、BAdam、APOLLO、Adam-mini、DoRA、LongLoRA、LLaMA Pro、Mixture-of-Depths、LoRA+、LoftQ 和 PiSSA。
5、git地址:
https://github.com/hiyouga/LLaMA-Factory
2 环境搭建
2.1 创建虚拟环境
conda create --name llamafactory-3.11 python==3.11
conda activate llamafactory-3.11
2.2 拉代码安装
git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git
cd LLaMA-Factory
pip install -e ".[torch,metrics]"
如果报错:No matching distribution found for setuptools>=61.0
pip install -r requirements.txt -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
pip install --no-build-isolation --no-index --find-links=./ --no-deps -e ".[torch,metrics]"
2.3 追加两个包
pip install auto_gptq optimum
3 LLaMA-Factory的使用
3.1 使用webui
在Anaconda Prompt中输入以下命令
conda activate llamafactory-3.11
llamafactory-cli webui
如果报错:argument of type ‘bool’ is not iterable
pip install pydantic==2.10.6
本地操作系统,启动后在浏览器上输入 http://localhost:7860,进入webui页面
3.2 使用命令行训练
llamafactory-cli train \
--stage sft \
--do_train True \
--model_name_or_path /workspace/deepseekDistllation/models/Qwen/Qwen2.5-3B-Instruct-GPTQ-Int4 \
--preprocessing_num_workers 16 \
--finetuning_type lora \
--template qwen \
--flash_attn auto \
--dataset_dir /workspace/deepseekDistllation/data/chatData \
--dataset chat-train \
--cutoff_len 6000 \
--learning_rate 0.0001 \
--num_train_epochs 1.0 \
--max_samples 100000 \
--per_device_train_batch_size 2 \
--gradient_accumulation_steps 2 \
--lr_scheduler_type cosine \
--max_grad_norm 1.0 \
--logging_steps 5 \
--save_steps 100 \
--warmup_steps 10 \
--packing False \
--report_to none \
--output_dir /workspace/deepseekDistllation/models/lora/Qwen2.5-3B-instruct-GPTQ-Int4/train_2025-04-22-07-55-05 \
--bf16 True \
--plot_loss True \
--trust_remote_code True \
--ddp_timeout 180000000 \
--include_num_input_tokens_seen True \
--optim adamw_torch \
--quantization_bit 4 \
--quantization_method bitsandbytes \
--double_quantization True \
--lora_rank 16 \
--lora_alpha 16 \
--lora_dropout 0 \
--lora_target all
四、训练过程
1 指定基座模型
模型名称:Qwen2.5-3B-Instruct-GPTQ-Int4
模型路径:/workspace/deepseekDistllation/models/Qwen/Qwen2.5-3B-Instruct-GPTQ-Int4
2 指定数据集
数据路径:/workspace/deepseekDistllation/data/chatData
数据集:chat-train
3 指定训练的基本性质
微调方法:LoRA
量化等级:4
训练阶段:Supervised fine-tuning
4 指定重要参数
学习率:1e-4 或者 5e-5
截断长度:6000
训练轮数:1.0
批处理大小:1
梯度累计:2
预热步数:10
LoRA的秩:8
LoRA缩放系数:16
LoRA随机丢弃:0.1
5 指定训练完成后的模型存储位置
/workspace/deepseekDistllation/models/lora/Qwen2.5-3B-instruct-GPTQ-Int4/
6 点击开始按钮,开始训练
五、检查训练效果
1 加载基座模型
CUDA_VISIBLE_DEVICES=0 API_PORT=8000 llamafactory-cli api \
--model_name_or_path /workspace/deepseekDistllation/models/Qwen/Qwen2.5-3B-Instruct-GPTQ-Int4
2 加载基座模型+LoRA
CUDA_VISIBLE_DEVICES=0 API_PORT=8000 llamafactory-cli api \
--model_name_or_path /workspace/deepseekDistllation/models/Qwen/Qwen2.5-3B-Instruct-GPTQ-Int4 \
--adapter_name_or_path /workspace/deepseekDistllation/models/lora/Qwen2.5-3B-instruct-GPTQ-Int4/train_2025-03-20-20-41-50/checkpoint-1250 \
--finetuning_type lora
3 使用代码访问服务
可以用代码访问部署好的api server
def callServer(input):
port = 8000
client = OpenAI(
api_key="0",
base_url="http://localhost:{}/v1".format(os.environ.get("API_PORT", port)),
)
messages = []
messages.append({"role": "user", "content": input})
result = client.chat.completions.create(messages=messages, model="test",max_tokens=6000)
return result.choices[0].message.content
if __name__ == "__main__":
input = "对于「初三女生在搀扶跌倒老奶奶后反被冤枉,但仍选择资助她千元」的新闻事件,你有什么看法?"
a = time.time()
result = callServer(input)
b = time.time()
print("输出长度:"+str(len(result))+"字 耗时:"+str(b-a)+"秒 输出速度:"+str(len(result)/(b-a))+"字/秒")
print(result)
访问时,可以观察显卡的实时状态,windows在命令行里启动nvidia-smi -l 1,linux 使用 watch -n 1 nvidia-smi
六、主要参数
LLaMA-Factory训练过程中用到的参数非常多,按照重要程度整理如下:
1 极重要,本次训练模型和数据路径
| 参数名称 | 说明 |
|---|---|
| 模型名称 | 基座模型的名称 |
| 模型路径 | 基座模型的路径 |
| 检查点路径 | 开始的checkpoint路径,如果不需要可以为空 |
| 数据路径 | 数据存放的目录 |
| 数据集 | dataset_info.json中记录的哪一个数据集 |
| 输出目录 | 训练好的模型的路径,windows下默认在 C:\Users\foxba\saves\Qwen2.5-3B-Instruct-GPTQ-Int4\LoRA\ |
| 训练参数目录 | C:\Users\foxba\config\ |
| 对话模板 | 和使用的基座模型一致 |
2 极重要,决定本次训练的基本性质
| 参数名称 | 说明 |
|---|---|
| 微调方法 | full–全参数训练 <br />freeze–冻结一部分参数<br />LoRA–使用LoRA微调 |
| 训练阶段 | 属于哪个训练阶段<br />Supervised Fine-Tuning:进一步做有监督训练<br />Reward Modeling:奖励建模,用于强化学习<br />PPO:强化学习算法之一,用于增强多次迭代中的稳定性<br />DPO:强化学习算法之一,用于避免策略和价值函数之间的相互影响,提高学习效率<br />KTO:知识转移方法,可以强化学习效率和最终效果<br />Pre-Training:预训练<br />本次实验选Supervised Fine-Tuning |
| 量化等级 | none:不做量化<br />8:8位量化<br />4:4位量化 |
3 重要,决定本次训练的整体效果
| 参数名称 | 说明 |
|---|---|
| 学习率 | 0.1 一般只用于探索,没人会真的用<br />0.01 从头训练的标准模型初始学习率<br />0.001 已经快接近优化目标时做细致调整时采用<br />0.0001 模型接近收敛时做微调<br />0.00005 预训练阶段的最后微调 |
| 截断长度 | 本次实验选6000 |
| 训练轮数 | 学习的特性较简单 ,1轮即可,如果数据集太小,不应选择太多轮数,可以考虑数据增强。 |
| 批处理大小 | 根据显存的情况调整 |
| 梯度累计 | 批处理大小*梯度累计决定了梯度更新的频率 |
| 预热步数 | 建议使用,防止参数剧烈震荡 |
| LoRA的秩 | 学到信息的丰富程度 |
| LoRA缩放系数 | LoRA的重要程度 |
| LoRA随机丢弃 | 随机丢弃LoRA层权重的概率,是一种正则化方法,方式模型过度依赖LoRA |