实战演练,用 AMD GPU 完成一次完整的 LLaMA 模型微调
环境搭建:告别编译噩梦
在 AMD GPU 上跑大模型,很多人第一反应是“配环境太痛苦”。确实,ROCm 的门槛曾经让不少开发者望而却步,但现在社区已经沉淀了大量成熟的自动化方案。我们不再需要手动去纠结 HIP 编译器路径或者架构参数,直接利用社区验证过的脚本是最稳妥的起点。
首先,确保你的系统已安装 ROCm 7.x 驱动。对于大多数 Linux 发行版(如 Ubuntu 22.04),我们可以通过简单的命令将用户加入必要的用户组,避免后续权限报错:
sudo usermod -aG render,video $USER
重启后,核心步骤是部署 PyTorch 的 ROCm 版本。与其从源码硬编,不如直接使用预构建的 Wheel 包,这样能节省数小时甚至更久。以下命令会安装适配当前 GPU 架构(自动检测 gfx90a/gfx942 等)的 PyTorch:
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm6.2
注:虽然标题提及 ROCm 7.x,但当前稳定生态多基于 6.2 版本构建,若你有特定的 7.x 测试版需求,请替换对应索引源,原理一致。
接下来是推理与微调框架的选择。为了本次实战,我们选用 LLaMA-Factory 的社区分支,它对 ROCm 的后端支持非常友好,且内置了 LoRA 微调的完整流程。克隆仓库时,建议拉取专门优化过显存管理的分支:
git clone -b rocm_optimized https://github.com/your-community-mirror/LLaMA-Factory.git
cd LLaMA-Factory
pip install -e ".[torch,metrics]"
这一步完成后,你可以运行一个简单的检查脚本来确认 GPU 是否被正确识别:
import torch
print(f"CUDA available: {torch.cuda.is_available()}")
print(f"Device count: {torch.cuda.device_count()}")
print(f"Device name: {torch.cuda.get_device_name(0)}")
如果输出显示你的 Radeon 或 Instinct 显卡型号,且 CUDA available 为 True(在 ROCm 中 PyTorch 仍沿用 cuda 接口名),那么恭喜,最难的“劝退”环节已经过去了。
数据准备与参数策略
微调的效果七分靠数据。我们不需要海量数据,关键在于质量和对齐。假设我们要让 LLaMA 3 学会特定的代码生成风格,首先需要将数据整理成 JSONL 格式。每一行是一个独立的样本,包含 instruction(指令)、input(可选输入)和 output(期望输出)。
创建一个名为 alpaca_data.json 的文件,内容示例如下:
{"instruction": "解释 Python 中的装饰器", "input": "", "output": "装饰器是一种设计模式,允许你在不修改原函数代码的情况下增强其功能..."}
{"instruction": "修复这段 SQL 查询", "input": "SELECT * FROM users WHERE id = '1' OR '1'='1'", "output": "SELECT * FROM users WHERE id = %s (使用参数化查询防止注入)..."}
在 LLaMA-Factory 中,你需要注册这个数据集。打开 data/dataset_info.json,添加你的自定义条目:
"my_code_data": {
"file_name": "alpaca_data.json",
"columns": {
"prompt": "instruction",
"query": "input",
"response": "output"
}
}
接下来是关键的训练配置。对于单卡 Radeon 显卡(如 RX 7900 XTX 或 MI250),显存是最大瓶颈。我们必须启用 LoRA(低秩自适应)技术,它只训练极少量的参数,大幅降低显存占用。
编写 train_lora.sh 脚本,以下是经过实战调整的核心参数解析:
llama_factory-cli train \
--stage sft \
--do_train \
--model_name_or_path meta-llama/Meta-Llama-3-8B-Instruct \
--dataset my_code_data \
--template llama3 \
--finetuning_type lora \
--lora_target q_proj,v_proj \
--output_dir ./saves/llama3-lora \
--overwrite_cache \
--per_device_train_batch_size 2 \
--gradient_accumulation_steps 4 \
--lr_scheduler_type cosine \
--logging_steps 10 \
--warmup_ratio 0.1 \
--save_steps 100 \
--learning_rate 2e-4 \
--num_train_epochs 3.0 \
--plot_loss \
--fp16
这里有几个值得细说的点:
lora_target:指定微调哪些层。q_proj和v_proj是注意力机制中的查询和值投影层,通常对风格迁移最有效。如果想效果更强,可以加上k_proj,o_proj,但显存消耗会增加。gradient_accumulation_steps:这是小显存救星。如果你的显存只能塞下 batch_size=1,可以把这个值设为 8 或 16,等效于更大的批次,同时保持显存不爆。fp16:AMD 显卡在半精度下表现良好,务必开启以节省一半显存空间。如果遇到数值溢出(NaN),可以尝试改为bf16(需硬件支持)。
训练监控与效果验证
启动脚本后,终端会实时打印 Loss 曲线。正常的训练过程应该是 Loss 快速下降然后趋于平稳。如果发现 Loss 震荡剧烈或不下降,通常是学习率(learning_rate)过大,建议减半重试。
训练完成后,模型权重保存在 ./saves/llama3-lora 目录下。现在到了见证奇迹的时刻——加载模型进行测试。我们可以写一个简短的 Python 脚本来验证微调成果:
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
# 加载基座模型
base_model = "meta-llama/Meta-Llama-3-8B-Instruct"
adapter_path = "./saves/llama3-lora"
tokenizer = AutoTokenizer.from_pretrained(base_model)
model = AutoModelForCausalLM.from_pretrained(
base_model,
torch_dtype=torch.float16,
device_map="auto"
)
# 加载 LoRA 适配器
from peft import PeftModel
model = PeftModel.from_pretrained(model, adapter_path)
# 测试生成
prompt = "解释 Python 中的装饰器"
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
outputs = model.generate(
**inputs,
max_new_tokens=200,
temperature=0.7,
top_p=0.9
)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
运行这段代码,你会发现模型的回答风格明显贴近了你提供的训练数据。原本通用的回答可能比较教科书式,而微调后的模型可能会直接用你喜欢的“实战口吻”来解释,甚至带上你数据集中的特定术语。
如果在多卡环境下(例如双卡 MI250),还可以通过设置 --ddp_find_unused_parameters false 来加速通信效率。此外,社区中关于 vLLM 的 ROCm 分支也支持加载 LoRA 权重进行高并发推理,适合后续部署到生产环境。
整个流程走下来,从环境配置的“坑”到数据清洗的细节,再到最终看到模型“学会”新技能,这种掌控感是单纯调用 API 无法比拟的。AMD 的生态正在快速成熟,只要选对工具链,它完全能胜任大模型微调的重任。动手试试吧,你的显卡比你想象的更强大。

更多推荐


所有评论(0)