Skip to content

模型微调全流程总结


一、Transformer 模型基础

1. 什么是 NLP(自然语言处理)?

定义: NLP 是语言学和机器学习的交叉领域,专注于理解与人类语言相关的一切。

目标: 不仅理解单个单词,而是理解单词的上下文和语义关系。

2. Transformer 是什么?

定义: Transformer 是一种神经网络架构,2017年由Google提出,是现代大语言模型(BERT、GPT等)的基础。

核心创新: 自注意力机制(Self-Attention)

传统模型(RNN):
  逐个处理单词,像读书一样从头读到尾
  问题:后面的内容看不到前面的,处理长文本困难

Transformer:
  同时看到所有单词,像一眼看整篇文章
  优势:能捕捉长距离的语义关系,并行计算速度快

3. Transformer 核心组件

┌─────────────────────────────────────────────────────────────┐
│                    Transformer 架构                          │
└─────────────────────────────────────────────────────────────┘

  输入文本: "我喜欢学习机器学习"


  ┌──────────────┐
  │  Embedding   │  文字 → 数字向量
  │  (词嵌入)     │  每个 token → 768维向量
  └──────────────┘


  ┌──────────────┐
  │  Position    │  加上位置信息
  │  Encoding    │  让模型知道词的顺序
  └──────────────┘


  ┌──────────────────────────────────────┐
  │  Self-Attention (自注意力)            │
  │  ┌────────────────────────────────┐  │
  │  │ "我" 关注谁? → "喜欢"、"学习"   │  │
  │  │ "机器学习" 关注谁? → "学习"     │  │
  │  │ 每个词都能看其他所有词           │  │
  │  └────────────────────────────────┘  │
  │  作用:理解词与词之间的关系           │
  └──────────────────────────────────────┘


  ┌──────────────┐
  │  Feed Forward│  进一步处理
  │  Network     │  提取语义信息
  └──────────────┘

      ▼  (重复多层)


  ┌──────────────┐
  │  Output      │  输出结果
  └──────────────┘

自注意力通俗理解:

例子:"猫坐在垫子上,它很舒服"

自注意力作用:
  "它" 这个词应该关注谁?
  - 关注"猫" → 知道"它"指的是猫
  - 关注"垫子" → 也有可能指垫子
  
模型通过注意力权重判断:更可能指"猫"

4. Transformer 家族

┌─────────────────────────────────────────────────────────────┐
│                  Transformer 模型家族                        │
└─────────────────────────────────────────────────────────────┘

  ┌─────────────┐
  │ Transformer │ (2017 Google,原始架构)
  └─────────────┘

   ┌────┴────┐
   │         │
   ▼         ▼
┌─────┐   ┌─────┐
│ BERT│   │ GPT │
│编码器│   │解码器│
└─────┘   └─────┘
   │         │
   ▼         ▼
理解类任务  生成类任务
- 分类      - 写文章
- 问答      - 翻译
- 搜索      - 对话

BERT vs GPT 对比:

对比项BERT(编码器)GPT(解码器)
方向双向(看前后文)单向(只看前文)
训练方式填空(预测遮盖词)预测下一个词
适用任务理解类:分类、问答生成类:写作、对话
代表模型BERT, RoBERTaGPT-3, GPT-4, ChatGPT

二、NLP 任务类型与应用

1. 四大类 NLP 任务

┌─────────────────────────────────────────────────────────────┐
│                    NLP 任务分类                              │
└─────────────────────────────────────────────────────────────┘

【类型一:文本分类】
  输入:一段文本
  输出:类别标签
  
  ┌────────────────────┐
  │ "这部电影很精彩!"  │ → 情感分析 → "正面"
  └────────────────────┘
  
  应用:情感分析、新闻分类、垃圾邮件检测

【类型二:序列标注】
  输入:一段文本
  输出:每个词的标签
  
  ┌────────────────────────────────────┐
  │ "张三在北京创办了公司"              │
  │   ↓    ↓    ↓                      │
  │  人名  地名  O                      │ → 命名实体识别
  └────────────────────────────────────┘
  
  应用:命名实体识别(NER)、词性标注

