大模型微调:概念、技术与实践指南

1. 大模型微调概述

1.1 什么是大模型微调

大模型微调(Fine-tuning)是指在一个预训练好的大型语言模型(如GPT、BERT等)基础上,使用特定领域或任务的数据集进行额外训练,使模型适应特定任务的过程。与从零开始训练相比,微调能够利用预训练模型已经学习到的通用语言表示,只需相对较少的数据和计算资源就能获得良好的性能。

1.2 微调的必要性

尽管现代大语言模型(LLM)在预训练阶段已经学习了丰富的语言知识,但在特定场景下仍需要微调:

  1. 领域适应:使通用模型适应医疗、法律、金融等专业领域
  2. 任务定制:针对特定任务(如文本分类、问答、摘要等)优化模型
  3. 风格调整:调整生成内容的风格、语气或格式
  4. 性能提升:在特定指标上超越零样本或少样本学习的效果

1.3 微调的主要类型

  1. 全参数微调(Full Fine-tuning):更新模型所有权重参数
  2. 参数高效微调(Parameter-Efficient Fine-tuning, PEFT)
    • LoRA(Low-Rank Adaptation,低秩自适应)
    • 适配器(Adapter)
    • 前缀微调(Prefix Tuning)
    • 提示微调(Prompt Tuning)
  3. 指令微调(Instruction Fine-tuning):针对指令遵循能力进行优化

2. 微调技术详解

2.1 全参数微调(Full Fine-tuning)

全参数微调是最直接的微调方法,允许所有模型参数在微调过程中更新。这种方法通常能获得最佳性能,但也需要最多的计算资源。

技术特点:
  • 更新基础模型的所有参数
  • 需要相对较大的数据集(通常数千到数万样本)
  • 计算成本高,需要强大的GPU资源
  • 存在灾难性遗忘的风险

2.2 参数高效微调技术(PEFT)

2.2.1 LoRA(Low-Rank Adaptation)

LoRA通过低秩分解来减少可训练参数数量,其核心思想是:权重变化 ΔWΔWΔW 可以分解为两个小矩阵的乘积(ΔW=BAΔW = BAΔW=BA),其中 B∈Rd×r,A∈Rr×k,r≪min(d,k)B∈ℝ^{d×r},A∈ℝ^{r×k},r≪min(d,k)B∈Rd×r,A∈Rr×k,r≪min(d,k)。

优势

  • 显著减少可训练参数(通常减少90%以上)
  • 保持原始模型权重不变,易于切换任务
  • 训练后可将LoRA权重合并到基础模型中,不增加推理延迟
2.2.2 适配器(Adapter)

在Transformer层中插入小型全连接网络,仅训练这些适配器层而冻结原始模型参数。

2.2.3 前缀微调(Prefix Tuning)

在输入序列前添加可训练的任务特定前缀向量,引导模型生成期望的输出。

2.3 指令微调

指令微调旨在增强模型理解和遵循人类指令的能力。通过使用(指令,输入,输出)三元组数据集进行训练,使模型能够更好地泛化到未见过的任务。

关键点

  • 使用多样化的任务和指令
  • 强调任务描述的清晰表达
  • 有助于模型的零样本泛化能力

3. 微调实践指南

我们把轻量级的开源中文生成模型 uer/gpt2-chinese-cluecorpussmall 微调成一个可进行中文对话的问答模型。

3.1 准备工作

Colab 免费版:
  • GPU:NVIDIA T4(16GB 显存)
  • 可运行 QLoRA 微调 DeepSeek-1.3B
  • 内存:12GB RAM
  • 存储:至少 5GB 空闲空间(用于模型缓存)

软件环境:
# 基础环境配置
pip install torch transformers datasets accelerate

3.2 数据集准备

我们使用LLM生成训练数据,格式如下:

# train_data.py

