昇思LLM微调基于“预训练-微调”范式,核心是在预训练模型(如Llama2、Qwen)的基础上,使用目标任务数据集调整模型参数,使模型适配特定场景(如对话、领域问答)[superscript:3]。其核心技术要点如下:
1. 全参微调:更新模型所有权重参数,需大量计算资源与数据,适合对任务精度要求高的场景,如专业领域模型优化[superscript:2]。
2. LoRA低参微调:通过将模型权重矩阵分解为两个低秩矩阵(A和B),仅更新这两个低秩矩阵,冻结原始模型参数[superscript:1]。参数量仅为全参微调的0.5%左右,显存占用降低60%以上,是昇思LLM微调的主流选择[superscript:4]。
3. 核心流程:统一为“环境准备→数据集预处理→模型加载与配置→微调训练→模型评估与保存”,依托MindFormers套件实现一键式微调[superscript:3]。
以下基于MindSpore 2.3.0、MindFormers 1.3.2,以Llama2-7B模型为例,实现LoRA低参微调(资源友好型)与全参微调,适配openEuler系统,代码可直接实操。
1. 环境准备
安装MindSpore、MindFormers及相关依赖,确保适配昇腾NPU或CPU环境:
# 1. 安装MindSpore(以CPU版本为例,昇腾NPU需安装对应版本)
pip install mindspore-cpu==2.3.0 -i https://pypi.tuna.tsinghua.edu.cn/simple
# 2. 安装MindFormers大模型套件(含LLM微调工具)
pip install mindformers==1.3.2
# 3. 安装额外依赖(数据集处理、权重转换)
pip install datasets transformers sentencepiece
2. LoRA低参微调
LoRA微调通过配置pet_config参数,指定低秩矩阵相关设置,仅更新注意力层参数,实操代码如下[superscript:1][superscript:4]:
import mindspore as ms
from mindformers import LlamaForCausalLM, LlamaTokenizer, TrainingArguments, Trainer
from mindformers.models.peft import LoraConfig, get_peft_model
# 1. 初始化环境(昇腾NPU设置为Ascend,CPU设置为CPU)
ms.set_context(mode=ms.GRAPH_MODE, device_target="CPU")
# 2. 加载预训练模型与Tokenizer
model = LlamaForCausalLM.from_pretrained("llama2-7b", ms_dtype=ms.float16)
tokenizer = LlamaTokenizer.from_pretrained("llama2-7b")
# 3. 配置LoRA参数(核心)
lora_config = LoraConfig(
task_type="CAUSAL_LM",
target_modules=".*wq|.*wk|.*wv|.*wo", # 作用于注意力层
lora_rank=16, # 低秩矩阵秩值,平衡性能与参数量
lora_alpha=16, # 权重更新缩放比例
lora_dropout=0.05 # 正则化,避免过拟合
)
# 4. 创建LoRA模型(冻结原模型,仅训练LoRA参数)
peft_model = get_peft_model(model, lora_config)
peft_model.print_trainable_parameters() # 输出可训练参数(约0.5%)
# 5. 准备微调数据集(以Alpaca对话数据集为例)
def process_data(examples):
# 格式化对话数据
texts = [f"用户:{q}\n助手:{a}" for q, a in zip(examples["question"], examples["answer"])]
# tokenizer编码
return tokenizer(texts, truncation=True, max_length=512, padding="max_length")
# 加载并处理数据集
from datasets import load_dataset
dataset = load_dataset("tatsu-lab/alpaca", split="train[:1000]") # 取1000条样本
dataset = dataset.map(process_data, batched=True)
# 6. 配置训练参数
training_args = TrainingArguments(
output_dir="./llama2_lora_finetune",
per_device_train_batch_size=2,
learning_rate=5e-5,
num_train_epochs=3,
logging_steps=10,
save_strategy="epoch"
)
# 7. 启动LoRA微调
trainer = Trainer(
model=peft_model,
args=training_args,
train_dataset=dataset
)
trainer.train()
# 8. 保存LoRA适配器(仅保存新增低秩矩阵参数)
peft_model.save_pretrained("./llama2_lora_adapter")
3. 全参微调
全参微调更新模型所有参数,需更多计算资源,适合大规模数据集场景,实操代码如下[superscript:2][superscript:3]:
import mindspore as ms
from mindformers import LlamaForCausalLM, LlamaTokenizer, TrainingArguments, Trainer
# 1. 初始化环境(建议使用昇腾NPU,CPU需增大内存)
ms.set_context(mode=ms.GRAPH_MODE, device_target="Ascend")
# 2. 加载预训练模型与Tokenizer(不冻结参数)
model = LlamaForCausalLM.from_pretrained("llama2-7b", ms_dtype=ms.float16)
tokenizer = LlamaTokenizer.from_pretrained("llama2-7b")
# 3. 数据集准备(同LoRA微调,使用完整Alpaca数据集)
dataset = load_dataset("tatsu-lab/alpaca", split="train")
dataset = dataset.map(process_data, batched=True) # 复用上述process_data函数
# 4. 配置全参微调参数(学习率略低,避免参数震荡)
training_args = TrainingArguments(
output_dir="./llama2_full_finetune",
per_device_train_batch_size=1,
learning_rate=2e-5,
num_train_epochs=2,
logging_steps=50,
save_strategy="epoch",
gradient_accumulation_steps=4 # 梯度累积,降低显存占用
)
# 5. 启动全参微调
trainer = Trainer(
model=model,
args=training_args,
train_dataset=dataset
)
trainer.train()
# 6. 保存全参微调模型
ms.save_checkpoint(model, "./llama2_full_finetune/llama2_7b_finetune.ckpt")
4. 微调模型推理验证
微调完成后,加载模型进行推理,验证微调效果,代码如下[superscript:4]:
from mindformers.models.peft import PeftModel
# 1. 加载基础模型与LoRA适配器(LoRA微调验证)
base_model = LlamaForCausalLM.from_pretrained("llama2-7b", ms_dtype=ms.float16)
finetune_model = PeftModel.from_pretrained(base_model, "./llama2_lora_adapter")
# 2. 推理测试
prompt = "用户:解释什么是大语言模型微调?\n助手:"
inputs = tokenizer(prompt, return_tensors="ms")
outputs = finetune_model.generate(**inputs, max_new_tokens=100)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
# 全参微调模型推理(直接加载保存的模型)
# finetune_model = LlamaForCausalLM.from_pretrained("./llama2_full_finetune")
# outputs = finetune_model.generate(**inputs, max_new_tokens=100)