一、配置信息
ubuntu 22.04
二、安装GPU驱动、cuDNN 英伟达CUDA深度学习网络加速引擎、pytorch框架
1、教程链接
验证是否安装成功
安装完成后,用这条命令一次性验证所有环境
python3 -c "
import torch
print('====================')
print('PyTorch 版本:', torch.__version__)
print('GPU 可用:', torch.cuda.is_available())
print('GPU 型号:', torch.cuda.get_device_name(0) if torch.cuda.is_available() else '无')
print('cuDNN 版本:', torch.backends.cudnn.version())
print('====================')
"
正确输出格式模版:
PyTorch 版本: 2.5.1+cu121
GPU 可用: True
GPU 型号: Tesla T4
cuDNN 版本: 90100
出现上述返回信息,就说明你的 PyTorch + GPU 环境已经完全就绪了。
三、开始微调
3.1、安装微调所学的核心且常用的工具
pip install transformers datasets peft accelerate bitsandbytes trl sentencepiece modelscope huggingface
-
PEFT (Parameter-Efficient Fine-Tuning):参数高效微调库
PEFT 的核心目标是“省钱省力”。在大模型时代,全量微调(Fine-Tuning)所有参数需要巨大的显存和算力。PEFT 提供了一系列技术(如最知名的 LoRA),允许你冻结模型绝大部分参数,只微调极少量的新增参数(通常仅占原模型参数的 0.1%-5%)。 -
Accelerate:硬件适配与分布式训练库
Accelerate 的核心目标是“一套代码,到处运行”。它是由 Hugging Face 推出的轻量级库,用于抽象底层硬件的差异。
有什么用:无论你是在单张 CPU、单张 GPU、多张 GPU(单机多卡/多机多卡)还是 TPU 上运行模型,使用 Accelerate 后,你几乎不需要修改原本的 PyTorch 训练代码。它自动化了混合精度训练(FP16/BF16)、分布式环境初始化等繁琐配置,极大降低了多卡训练和显存优化的门槛。 -
bitsandbytes:模型量化与显存压缩库
bitsandbytes 的核心目标是“把模型变小”。它专注于提供高效的低精度(8-bit、4-bit)CUDA 算子,主要用于模型量化(Quantization)。这能让模型的显存占用降低。著名的 QLoRA 微调技术,就是结合了 bitsandbytes 的 4位量化和 PEFT 的 LoRA 技术,实现了在极低显存下的高效微调。 -
TRL (Transformer Reinforcement Learning):大模型强化学习与对齐库
TRL 的核心目标是“让模型更听话(对齐人类偏好)”。它是 Hugging Face 推出的专门用于大语言模型对齐和微调的框架。
有什么用:它封装了复杂的强化学习流程,支持 SFT(监督微调)、PPO(近端策略优化) 和 DPO(直接偏好优化) 等主流算法。当你想让大模型不仅会说话,还能按照人类的价值观、安全规范或特定偏好来回答问题时(即 RLHF 过程),TRL 是最主流的工具。它与 Transformers 和 PEFT 完美兼容。 -
SentencePiece:无监督文本分词工具
SentencePiece 的核心目标是“把文字切成模型能懂的碎片”。它是一个由 Google 推出的、语言无关的文本分词(Tokenizer)和去分词(Detokenizer)框架。
有什么用:它不依赖特定语言的预处理(比如中文不需要提前用 Jieba 分词),而是直接在原始文本(包括空格)上进行无监督学习,将句子切分成子词(Subword)单元(常用算法如 BPE 或 Unigram)。目前绝大多数主流大模型(如 LLaMA、T5、ChatGLM 等)的底层分词器都是基于 SentencePiece 构建的。
总结它们在实际工作流中的关系:
如果你要微调一个大模型,通常的流程是:用 SentencePiece 处理文本数据,用 bitsandbytes 把模型量化以节省显存,用 PEFT (LoRA) 进行参数高效微调,用 Accelerate 来加速训练并适配你的多卡环境,最后如果你想让模型更符合人类偏好,还可以用 TRL 进行进一步的强化学习对齐。
3.2、再次安装torch包的命令(可跳过)
如果上述的包,强制把torch包升级了,导致cuda版本不适配,需要重新执行一遍安装torch包的命令
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu117
3.3. 数据集下载
ModelScope:https://modelscope.cn/datasets →搜 alpaca_zh->下载数据集
数据集准备(放在 /opt/lora/data.json)
3.2、nano train.py
# 环境变量禁用flops
import os
os.environ["TRANSFORMERS_NO_FLOPS"] = "1"
import torch
from datasets import load_dataset
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
BitsAndBytesConfig,
TrainingArguments,
Trainer,
DataCollatorForLanguageModeling
)
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
# 配置
MODEL_PATH = "Qwen/Qwen1.5-0.5B-Chat"
DATA_PATH = "./data-1000.json"
OUTPUT_DIR = "./lora_output"
# 4bit量化
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_use_double_quant=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16
)
# LoRA
lora_config = LoraConfig(
r=8,
lora_alpha=16,
target_modules=["q_proj", "v_proj"],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
# 分词器
tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"
# 模型
model = AutoModelForCausalLM.from_pretrained(
MODEL_PATH,
quantization_config=bnb_config,
device_map="auto",
trust_remote_code=True,
use_cache=False
)
model = prepare_model_for_kbit_training(model)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# 数据集
raw_ds = load_dataset("json", data_files=DATA_PATH, split="train")
def build_text(sample):
prompt = f"<|im_start|>user\n{sample['instruction']}<|im_end|>\n<|im_start|>assistant\n{sample['output']}<|im_end|>"
return {"text": prompt}
ds = raw_ds.map(build_text)
def tokenize_fn(examples):
return tokenizer(examples["text"], truncation=True, max_length=512)
token_ds = ds.map(tokenize_fn, batched=True, remove_columns=["instruction","input","output","text"])
data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)
# 训练参数,添加disable_flops计算
training_args = TrainingArguments(
output_dir=OUTPUT_DIR,
per_device_train_batch_size=1,
gradient_accumulation_steps=4,
learning_rate=2e-4,
num_train_epochs=3,
logging_steps=10,
save_strategy="epoch",
fp16=True,
optim="paged_adamw_8bit",
gradient_checkpointing=True,
report_to="none",
overwrite_output_dir=True
)
# 重写model.floating_point_ops,直接返回0,彻底绕过报错
def empty_flops(*args,**kwargs):
return 0.0
model.floating_point_ops = empty_flops
trainer = Trainer(
model=model,
args=training_args,
train_dataset=token_ds,
data_collator=data_collator
)
if __name__ == "__main__":
trainer.train()
trainer.save_model(OUTPUT_DIR)
tokenizer.save_pretrained(OUTPUT_DIR)
3.3. 开始微调训练
python3 train.py
3.4. 编辑测试文件:
nano test-inference.py
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
base_name = "Qwen/Qwen1.5-0.5B-Chat"
lora_path = "./lora_output/checkpoint-150"
tokenizer = AutoTokenizer.from_pretrained(base_name, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(base_name, load_in_4bit=True, device_map="auto", trust_remote_code=True)
model = PeftModel.from_pretrained(model, lora_path)
prompt = "<|im_start|>user\n列出 5 种不同类型的水果。<|im_end|>\n<|im_start|>assistant\n"
inp = tokenizer(prompt, return_tensors="pt").to("cuda")
out = model.generate(**inp, max_new_tokens=128)
print(tokenizer.decode(out[0]))
3.5. 执行测试推理的文件
python3 test-inference.py
4. 调整训练参数
4.1. LoRA 结构(最关键,大概率 r 太小 / 只训少量层)
from peft import LoraConfig
lora_config = LoraConfig(
r=16, # 原来如果是4/8 → 改成16(容量不足loss下不去)
lora_alpha=32, # alpha=2×r固定
target_modules=[
"q_proj","k_proj","v_proj","o_proj",
"gate_proj","up_proj","down_proj"
], # 全层,不要只q/v,小模型必须全开
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
r 过小 = 适配器容量不够,模型存不下指令,loss 卡死高位。
4.2. 学习率(头号元凶,loss 停滞首选改 lr),training_args
原 lr<8e-5 → 改成 1.5e-4 ~ 2e-4(1.5e-4 稳妥)
必须加预热:warmup_ratio=0.05(总步数 5% 预热)+ lr_scheduler_type="cosine"余弦衰减
lr 太低参数更新微弱,loss 长期横盘 2.2~2.4;太高 loss 震荡不收敛。
4.3. 有效批次(梯度不稳导致收敛差)
per_device_train_batch_size=1
有效batch=8,显存不够就accum=4
gradient_accumulation_steps=8
4.4. 训练轮次
num_train_epochs=3,别超过 4,小样本极易过拟合。