chat_data = [
    {"text": "<user>如何选择护色剂?</user><bot>考虑种类、安全性和使用量。</bot>"},
    {"text": "<user>什么是UMAP?</user><bot>统一流形逼近与投影,降维方法。</bot>"},
    {"text": "<user>怎样学习银河摄影?</user><bot>从无月夜开始,学习广角构图,多实践。</bot>"},
    {"text": "<user>如何选择漂白剂?</user><bot>考虑种类、安全性和使用量。</bot>"},
    {"text": "<user>什么是自动编码器?</user><bot>通过压缩再重建实现降维的神经网络。</bot>"},
    {"text": "<user>怎样学习星野摄影?</user><bot>从简单地景开始,学习天地结合,多实践。</bot>"},
    {"text": "<user>如何选择酶制剂?</user><bot>考虑种类、活性和使用量。</bot>"},
    {"text": "<user>什么是聚类分析?</user><bot>将数据分组为相似集合的无监督学习。</bot>"},
    {"text": "<user>怎样学习延时摄影?</user><bot>从短间隔开始,学习后期合成,多实践。</bot>"},
    {"text": "<user>如何选择增味剂?</user><bot>考虑种类、安全性和使用量。</bot>"},
    {"text": "<user>什么是K-means?</user><bot>基于距离的经典聚类算法。</bot>"},
    {"text": "<user>怎样学习缩时摄影?</user><bot>从简单主体开始,学习间隔设置,多实践。</bot>"},
    ...
]

3.3 全参数微调示例

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, Trainer, TrainingArguments
from transformers import DataCollatorForLanguageModeling
from datasets import Dataset

from train_data import chat_data

# ----------------------------
# 1. 自动检测设备 (GPU 优先,否则 CPU)
# ----------------------------
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"当前设备:{device}")

# ----------------------------
# 2. 加载模型和分词器
# ----------------------------
model_name = "uer/gpt2-chinese-cluecorpussmall"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name).to(device)

# ----------------------------
# 3. 添加特殊token,扩充词表
# ----------------------------
special_tokens_dict = {
    "pad_token": "<pad>",
    "bos_token": "<s>",
    "eos_token": "</s>",
    "additional_special_tokens": ["<user>", "</user>", "<bot>", "</bot>"]
}
tokenizer.add_special_tokens(special_tokens_dict)
tokenizer.pad_token = tokenizer.eos_token
model.resize_token_embeddings(len(tokenizer))
  1. 看看微调之前
# ------------------------------------------------------------------
# 调用你微调后的中文 GPT 模型,根据用户输入的提示(prompt)生成对话回复
# ------------------------------------------------------------------
def chat(prompt, max_new_tokens=50):
    device = "cuda" if torch.cuda.is_available() else "cpu"
    inputs = tokenizer(prompt, return_tensors="pt").to(device)
    outputs = model.generate(
        inputs["input_ids"],
        max_new_tokens=max_new_tokens,
        eos_token_id=tokenizer.convert_tokens_to_ids("</bot>"),
        pad_token_id=tokenizer.pad_token_id,
        do_sample=False,  # 贪心解码,最保守
    )
    return tokenizer.decode(outputs[0], skip_special_tokens=True)


prompt = "<user>如何选择茶具?</user><bot>"
chat(prompt)

准备数据和设置参数

# ----------------------------
# 4. 使用 Dataset 加载数据
# ----------------------------
dataset = Dataset.from_list(chat_data)


# ----------------------------
# 5. 分词和标签处理,确保padding和truncation
# ----------------------------
def tokenize_function(example):
    encoding = tokenizer(
        example["text"],
        truncation=True,
        padding="max_length",
        max_length=512
    )
    encoding["labels"] = encoding["input_ids"].copy()
    return encoding


tokenized_dataset = dataset.map(tokenize_function)

# ----------------------------
# 6. 数据整理器,自动对齐输入和标签
# ----------------------------
data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)

# ----------------------------
# 7. 训练参数设置
# ----------------------------
training_args = TrainingArguments(
    output_dir="./chatgpt2-chinese",
    overwrite_output_dir=True,
    num_train_epochs=3,
    per_device_train_batch_size=4,
    save_steps=500,
    save_total_limit=2,
    logging_steps=50,
    fp16=True if device == "cuda" else False,  # 仅GPU时启用混合精度
    report_to="none"
)

# ----------------------------
# 8. Trainer 初始化
# ----------------------------
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset,
    data_collator=data_collator,
)

开始微调

# ----------------------------
# 9. 启动训练
# ----------------------------
trainer.train()

# ----------------------------
# 10. 保存模型和分词器
# ----------------------------
trainer.save_model("./chatgpt2-chinese")
tokenizer.save_pretrained("./chatgpt2-chinese")

看看微调效果

3.4 LoRA微调示例

  1. 环境依赖及支持
pip install transformers datasets peft accelerate
# utils.py

chat_data = [
    {"text": "<user>你好</user><bot>你好!请问有什么可以帮您?</bot>"},
    {"text": "<user>你是谁?</user><bot>我是一个由GPT模型训练的中文智能助手。</bot>"},
    {"text": "<user>你能做什么?</user><bot>我可以回答问题、写作、翻译和聊天。</bot>"},
    {"text": "<user>今天天气怎么样?</user><bot>抱歉,我无法查询实时天气,建议查看天气预报网站。</bot>"},
    {"text": "<user>讲个笑话</user><bot>为什么程序员喜欢下雨天?因为可以在家 debug!</bot>"},
    ...
]

# ------------------------------------------------------------------
# 调用你微调后的中文 GPT 模型,根据用户输入的提示(prompt)生成对话回复
# ------------------------------------------------------------------
def chat(model, tokenizer, prompt, max_new_tokens=50):
    device = "cuda" if torch.cuda.is_available() else "cpu"
    inputs = tokenizer(prompt, return_tensors="pt").to(device)
    outputs = model.generate(
        inputs["input_ids"],
        max_new_tokens=max_new_tokens,
        eos_token_id=tokenizer.convert_tokens_to_ids("</bot>"),
        pad_token_id=tokenizer.pad_token_id,
        do_sample=False,  # 贪心解码,最保守
    )
    return tokenizer.decode(outputs[0], skip_special_tokens=True)
import torch
from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    TrainingArguments,
    Trainer,
    DataCollatorForLanguageModeling,
)
from datasets import Dataset
from peft import get_peft_model, LoraConfig, TaskType

from utils import chat_data, chat

 2.加载模型

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 1. 加载预训练模型和分词器
model_name = "uer/gpt2-chinese-cluecorpussmall"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name).to(device)

微调前效果:

3.处理训练数据

# 4. 加载聊天语料,每行为一组完整的用户-助手对话
# 将 chat_data 转换为 Hugging Face Dataset 格式
dataset = Dataset.from_list(chat_data)


# 5. 将对话文本转换为模型输入格式(带标签input_ids)
def tokenize(example):
    encoding = tokenizer(
        example["text"],
        padding="max_length",
        truncation=True,
        max_length=512
    )
    encoding["labels"] = encoding["input_ids"].copy()
    return encoding


# 批处理分词 + 去除原始字段
tokenized_dataset = dataset.map(tokenize, batched=True, remove_columns=["text"])

# 6. 创建数据整理器(自动padding、生成labels等)
data_collator = DataCollatorForLanguageModeling(
    tokenizer=tokenizer,
    mlm=False  # GPT是自回归模型,不使用掩码语言建模
)

设置训练参数

# 7. 设置训练参数
training_args = TrainingArguments(
    output_dir="./chatgpt2-lora",  # 输出路径
    per_device_train_batch_size=4,  # 单卡batch size
    num_train_epochs=3,  # 训练轮次
    save_steps=500,  # 每500步保存一次模型
    save_total_limit=2,  # 最多保留2个checkpoint
    logging_steps=50,  # 每50步打印日志
    report_to="none",  # 不使用wandb等日志平台
    fp16=True  # 使用半精度训练以节省显存
)

# 8. 启动Trainer进行LoRA训练
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset,
    data_collator=data_collator,
)

进行微调训练

trainer.train()
  1. 保存训练参数
# 9. 保存LoRA适配器权重(不是完整模型)和tokenizer
model.save_pretrained("./chatgpt2-lora")
tokenizer.save_pretrained("./chatgpt2-lora")
# 9. 保存LoRA适配器权重(不是完整模型)和tokenizer
model.save_pretrained("./chatgpt2-lora")
tokenizer.save_pretrained("./chatgpt2-lora")

3.5 指令微调示例

# utils.py

def chat_instruction(tokenizer, model, instruction, input_text=""):
    """
    简单预测函数
    """
    device = "cuda" if torch.cuda.is_available() else "cpu"
    prompt = f"<s>指令:{instruction}\n输入:{input_text}\n输出:" if input_text else f"<s>指令:{instruction}\n输出:"
    inputs = tokenizer(prompt, return_tensors="pt").to(device)
    outputs = model.generate(
        inputs["input_ids"],
        max_new_tokens=100,
        do_sample=True,
        temperature=0.7,
        top_p=0.9,
        pad_token_id=tokenizer.pad_token_id,
        eos_token_id=tokenizer.eos_token_id
    )
    return tokenizer.decode(outputs[0], skip_special_tokens=True)
import torch
from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    TrainingArguments,
    Trainer,
    DataCollatorForLanguageModeling,
)
from peft import get_peft_model, LoraConfig, TaskType
from datasets import Dataset

from utils import chat_instruction

# 1. 设置设备
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 2. 加载模型和分词器
model_name = "uer/gpt2-chinese-cluecorpussmall"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name).to(device)

微调前:

chat_instruction(tokenizer, model, "介绍你自己")

# 3. 添加特殊 token
special_tokens = {
    "pad_token": "<pad>",
    "bos_token": "<s>",
    "eos_token": "</s>"
}
tokenizer.add_special_tokens(special_tokens)
tokenizer.pad_token = tokenizer.eos_token
model.resize_token_embeddings(len(tokenizer))

# 4. 配置 LoRA 参数
lora_config = LoraConfig(
    r=8,
    lora_alpha=32,
    target_modules=["c_attn", "c_proj"],
    lora_dropout=0.1,
    bias="none",
    task_type=TaskType.CAUSAL_LM
)
model = get_peft_model(model, lora_config).to(device)

# 5. 准备指令微调数据
chat_data = [
    {
        "instruction": "介绍你自己",
        "input": "",
        "output": "我是一个由 GPT 模型训练的中文智能助手,可以回答问题、写作、翻译和聊天等。"
    },
    {
        "instruction": "写一首关于春天的诗",
        "input": "",
        "output": "春风拂面百花开,柳绿莺啼燕归来。暖阳轻洒江南岸,山水悠悠入梦来。"
    },
    {
        "instruction": "将下面这句话翻译成英文",
        "input": "人生如逆旅,我亦是行人。",
        "output": "Life is like a journey against the current; I am just a traveler."
    },
    {
        "instruction": "讲一个冷笑话",
        "input": "",
        "output": "为什么程序员下雨天不带伞?因为他喜欢在云端工作。"
    },
    {
        "instruction": "什么是机器学习?",
        "input": "",
        "output": "机器学习是人工智能的一个分支,它让计算机通过数据自动学习规律,从而完成任务。"
    },
    {
        "instruction": "用Python写一个计算斐波那契数列的函数",
        "input": "",
        "output": "```python\ndef fib(n):\n    if n <= 1:\n        return n\n    return fib(n-1) + fib(n-2)\n```"
    },
    {
        "instruction": "写一段关于月亮的文案",
        "input": "",
        "output": "夜幕降临,月色如水。那轮皎洁的明月,像是一只温柔的眼睛,静静注视着人间的悲欢离合。"
    },
    {
        "instruction": "解释一下牛顿第一定律",
        "input": "",
        "output": "牛顿第一定律指出,物体在不受外力作用时,将保持静止状态或匀速直线运动状态。"
    },
    {
        "instruction": "推荐一本适合入门AI的书籍",
        "input": "",
        "output": "《机器学习实战》是一本适合 AI 入门者的经典书籍,内容通俗易懂,配有丰富代码示例。"
    },
    {
        "instruction": "将下面句子改写得更有文采",
        "input": "我喜欢看日出。",
        "output": "我痴迷于朝阳初升的那一刻,金光洒满天际,仿佛万物皆被唤醒。"
    }
]


# 6. 构造统一的 prompt 文本
def format_prompt(example):
    if example["input"]:
        return f"<s>指令:{example['instruction']}\n输入:{example['input']}\n输出:{example['output']}</s>"
    else:
        return f"<s>指令:{example['instruction']}\n输出:{example['output']}</s>"


for sample in chat_data:
    sample["text"] = format_prompt(sample)

# 7. 转换为 HF Dataset,并分词
dataset = Dataset.from_list(chat_data)


def tokenize(example):
    encoding = tokenizer(
        example["text"],
        truncation=True,
        padding="max_length",
        max_length=512,
    )
    encoding["labels"] = encoding["input_ids"].copy()
    return encoding


tokenized_dataset = dataset.map(tokenize, remove_columns=dataset.column_names)

# 8. 创建训练配置
training_args = TrainingArguments(
    output_dir="./gpt2-chinese-instruction-lora",
    per_device_train_batch_size=4,
    num_train_epochs=3,
    save_steps=500,
    logging_steps=50,
    fp16=torch.cuda.is_available(),
    report_to="none",
    save_total_limit=2,
)

data_collator = DataCollatorForLanguageModeling(
    tokenizer=tokenizer,
    mlm=False
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset,
    data_collator=data_collator,
)

# 9. 启动训练
trainer.train()

# 10. 保存模型和分词器
model.save_pretrained("./gpt2-chinese-instruction-lora")
tokenizer.save_pretrained("./gpt2-chinese-instruction-lora")

4. 微调优化策略

4.1 学习率调度

training_args = TrainingArguments(
    learning_rate=5e-5,
    lr_scheduler_type="cosine",  # 余弦退火
    warmup_steps=500,           # 预热步数
)

4.2 混合精度训练

training_args = TrainingArguments(
    fp16=True,  # 使用16位浮点数
    # 或
    bf16=True,  # 在支持bfloat16的硬件上
)

4.3 梯度累积

training_args = TrainingArguments(
    per_device_train_batch_size=4,
    gradient_accumulation_steps=4,  # 实际batch_size=16
)

4.4 模型量化(QLoRA)

from transformers import BitsAndBytesConfig
import torch

# 4位量化配置
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True,
)

# 加载量化模型
model = AutoModelForCausalLM.from_pretrained(
    "bigscience/bloom-560m",
    quantization_config=bnb_config,
    device_map="auto"
)

# 然后应用LoRA等PEFT方法

5. 微调后的评估与部署

5.1 模型评估

# 使用Trainer内置评估
trainer.evaluate()

# 或自定义评估函数
from sklearn.metrics import accuracy_score

def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=-1)
    return {"accuracy": accuracy_score(labels, predictions)}

5.2 模型保存与加载

# 保存全模型
model.save_pretrained("./full_model")
tokenizer.save_pretrained("./full_model")

# 保存PEFT适配器
peft_model.save_pretrained("./adapter")

# 加载
from peft import PeftModel

base_model = AutoModelForCausalLM.from_pretrained("bigscience/bloom-560m")
peft_model = PeftModel.from_pretrained(base_model, "./adapter")

5.3 模型合并(LoRA)

# 将LoRA权重合并到基础模型中
merged_model = peft_model.merge_and_unload()
merged_model.save_pretrained("./merged_model")

6. 微调中的常见问题与解决方案

6.1 过拟合

解决方案

  • 增加数据集规模
  • 使用更强的正则化(如权重衰减、dropout)
  • 早停(Early Stopping)
  • 减少训练epoch数

6.2 灾难性遗忘

解决方案

  • 使用较小的学习率(通常1e-5到5e-5)
  • 混合通用数据和任务特定数据
  • 采用参数高效微调方法(如LoRA)

6.3 显存不足

解决方案

  • 使用梯度累积
  • 采用混合精度训练
  • 应用模型量化(如QLoRA)
  • 使用参数高效微调方法
  • 启用梯度检查点
model.gradient_checkpointing_enable()

结语

大模型微调是将通用语言模型适配到特定任务的关键技术。随着参数高效微调技术的发展,现在即使是资源有限的研究者和开发者也能有效地定制大语言模型。选择何种微调方法取决于具体任务、数据规模和可用资源。在实践中,建议从LoRA等PEFT方法开始,逐步探索更复杂的微调策略。

通过本文介绍的概念、技术和代码示例,读者应能够开始自己的大模型微调实践,并根据具体需求进行调整和优化。

 零基础入门AI大模型

今天贴心为大家准备好了一系列AI大模型资源,包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

1.学习路线图

在这里插入图片描述

第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;

第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

2.视频教程

网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己整理的大模型视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。

 

 

(都打包成一块的了,不能一一展开,总共300多集)

3.技术文档和电子书

这里主要整理了大模型相关PDF书籍、行业报告、文档,有几百本,都是目前行业最新的。

4.LLM面试题和面经合集

这里主要整理了行业目前最新的大模型面试题和各种大厂offer面经合集。

 

👉学会后的收获:👈

• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

1.AI大模型学习路线图
2.100套AI大模型商业化落地方案
3.100集大模型视频教程
4.200本大模型PDF书籍
5.LLM面试题合集
6.AI产品经理资源合集

5.免费获取(扫下方二v码即可100%领取)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值