【类型三:文本生成】
  输入:提示文本/条件
  输出:新生成的文本
  
  ┌────────────────────┐
  │ "请写一首关于春天的诗"│ → 文本生成 → "春风拂面..."
  └────────────────────┘
  
  应用:机器翻译、摘要生成、对话系统、写作助手

【类型四:问答/抽取】
  输入:问题 + 文本
  输出:答案
  
  ┌────────────────────────────────────┐
  │ 文本:"BERT是Google在2018年提出的" │
  │ 问题:"BERT是谁提出的?"            │ → "Google"
  └────────────────────────────────────┘
  
  应用:问答系统、信息抽取

2. 常见 NLP 任务详解

任务名称输入输出应用场景代表模型
情感分析评论文本正/负情感产品评论分析BERT微调
命名实体识别(NER)文本实体类型信息提取、知识图谱BERT+CRF
机器翻译源语言文本目标语言文本跨语言翻译T5, mBART
文本摘要长文章简短摘要新闻摘要BART, PEGASUS
问答系统问题+文档答案智能客服BERT, DPR
文本生成提示词生成的文本写作助手GPT系列
句子相似度两个句子相似度分数搜索匹配sentence-transformers
填空预测(MLM)遮盖文本预测遮盖词预训练BERT

3. 任务对应的模型架构

┌─────────────────────────────────────────────────────────────┐
│              任务类型 → 推荐模型架构                          │
└─────────────────────────────────────────────────────────────┘

  理解类任务(分类、标注、问答)


  ┌─────────────────┐
  │  Encoder-only   │
  │  (BERT系列)     │
  │                 │
  │  - BERT         │
  │  - RoBERTa      │
  │  - ALBERT       │
  │  - DistilBERT   │
  └─────────────────┘

  生成类任务(翻译、摘要、写作)


  ┌─────────────────┐
  │  Decoder-only   │    或    Encoder-Decoder
  │  (GPT系列)      │         (T5, BART)
  │                 │
  │  - GPT-2/3/4    │         - T5 (翻译、问答)
  │  - LLaMA        │         - BART (摘要)
  │  - Claude       │         - mBART (多语言翻译)
  └─────────────────┘

  序列标注类任务


  ┌─────────────────┐
  │  BERT + CRF     │
  │  或 BERT + 分类头│
  │                 │
  │  - NER (命名实体)│
  │  - POS (词性标注)│
  └─────────────────┘

4. 从预训练到任务适配

┌─────────────────────────────────────────────────────────────┐
│              预训练模型 → 下游任务适配                        │
└─────────────────────────────────────────────────────────────┘

  预训练模型(通用语言能力)

      │  加任务特定的"头"(Head)


  ┌─────────────────────────────────┐
  │  分类任务:Classification Head   │
  │  输入 → BERT → 分类头 → 类别     │
  │  (如:正面/负面情感)              │
  └─────────────────────────────────┘
  
  ┌─────────────────────────────────┐
  │  标注任务:Token Classification  │
  │  输入 → BERT → 每个token分类     │
  │  (如:人名/地名/其他)             │
  └─────────────────────────────────┘
  
  ┌─────────────────────────────────┐
  │  问答任务:Span Prediction       │
  │  问题+文档 → BERT → 答案位置     │
  │  (如:答案从第5词到第8词)         │
  └─────────────────────────────────┘
  
  ┌─────────────────────────────────┐
  │  生成任务:Language Model Head   │
  │  输入 → GPT → 逐词生成           │
  │  (如:根据前文生成后文)           │
  └─────────────────────────────────┘

三、为什么要微调模型

预训练模型的局限性:

  • 预训练模型的分类头是随机初始化的,在下游任务上表现接近随机猜测
  • 例如二分类任务,未微调的模型准确率约50-70%,远低于实际需求

微调的价值:

  • 让预训练模型适应特定任务(如文本分类、问答、翻译等)
  • 充分利用预训练模型已学习的大量通用知识
  • 只需少量任务数据即可获得优异效果
  • 相比从头训练,大幅降低计算成本和数据需求

四、微调的原理

核心思想: 预训练 → 微调(Pre-training → Fine-tuning)

预训练 vs 微调:两种学习方式的对比

对比项预训练(无监督学习)微调(监督学习)
学习方式无监督学习监督学习
数据要求海量无标注文本(TB级)少量标注数据(几千条)
数据特点只有文本,没有答案文本 + 标注好的答案
学习目标学习通用语言知识(词义、语法)学习特定任务的模式
训练方式自监督:预测下一个词、填空等有监督:根据答案调整模型
例子BERT:预测被遮盖的词MRPC:判断两个句子是否同义

通俗理解:

  • 预训练 = 读书学习:模型读了海量书籍,学会了语言的基本规律,但不知道如何回答具体问题
  • 微调 = 考前刷题:给模型做有答案的练习题,让它学会如何回答特定类型的考题

举例说明:

预训练阶段(无监督):
输入:海量文本,如维基百科、新闻、小说等
任务:预测下一个词、填空
例子:"今天天气很_____" → 模型学习预测"好/坏/晴..."
答案来源:文本本身(自监督)

微调阶段(监督):
输入:标注好的数据
任务:判断两个句子是否同义
例子:
  句子1:"苹果发布新手机"
  句子2:"Apple推出新款iPhone"
  答案(人工标注):同义(label=1)
答案来源:人工标注(有监督)

为什么需要两种阶段?

预训练的作用:

  • 让模型掌握语言基础能力
  • 一次训练,所有任务受益(通用性)

微调的作用:

  • 让模型适应具体任务
  • 用少量数据快速获得专业能力

关键技术:

组件作用
AdamW优化器带权重衰减的Adam,正则化效果更好,是BERT训练的标准选择
学习率调度器学习率随训练逐渐降低,初期快速学习,后期精细调整
Batch训练多样本并行计算,梯度更稳定,训练更平滑

五、微调流程

完整流程图:

┌─────────────────────────────────────────────────────────────────────────────┐
│                           模型微调完整流程                                    │
└─────────────────────────────────────────────────────────────────────────────┘

     ┌──────────────────┐
     │  1. 数据准备      │
     │  load_dataset()   │
     │  获取训练/验证集   │
     └───┬──────────────┘


     ┌──────────────────┐
     │  2. 数据预处理    │
     │  Tokenizer分词    │
     │  → input_ids      │
     │  动态填充         │
     └───┬──────────────┘


     ┌──────────────────┐
     │  3. 模型加载      │
     │  from_pretrained  │
     │  ('bert-base')    │
     │  num_labels=2     │
     └───┬──────────────┘


     ┌──────────────────┐
     │  4. 训练配置      │
     │  epochs=3         │
     │  lr=5e-5          │
     │  batch_size=8     │
     │  AdamW优化器      │
     └───┬──────────────┘


     ┌──────────────────┐
     │  5. 训练循环      │─────────────────────────────┐
     │                   │                             │
     │  ┌─────────────┐  │   每个batch:                │
     │  │ 前向传播    │  │   1. outputs = model(**batch)│
     │  │ 计算loss    │  │   2. loss.backward()        │
     │  └─────────────┘  │   3. optimizer.step()       │
     │        │          │   4. optimizer.zero_grad()  │
     │        ▼          │                             │
     │  ┌─────────────┐  │   重复num_epochs轮          │
     │  │ 反向传播    │  │◄────────────────────────────┘
     │  │ 计算梯度    │  │
     │  └─────────────┘  │
     │        │          │
     │        ▼          │
     │  ┌─────────────┐  │
     │  │ 更新参数    │  │
     │  │ 清零梯度    │  │
     │  └─────────────┘  │
     └───┬──────────────┘


     ┌──────────────────┐
     │  6. 评估         │
     │  predict验证集    │
     │  argmax(logits)  │
     │  → 预测类别       │
     │  计算accuracy/F1 │
     └───┬──────────────┘


     ┌──────────────────┐
     │  7. 保存模型     │
     │  save_pretrained │
     │  (模型+tokenizer)│
     └──────────────────┘

1. 数据准备

python
from datasets import load_dataset
raw_datasets = load_dataset("glue", "mrpc")  # 加载MRPC句子对分类数据集

2. 数据预处理

python
from transformers import AutoTokenizer, DataCollatorWithPadding

tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")

# 分词处理
def tokenize_function(example):
    return tokenizer(example["sentence1"], example["sentence2"], truncation=True)

tokenized_datasets = raw_datasets.map(tokenize_function, batched=True)

# 动态填充(保证batch内长度统一)
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)

3. 模型加载

python
from transformers import AutoModelForSequenceClassification

model = AutoModelForSequenceClassification.from_pretrained("bert-base-uncased", num_labels=2)

4. 训练配置

python
from transformers import TrainingArguments, Trainer

training_args = TrainingArguments(
    "test-trainer",
    eval_strategy="epoch",  # 每个epoch结束后评估
    num_train_epochs=3,
    learning_rate=5e-5,
    per_device_train_batch_size=8
)

5. 训练循环

python
trainer = Trainer(
    model,
    training_args,
    train_dataset=tokenized_datasets["train"],
    eval_dataset=tokenized_datasets["validation"],
    data_collator=data_collator,
    processing_class=tokenizer,
    compute_metrics=compute_metrics
)

trainer.train()

手动训练循环(无Trainer API):

python
# 优化器和学习率调度器
optimizer = AdamW(model.parameters(), lr=5e-5)
lr_scheduler = get_scheduler("linear", optimizer, num_training_steps=num_training_steps)

# 训练
model.train()
for epoch in range(num_epochs):
    for batch in train_dataloader:
        outputs = model(**batch)       # 前向传播
        loss = outputs.loss
        loss.backward()                # 反向传播
        optimizer.step()               # 更新参数
        lr_scheduler.step()            # 更新学习率
        optimizer.zero_grad()          # 清零梯度

6. 评估

python
import evaluate
metric = evaluate.load("glue", "mrpc")
predictions = trainer.predict(tokenized_datasets["validation"])
preds = np.argmax(predictions.predictions, axis=-1)
metric.compute(predictions=preds, references=predictions.label_ids)

7. 保存模型

python
model.save_pretrained("./my-model")
tokenizer.save_pretrained("./my-model")

六、微调后的效果

MRPC任务效果对比:

数据集指标Baseline(微调前)微调后提升
ValidationAccuracy0.68380.8578+17.4%
ValidationF10.81220.8990+8.7%
TestAccuracy0.66490.8458+18.1%
TestF10.79870.8871+8.8%

效果分析:

  • Accuracy相对提升约26%,属于显著提升
  • 微调结果接近BERT-base的典型水平(84-85% accuracy)
  • 说明微调有效,模型成功学习了任务特定的模式

与基准对比:

模型AccuracyF1
原始BERT(未微调)~60-70%~75-80%
微调后BERT-base84-85%88-89%
更强模型(RoBERTa等)~90%~92%
人类水平~90%~92%

七、Embedding 语义向量

1. 什么是 Embedding?

定义: Embedding 是将文本转换为高维向量(数值数组)的过程,使得语义相似的文本在向量空间中距离更近。

"How to load dataset" → [0.12, -0.34, 0.56, ..., 0.78]  (768维向量)
"I want to download data" → [0.15, -0.30, 0.52, ..., 0.75]  (语义相似,向量相近)
"The weather is nice" → [0.89, 0.12, -0.45, ..., -0.23]  (语义不同,向量距离远)

通俗理解:

  • Embedding = 把文字翻译成数字坐标
  • 语义相似的两个句子,坐标位置相近
  • 通过向量距离就能判断语义相似度

八、RAG 检索增强生成

1. 什么是 RAG?

定义: RAG(Retrieval-Augmented Generation) = 检索 + 生成

核心流程:

用户问题 → Embedding → 向量检索 → 获取相关文档 → 拼接到Prompt → LLM生成回答

为什么需要 RAG?

问题RAG 解决方案
LLM知识过时实时检索最新文档
LLM会编造答案基于真实文档回答
私有数据无法训练检索私有知识库

2. RAG 完整流程

┌─────────────────────────────────────────────────────────────┐
│                      RAG 架构                                │
└─────────────────────────────────────────────────────────────┘

【阶段一:知识库构建】

  文档 → 分块 → Embedding → 存入向量数据库(FAISS)
  
     ┌────────────┐
     │  原始文档   │
     │  (10000字)  │
     └───┬────────┘
         │ 分块

     ┌────────────┐
     │  Chunk 1   │ → Embedding → 存入FAISS
     │  Chunk 2   │ → Embedding → 存入FAISS
     │  Chunk 3   │ → Embedding → 存入FAISS
     └────────────┘

【阶段二:查询】

  问题 → Embedding → FAISS相似度搜索 → Top-K相关文档
  
     ┌────────────┐
     │  用户问题   │
     │  "如何..."  │
     └───┬────────┘
         │ Embedding

     ┌────────────┐
     │  查询向量   │
     │  [0.12,...] │
     └───┬────────┘
         │ FAISS搜索

     ┌────────────┐
     │  相关文档   │
     │  Top-K=5   │
     └────────────┘

【阶段三:生成】

  问题 + 相关文档 → Prompt → LLM → 回答
  
     ┌─────────────────────────────────┐
     │  Prompt:                         │
     │  问题:如何加载离线数据集?        │
     │  参考资料:                       │
     │  - 文档1: 使用load_dataset()...   │
     │  - 文档2: 支持CSV/JSON格式...      │
     │  请基于参考资料回答:              │
     └────────────┴────────────────────┘

              ┌──────────┐
              │    LLM   │
              └──────────┘

              ┌──────────┐
              │  回答     │
              └──────────┘

3. Embedding 搜索 vs 关键词搜索

对比项关键词搜索Embedding 语义搜索
"如何下载模型"匹配不到"离线加载"能匹配(语义相似)
"报错了怎么办"匹配不到具体错误能找到解决方案
精确度精确匹配语义理解
适用场景明确关键词自然语言问答

九、Agentic RAG(智能检索)

传统 RAG vs Agentic RAG

【传统 RAG - 被动检索】
用户问题 → 固定流程检索 → 拼接文档 → LLM生成
特点:检索是前置的、固定的、模型被动接收

【Agentic RAG - 主动检索】
用户问题 → LLM分析 → LLM决定是否检索 →
LLM调用检索工具 → LLM分析结果 → 可能再检索 → LLM总结
特点:检索由模型主动决策、可迭代、可多轮

Agentic RAG 的优势

优势说明
智能判断模型自己判断是否需要检索("你好"不需要检索)
动态查询模型可以优化查询词
迭代检索第一次不满意,可以调整策略再检索
多源检索可以调用多个不同的知识库
上下文理解根据对话历史决定检索什么

流程示例

用户:"HuggingFace datasets 如何处理大数据?"

LLM分析:"需要检索知识库"

LLM调用:search("datasets large data memory mapping", k=5)

工具返回:5条相关文档

LLM分析:"提到了memory mapping,但不够详细,再检索"

LLM调用:search("Apache Arrow lazy loading", k=3)

工具返回:3条补充文档

LLM总结:综合所有文档生成回答

全文关键要点总结

Transformer 与 NLP 基础

  1. Transformer核心:自注意力机制,让每个词都能看到其他所有词
  2. BERT vs GPT:BERT双向理解(分类、问答),GPT单向生成(写作、对话)
  3. 四大NLP任务:文本分类、序列标注、文本生成、问答抽取

微调核心流程

  1. 微调必要性:预训练模型需要任务适配才能发挥作用
  2. 核心流程:数据准备 → 预处理 → 训练 → 评估 → 保存
  3. 关键技术:动态填充、AdamW优化器、学习率调度
  4. 效果显著:3个epoch即可达到BERT-base典型水平

Embedding 与 RAG

  1. Embedding本质:把文本翻译成数字坐标,语义相似的坐标相近
  2. 维度由模型决定:BERT-base是768维,越大模型维度越高
  3. RAG流程:知识库构建 → 查询检索 → Prompt拼接 → LLM生成
  4. 语义搜索优势:能理解用户意图,比关键词搜索更智能
  5. Agentic RAG:让模型主动决定是否检索、如何检索
  6. 文档过长方案:分块是最常用的解决方案

参考资源


Move fast and break things