资讯详情

资讯详情

AMD GPU上的LoRA微调:ROCm配置与实战教程

1. 从“显卡不支持”到“AMD 也能跑 LoRA”很多同学在接触大模型微调时第一反应是“我没有 NVIDIA 显卡是不是就不能玩 LoRA 了”在很长一段时间里这个想法确实有道理CUDA 生态太成熟PyTorch、TensorFlow 默认都优先支持 NVIDIA 显卡而 AMD 显卡的深度学习生态相对小众资料零散很多教程默认读者用的是 RTX 系列。但最近两年情况发生了明显变化。AMD 的 ROCm 软件栈逐渐完善PyTorch 官方也开始提供 ROCm 版本的安装包再加上 LoRA 这类参数高效微调技术显著降低了显存门槛越来越多开发者开始在 AMD GPU 上跑大模型微调。本文就以“AMD GPU 从 0 做 LoRA 微调”为主线完整梳理驱动安装、ROCm 环境配置、PyTorch 安装、PEFT 库的使用、训练脚本编写、结果验证和常见排错方法。本文适合这几类读者手头只有 AMD 显卡想尝试大模型微调的学生或开发者已经在 NVIDIA 上跑过微调想了解 AMD 环境差异的工程师准备在 Linux 服务器上部署 AMD GPU 训练环境的运维或算法同学。读完本文你将掌握如何确认 AMD 显卡是否被 ROCm 支持如何安装驱动和 PyTorch ROCm 版本如何用 LoRA 微调一个开源大模型以及遇到“识别不到显卡”“OOM 显存不足”“训练速度慢”等问题时如何排查。2. 核心概念全量微调、Freeze 微调与 LoRA 微调2.1 什么是大模型微调预训练大模型如 Qwen、DeepSeek、Llama本身已经通过海量文本学到了通用语言能力但它不一定懂你的业务客服话术、法律条款、代码规范、私有文档风格。微调就是用一批带标注的业务数据让模型在原有能力基础上适配特定任务。全量微调Full Fine-tuning是最直接的方式加载预训练权重后继续训练所有参数。这种方式效果好但对显存和算力的要求极高。以 7B 模型为例全量微调通常需要 60GB 以上的显存普通消费级显卡基本跑不动。Freeze 微调是折中方案只训练模型的一部分参数比如只训练最后几层 Transformer 层或只训练注意力层其余参数全部冻结。这种方式显存压力小一些但效果比较依赖人工选择哪些层该冻结。LoRALow-Rank Adaptation低秩适配是目前最主流的参数高效微调方法。它的核心思想是冻结原始模型参数在模型旁边额外插入少量低秩矩阵作为可训练参数。训练时只更新这些新增参数推理时再把新增参数合并回原模型或单独加载。2.2 LoRA 的数学原理假设原始模型的权重矩阵是 W0尺寸为 d×k。全量微调需要更新整个 W0LoRA 则假设权重更新量 ΔW 是低秩的可以分解为两个小矩阵 B 和 A 的乘积ΔW B × A其中 B 的尺寸是 d×rA 的尺寸是 r×k秩 r 远小于 d 和 k。训练时前向传播变为h W0 × x ΔW × x W0 × x B × A × xW0 被冻结只有 B 和 A 参与梯度更新。这样可训练参数量从 d×k 降为 d×r r×k。比如一个 4096×4096 的权重矩阵全量训练要更新约 1677 万参数使用 r8 的 LoRA只需训练约 6.5 万参数参数量只有原来的 0.4% 左右。这带来的直接好处有三个显存占用大幅下降消费级显卡也有机会跑微调训练速度显著提升因为反向传播只计算少量新增参数每次任务可以只保存一小份 LoRA 权重文件几十 MB 到几百 MB而不需要保存整个模型副本。2.3 LoRA 文件格式是什么训练完成后LoRA 权重通常以 PEFTParameter-Efficient Fine-Tuning的格式保存常见的是adapter_model.safetensors文件旁边还有一个adapter_config.json里面记录了r、lora_alpha、target_modules等关键配置。加载时PEFT 库会读取这两个文件重新构建 LoRA 层并加载权重。这也是为什么 LoRA 微调的结果“很小但很有用”它本身就是一套独立的增量权重体系。3. 环境准备AMD 驱动、ROCm 与 PyTorch 安装3.1 确认自己的 AMD GPU 是否支持 ROCmROCmRadeon Open Compute是 AMD 的开源 GPU 计算平台对标 NVIDIA 的 CUDA。目前 ROCm 对 AMD 的 CDNA 架构Instinct 系列数据中心卡和 RDNA 架构Radeon RX 消费级显卡都有一定支持但不同型号的支持程度差异较大。在动手之前建议先到 ROCm 官方文档查询自己的显卡型号是否在支持列表内。常见的做法是运行下面命令查看显卡信息lspci | grep -i amd如果显卡型号较老或属于 RDNA 早期架构可能需要安装特定版本的 ROCm。版本对应关系变化较快不要凭记忆写版本号以 ROCm 文档和 PyTorch 官方安装页面为准。需要特别指出的是AMD 显卡跑深度学习优先推荐 Linux 环境尤其是 Ubuntu。原因是 ROCm 在 Linux 下的支持最完整、性能最好。Windows 下虽然也在逐步推进支持但坑相对更多。如果你的主力系统是 Windows可以考虑 Windows Subsystem for LinuxWSL2来运行后续步骤。3.2 安装 AMD 显卡驱动Ubuntu 系统下最简单的方式是直接安装 ROCm 官方仓库提供的驱动和运行时。首先添加 AMD GPU 仓库并更新软件包列表sudo apt update sudo apt install wget gnupg wget https://repo.radeon.com/rocm/apt/latest/rocm.gpg.key -O - | sudo gpg --dearmor | sudo tee /etc/apt/keyrings/rocm.gpg /dev/null echo deb [signed-by/etc/apt/keyrings/rocm.gpg] https://repo.radeon.com/rocm/apt/latest jammy main | sudo tee /etc/apt/sources.list.d/rocm.list sudo apt update注意这里的仓库地址和版本号只是一个示例不同 ROCm 版本对应的仓库链接不同。安装前建议访问 ROCm 官方安装文档复制对应版本的命令。接下来安装核心组件sudo apt install rocm-hip-libraries rocm-dev安装完成后把当前用户加入render和video用户组否则非 root 用户可能无法访问 GPU 设备sudo usermod -a -G render,video $USER重启系统后执行rocm-smi命令确认 GPU 是否被识别rocm-smi如果能看到显卡温度、功耗、显存占用等输出说明驱动已经正常工作。3.3 安装 PyTorch ROCm 版本PyTorch 官方针对 ROCm 提供了独立的安装源。安装方式与 CUDA 版本很相似只是--index-url不同。例如pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm6.2这里同样需要以 PyTorch 官网当时的版本为准。安装完成后可以用一段非常简单的代码验证 PyTorch 是否能调用 AMD GPUimport torch print(PyTorch 版本:, torch.__version__) print(是否检测到 ROCm:, torch.version.hip) print(GPU 是否可用:, torch.cuda.is_available()) print(GPU 名称:, torch.cuda.get_device_name(0) if torch.cuda.is_available() else 无)在 ROCm 环境下PyTorch 为了兼容 CUDA 生态暴露出来的接口仍然是torch.cuda但底层计算图会通过 HIP 翻译到 AMD GPU 上执行。所以你会看到torch.cuda.is_available()返回True这是正常现象。如果torch.version.hip不是None说明当前 PyTorch 确实是 ROCm 版本。3.4 安装 PEFT、Transformers 等微调依赖接下来安装微调所需的 Python 库pip install transformers datasets peft accelerate各库的作用如下transformers提供模型结构和 tokenizer 加载能力datasets方便处理数据集peftPEFT 库提供 LoRA 等参数高效微调方法accelerate负责分布式训练、混合精度、设备管理。这四个库是目前做 LoRA 微调最核心的依赖组合。后面还会用到bitsandbytes但它在 AMD ROCm 环境下支持度不稳定本文先用纯 LoRA 方式演示暂不引入量化。4. LoRA 微调完整实战让 Qwen 学会“打招呼”为了便于复现本文选择一个小规模模型进行演示Qwen2.5-0.5B-Instruct。这个模型参数量约 5 亿在普通消费级 AMD GPU 上也能训练非常适合验证环境配置和 LoRA 流程。4.1 准备业务数据集微调需要喂给模型一批“输入-输出”对。这里构造一个非常简单的场景让模型学会用特定风格回复“你好”。数据集保存为 JSON 文件。创建一个data.json[ { instruction: 用户说你好请用简洁欢快的语气回复, output: 嗨很高兴见到你有什么可以帮你的吗 }, { instruction: 用户说你好请用正式礼貌的语气回复, output: 您好欢迎咨询请问有什么需要帮助的 }, { instruction: 用户说你好请用可爱卖萌的语气回复, output: 哈喽哈喽我等你好久啦 }, { instruction: 用户说你好请用科技感十足的简短回复, output: 系统已连接随时为您服务。 } ]真实业务场景中这样的数据至少需要成百上千条且要覆盖多种表达方式。这里仅用于流程演示。4.2 编写 LoRA 训练脚本完整训练脚本放在train_lora.py中import json import torch from transformers import ( AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer, DataCollatorForSeq2Seq ) from peft import LoraConfig, get_peft_model, TaskType from datasets import Dataset # 1. 加载模型和 tokenizer model_name Qwen/Qwen2.5-0.5B-Instruct tokenizer AutoTokenizer.from_pretrained(model_name, trust_remote_codeTrue) if tokenizer.pad_token is None: tokenizer.pad_token tokenizer.eos_token model AutoModelForCausalLM.from_pretrained( model_name, torch_dtypetorch.bfloat16, device_mapauto, trust_remote_codeTrue ) # 2. 配置 LoRA lora_config LoraConfig( task_typeTaskType.CAUSAL_LM, r8, lora_alpha16, lora_dropout0.05, target_modules[q_proj, k_proj, v_proj, o_proj], ) model get_peft_model(model, lora_config) model.print_trainable_parameters() # 3. 加载数据集 with open(data.json, r, encodingutf-8) as f: raw_data json.load(f) def format_example(example): prompt f### 指令{example[instruction]}\n### 回复 return {prompt: prompt, completion: example[output]} formatted_data [format_example(x) for x in raw_data] dataset Dataset.from_list(formatted_data) def tokenize_function(examples): model_inputs tokenizer(examples[prompt], max_length256, truncationTrue) labels tokenizer(examples[completion], max_length256, truncationTrue) model_inputs[labels] labels[input_ids] return model_inputs tokenized_dataset dataset.map(tokenize_function, batchedTrue, remove_columnsdataset.column_names) # 4. 定义训练参数 training_args TrainingArguments( output_dir./qwen-lora, per_device_train_batch_size2, gradient_accumulation_steps4, learning_rate2e-4, num_train_epochs50, logging_steps10, save_steps100, save_total_limit2, fp16False, bf16True, remove_unused_columnsFalse, report_tonone, ) trainer Trainer( modelmodel, argstraining_args, train_datasettokenized_dataset, data_collatorDataCollatorForSeq2Seq(tokenizertokenizer), ) # 5. 开始训练 trainer.train() # 6. 保存 LoRA 权重 trainer.model.save_pretrained(./qwen-lora-output) tokenizer.save_pretrained(./qwen-lora-output)脚本中几个关键点需要解释一下device_mapauto让 Transformers 自动把模型放到可用 GPU 上torch_dtypetorch.bfloat16使用 BF16 混合精度能有效降低显存占用AMD 的 ROCm 对 BF16 支持也比较好target_modules指定在哪些模块上插入 LoRA 层Qwen 系列模型通常选择注意力层中的q_proj、k_proj、v_proj、o_projr8和lora_alpha16是 LoRA 的两个核心超参数lora_alpha / r相当于 LoRA 层输出的缩放系数会影响训练稳定性。4.3 运行训练执行训练命令python train_lora.py如果一切正常你会看到类似下面的输出trainable params: 1,572,864 || all params: 494,032,896 || trainable%: 0.3184这个输出说明整个模型约 4.94 亿参数其中只有约 157 万参数参与训练占比仅 0.32%。这就是 LoRA 微调高效的根本原因。训练过程中Trainer会打印 loss 变化。这里我们用了 50 个 epoch对于这样小的数据集略显“过拟合”但目的是演示 LoRA 能记住训练集中的回复模式。4.4 用微调后的 LoRA 权重做推理训练完成后编写inference.py验证效果import torch from transformers import AutoModelForCausalLM, AutoTokenizer from peft import PeftModel model_name Qwen/Qwen2.5-0.5B-Instruct lora_path ./qwen-lora-output tokenizer AutoTokenizer.from_pretrained(model_name, trust_remote_codeTrue) # 先加载基础模型再加载 LoRA 权重 base_model AutoModelForCausalLM.from_pretrained( model_name, torch_dtypetorch.bfloat16, device_mapauto, trust_remote_codeTrue ) model PeftModel.from_pretrained(base_model, lora_path) model.eval() def generate_response(prompt): messages [{role: user, content: prompt}] text tokenizer.apply_chat_template(messages, tokenizeFalse, add_generation_promptTrue) inputs tokenizer(text, return_tensorspt).to(cuda) outputs model.generate( **inputs, max_new_tokens64, do_sampleTrue, temperature0.7, top_p0.9, ) response tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokensTrue) return response # 用训练中出现过的输入测试 print(generate_response(你好))运行python inference.py如果模型学到了训练数据中的模式输出会偏向数据集里的风格比如“嗨很高兴见到你”而微调前的模型可能会生成一段更通用的解释性回答。这种差异说明 LoRA 权重确实生效了。4.5 如何合并 LoRA 权重进原模型LoRA 权重在推理时需要额外加载。如果希望得到一个独立的完整模型可以把 LoRA 权重合并回原模型from transformers import AutoModelForCausalLM, AutoTokenizer from peft import PeftModel model_name Qwen/Qwen2.5-0.5B-Instruct lora_path ./qwen-lora-output base_model AutoModelForCausalLM.from_pretrained(model_name, torch_dtypetorch.bfloat16, device_mapauto) model PeftModel.from_pretrained(base_model, lora_path) merged_model model.merge_and_unload() merged_model.save_pretrained(./qwen-lora-merged) tokenizer AutoTokenizer.from_pretrained(model_name) tokenizer.save_pretrained(./qwen-lora-merged)合并后的模型可以直接用AutoModelForCausalLM.from_pretrained(./qwen-lora-merged)加载无需再依赖 PEFT 库。这个操作在生产部署时很有用可以减少加载时的额外逻辑。5. 进阶用 Llama-Factory 快速微调如果你不想编写训练脚本或者想快速对比不同模型的微调效果可以试试Llama-Factory这个开源工具。它是一个封装好的大模型微调平台支持 LoRA、QLoRA、全量微调等多种方法并且提供了命令行和 Web 界面两种操作方式。安装git clone https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factory pip install -e .启动 Web 界面CUDA_VISIBLE_DEVICES0 python src/train_web.py在界面里选择模型名称、微调方法LoRA、数据集、学习率、训练轮数等参数后点击开始训练即可。Llama-Factory 底层仍然调用 Transformers 和 PEFT所以只要 ROCm 环境装好PyTorch 能识别到 AMD GPULlama-Factory 同样可以跑。它的优势是省去了写代码的步骤数据集格式也更工程化适合验证数据效果或快速出 baseline。缺点是对底层细节的控制不如直接写脚本灵活。6. 常见问题与排查思路AMD GPU LoRA 微调的过程中最容易遇到的问题集中在驱动、PyTorch 版本、显存和性能几个方面。问题现象常见原因解决思路torch.cuda.is_available()返回 FalsePyTorch 装成了 CPU 版本或 CUDA 版本而非 ROCm 版本检查torch.version.hip重装 PyTorch ROCm 版本rocm-smi看不到 GPU驱动未正确安装或用户不在render、video组重新安装 ROCm并执行usermod -a -G render,video $USER后重启训练时报HIP out of memory模型太大、batch size 太大或序列太长减小per_device_train_batch_size降低max_length使用gradient_accumulation_steps补偿训练速度很慢CPU 在跑而不是 GPU或模型在 GPU 和 CPU 之间反复搬运确认device_mapauto生效观察rocm-smi中 GPU 利用率推理结果和微调前一样LoRA 权重没正确加载或微调数据量太少、学习率太小用PeftModel.from_pretrained加载 LoRA适当增加 epoch 或调大学习率加载模型时报trust_remote_code相关错误某些模型需要执行自定义代码在from_pretrained中设置trust_remote_codeTrue6.1 显存不足怎么评估和优化显存占用由模型参数、优化器状态、梯度、激活值四部分共同决定。即使 LoRA 只训练了 1% 的参数模型本身和中间激活仍然占大头。一个经验估算是微调一个 0.5B 模型batch size 为 1、序列长度为 512 时显存需求大约在 6-8GB 左右。如果你的显卡只有 8GB 显存建议把序列长度降到 256并使用gradient_accumulation_steps来提高训练稳定性。如果感觉还是吃力可以进一步使用 QLoRAfrom transformers import BitsAndBytesConfig bnb_config BitsAndBytesConfig( load_in_4bitTrue, bnb_4bit_compute_dtypetorch.bfloat16, bnb_4bit_quant_typenf4, ) model AutoModelForCausalLM.from_pretrained( model_name, quantization_configbnb_config, device_mapauto, )注意bitsandbytes的 ROCm 支持相对有限需要安装对应 ROCm 版本的 bitsandbytes并且不同 ROCm 版本兼容性也略有差异。如果安装失败建议先退回纯 LoRA 方案。6.2 为什么 PyTorch 检查 GPU 使用torch.cuda很多刚接触 AMD 的同学会对torch.cuda.is_available()感到困惑明明是 AMD 显卡为什么接口名里带cuda这是历史原因。PyTorch 早期就把 GPU 抽象层统一命名为 CUDA后来即使接入 ROCm 后端也沿用这套接口。所以只要torch.version.hip非空就说明当前 PyTorch 识别到了 ROCm 后端。在编写代码时你仍然可以用torch.cuda这一套 API不需要改代码。7. 最佳实践与工程建议7.1 数据集质量优先LoRA 微调的效果上限主要由数据决定。数据量不在多而在“干净”和“风格统一”。以文本生成任务为例至少需要保证输入和输出有明确对应关系不要出现“答案在输入里却答非所问”的情况输出风格一致否则模型不知道该学哪种风格不要有重复和冲突的样本指令类任务建议统一模板让模型学到稳定的格式。你的训练数据如果只有几十条模型很可能会过拟合只能记住样本无法泛化。训练完成后一定要准备一份与训练数据不重叠的测试集做效果验证。7.2 超参数选择建议对于 LoRA几个核心参数的常规范围如下r4-16 比较常见。r越大表达能力越强但训练参数量和显存也会上升。领域数据充足、任务复杂时用稍大的r简单风格迁移用较小的r即可lora_alpha通常设为r的 1-2 倍比如r8时lora_alpha16learning_rateLoRA 的常用学习率在 1e-4 到 5e-4。比全量微调大一个数量级是正常的因为只训练少量低秩参数较小的学习率会导致收敛太慢num_train_epochs小数据量时可以多跑几轮但注意观察 loss 是否已经收敛避免严重过拟合。训练过程中最好开启logging_steps日志观察 loss 曲线。如果 loss 一直不下降优先检查学习率和数据格式如果 loss 下降但测试效果差优先怀疑过拟合和数据质量。7.3 环境与版本管理AMD GPU 的软件栈相对复杂ROCm 版本、PyTorch 版本、PEFT 版本三者之间需要匹配。强烈建议在项目目录中创建独立的虚拟环境python -m venv .venv source .venv/bin/activate并且把依赖锁在一个requirements.txt中pip freeze requirements.txt这样即使过段时间重新安装环境也能保证版本可复现。7.4 生产部署时的注意事项LoRA 微调完成后如果要在生产环境部署需要注意如果是长期固定的任务建议把 LoRA 权重合并回原模型省去每次加载 LoRA 的逻辑如果多个业务场景共用一个基础模型每个场景训练一份 LoRA推理时动态切换 LoRA 权重可以大大节省存储成本在 AMD GPU 环境部署推理时同样要确认 PyTorch 的 ROCm 版本与训练环境一致如果使用 llama.cpp 这类 C 推理框架它的 AMD GPU 支持是通过 Vulkan 或 ROCm 后端实现的部署前需要单独编译对应后端并且确认显卡型号受支持。7.5 数据安全与权限在做大模型微调时训练数据可能包含业务敏感信息。不要直接把包含手机号、身份证号、内部文档等信息的原始数据用于训练应先做脱敏处理。如果使用云服务器谨慎选择数据存放位置并严格控制访问权限。删除中间权重时也要确认没有备份泄露风险。8. 从 LoRA 走向更多微调方法与学习路线LoRA 并不是微调的唯一选项但它是理解和上手大模型微调的最佳入口。跑通本文的流程后你可以沿着下面几个方向继续深入QLoRA加入 4-bit 量化进一步降低显存门槛全量微调与 Freeze 微调对比不同方法的参数效率与效果差异长文本微调学习如何处理超过 4096 token 的输入涉及序列并行和显存优化强化学习偏好对齐如 DPO在指令微调之后让模型的输出更符合人类偏好服务化部署用 vLLM 或 llama.cpp 将微调后的模型封装成标准 API 服务。从硬件角度如果你的 AMD 显卡是 Radeon RX 6000/7000 系列建议优先在 Linux 下做训练如果是 Radeon 780M 这类核显也可以尝试跑 0.5B 级别的小模型但期望值不要太高毕竟显存带宽和容量是硬限制。如果想做更大规模的模型微调租用 GPU 服务器时也要留意供应商是否提供 AMD 显卡选项以及预装 ROCm 的方式。最后再提一个实用经验第一次配置 AMD GPU 微调环境时不要一上来就跑 7B 甚至 14B 模型先用 0.5B 或 1.5B 规模把整个流程打通确认驱动、PyTorch、训练脚本、推理验证每个环节都正常再逐步扩大模型规模。这个小步骤能帮你省下大量排查时间。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →