引言
"我们业务只有几百张标注图,能从零训个模型吗?"——几乎每个落地项目都会被问到。答案是:别从零训,站在预训练模型的肩膀上。迁移学习正是把 ImageNet 上预训练好的视觉先验、或大规模语料上预训练好的语言先验,"借"到你的小数据任务上。本篇拆解两种用法,并给出小样本下的量化收益与实操技巧。
一、迁移学习两类范式
1.1 特征提取式(Feature Extraction)
冻结预训练骨干(backbone)的所有参数,只训练你接在后面的新分类头。相当于把 backbone 当作一个"固定的特征提取器"。
优点:训练快、显存省、几乎不过拟合。
缺点:backbone 的特征是通用域的,未必适配你的特定分布。
适用:数据极少(几百~几千)、任务与预训练域接近。
1.2 微调式(Fine-tuning)
解冻全部或大部分层,端到端用小学习率继续训练,让 backbone 适配你的数据。
优点:上限更高,能学到领域专属特征。
缺点:显存大、易过拟合、需要谨慎调学习率。
适用:数据较多(万级及以上)、任务与预训练域有差异。
二者不是二选一,实践中常组合:先特征提取跑通,再分层解冻做微调,见第四节。
二、CV 侧 ResNet 迁移实验(思路与代码)
以一个"小样本医疗影像二分类"为例,对比三种方案。下面给出可运行的关键代码(基于torchvision,数值为公开基准典型区间,随数据规模与随机种子浮动,非本机实测):
import torch from torchvision import models, transforms from torch import nn, optim # 1) 加载 ImageNet 预训练 ResNet-18 weights = models.ResNet18_Weights.DEFAULT backbone = models.resnet18(weights=weights) # 2) 特征提取式:冻结 backbone,只换最后一层 for param in backbone.parameters(): param.requires_grad = False in_feat = backbone.fc.in_features backbone.fc = nn.Linear(in_feat, 2) # 你的类别数 # 特征提取阶段只优化 fc optimizer = optim.Adam(backbone.fc.parameters(), lr=1e-3) # 3) 微调式:解冻全部,整体小学习率 for param in backbone.parameters(): param.requires_grad = True optimizer_all = optim.AdamW(backbone.parameters(), lr=3e-5, weight_decay=0.01)三种方案的典型收益对比(数百张标注、公开基准区间):
| 方案 | 准确率(典型区间) | 过拟合风险 |
|---|---|---|
| 从零训练 | ~60% | 极高 |
| 特征提取(冻结 backbone) | ~78% | 低 |
| 全模型微调 | ~85% | 中(需正则) |
迁移学习把小数据任务从"不可用"拉到"可用"——这正是它成为落地第一选择的原因。
三、NLP 侧 BERT 迁移对照
NLP 的迁移范式与 CV 完全同构,只是 backbone 换成 BERT:
from transformers import BertForSequenceClassification, BertTokenizer model = BertForSequenceClassification.from_pretrained( "bert-base-chinese", num_labels=2) tokenizer = BertTokenizer.from_pretrained("bert-base-chinese") # 同样可以冻结底层、只训顶层——垂直领域小数据常用 for name, param in model.named_parameters(): if "encoder.layer.11" not in name and "classifier" not in name: param.requires_grad = False # 仅解冻最后一层 + 分类头垂直领域(如医疗、法律文本)与通用语料分布差异大时,分层解冻 + 差异化学习率(见下节)往往比全量微调更稳。
四、分层解冻与差异化学习率
微调的核心技巧是"越靠近输入的层越通用、越靠近输出的层越任务相关"。因此:
分层解冻(Layer-wise Unfreezing):先只训顶层,确认收敛后再逐步解冻更深的层。
差异化学习率(Discriminative LR):浅层小学习率(如 1e-5),深层大学习率(如 3e-4),避免浅层通用特征被破坏。
# PyTorch 给不同层组设置不同学习率 params = [ {"params": backbone.conv1.parameters(), "lr": 1e-5}, {"params": backbone.layer2.parameters(), "lr": 3e-5}, {"params": backbone.layer3.parameters(), "lr": 1e-4}, {"params": backbone.fc.parameters(), "lr": 3e-4}, ] optimizer = optim.Adam(params)此外,数据增强强度要适配迁移阶段:特征提取阶段可增强弱一些(避免破坏预训练特征),微调阶段可增强强一些(防过拟合)。
五、小样本效果量化与适用边界
| 你的标注数据量 | 推荐策略 |
|---|---|
| < 1k | 特征提取 + 强数据增强,慎用全微调 |
| 1k ~ 10k | 分层解冻,差异化学习率 |
| > 10k | 可考虑全模型微调,甚至从头预训练子集 |
| 跨域极大(如 X 光 → 自然图像) | 用领域自适应 / 自监督再预训练打底 |
避坑:
预训练域与任务域差异过大时,直接微调可能"负迁移",此时先做自监督预训练更靠谱。
分类头随机初始化容易在初期"污染"backbone 梯度,建议先用特征提取暖机几轮。
六、适用边界总结
迁移学习不是银弹,它的前提是"存在可复用的通用特征"。当你的任务与预训练域高度同构(如自然图像分类、通用中文文本分类),收益最大;当任务极其特殊(如特定工业缺陷、罕见蛋白质结构),则需要更多领域数据或自监督打底。
总结
迁移学习把"数据少"这个落地最大障碍变成了可管理问题:冻结骨干做特征提取保底,分层解冻做微调冲上限。本文的 CV/NLP 双对照与差异化学习率代码,可直接套进你的项目。记住一句话——小数据别从零训,先借预训练模型的力。
参考资料
Pan, S. J., & Yang, Q. (2010).A Survey on Transfer Learning.
Yosinski, J., et al. (2014).How transferable are features in deep neural networks?
Hugging Face Transformers 迁移微调文档。
torchvision 预训练模型列表与权重说明。
往期回顾
模型训练调参技巧——学习率、正则化与优化器
循环神经网络及其变体 LSTM/GRU 实战
BERT 模型原理解析与微调实战
关注作者,继续《深度学习工程化》专栏:下一篇进入计算机视觉的"定位"世界——目标检测 YOLO 演进。
📚本篇出自专栏《深学之路:从感知机到智能体》—— 从感知机到大模型智能体的完整深度学习连载(基础+工程化 、扩散模型 / RAG / Agent 等)。每篇附可运行代码与原创实验,收藏专栏不迷路。