迁移学习与预训练模型

机器学习专题 · 掌握迁移学习与预训练模型

专题:Python机器学习系统学习

关键词:Python, 机器学习, 迁移学习, 预训练模型, 微调, 特征提取, ResNet, BERT, HuggingFace

一、迁移学习概述

1. 什么是迁移学习

迁移学习(Transfer Learning)是机器学习中的一个重要方法,其核心思想是:将从一个任务(源任务)中学习到的知识应用到另一个相关任务(目标任务)中。通俗地说,就是"举一反三"——利用已经学会的知识来解决新问题,而不是从零开始学习。

在深度学习中,这意味着可以将在一个大型数据集(如ImageNet)上训练好的模型权重,作为解决新任务的起点。这种方式极大地降低了新任务对数据量和计算资源的需求。

2. 为什么需要迁移学习

传统的机器学习方法要求每个新任务都需要大量标注数据从头训练模型,这在很多实际场景中并不可行。迁移学习的必要性体现在以下几个方面:

3. 传统学习 vs 迁移学习

对比维度传统学习迁移学习
数据需求每个任务需要大量标注数据目标任务只需少量标注数据
训练起点随机初始化权重预训练权重初始化
训练时间长(数天到数周)短(数分钟到数小时)
泛化性能小数据下容易过拟合利用源域知识,泛化更强
计算资源需要大量GPU资源资源需求显著降低
适用场景数据充足且独立同分布目标域数据有限或分布有偏移

4. 迁移学习的适用场景

迁移学习特别适用于以下场景:一是目标任务标注数据有限但存在相关的大规模源域数据时,如使用ImageNet预训练模型进行医学图像分类;二是源域和目标域的特征分布存在差异但任务相关时,如从自然图像迁移到卫星图像分析;三是需要快速原型验证的场景,利用预训练模型快速搭建基线系统;四是在计算资源受限的环境中,通过迁移学习减少模型训练的计算开销。

二、迁移学习的类型

迁移学习根据源域和目标域的关系、标注数据的可用性以及学习任务的性质,可以分为以下几种主要类型:

1. 归纳迁移(Inductive Transfer)

归纳迁移是最常见的迁移学习类型。在这种设置中,源任务和目标任务不同,但目标域有少量的标注数据可用于归纳学习。具体又可分为两种情况:多任务学习(同时学习多个相关任务,共享表示)和自学习(源域有标注数据,目标域也有少量标注数据)。代表性应用包括多语言文本分类、联合目标检测等。

2. 转导迁移(Transductive Transfer)/ 直推式迁移

转导迁移(也称直推式迁移)中,源任务和目标任务相同,但源域和目标域的数据分布不同。目标域没有标注数据,只有未标注数据。常见的场景包括域适应(Domain Adaptation),即在不同但相关的域之间迁移知识。例如,在自然图像上训练的目标检测模型需要调整为适应监控摄像头拍摄的图像,自然图像的风格和监控图像的风格明显不同,但检测目标(如行人、车辆)是相同的。

3. 无监督迁移(Unsupervised Transfer)

无监督迁移适用于目标域没有任何标注数据的场景。源域和目标域的任务不同但相关。这种方法通常依赖于自监督学习(Self-supervised Learning)或聚类等技术来学习可迁移的特征表示。近年来的大语言模型预训练本质上就是无监督迁移的典型例子——模型在海量无标注文本上进行自监督预训练,然后通过少量标注数据进行微调。

4. 域适应(Domain Adaptation)

域适应是迁移学习的一个热门子领域,核心目标是减小源域和目标域之间的分布差异。主要方法包括:对抗性域适应(使用对抗训练来学习域不变特征,如DANN、CDAN等)、基于差异的域适应(通过MMD等距离度量最小化域间差异)以及基于重构的域适应(通过自编码器重构保留域-specific信息的同时学习共享表示)。

要点总结:选择哪种迁移学习方法取决于目标任务是否有标注数据(归纳 vs 无监督)以及源域和目标域数据分布是否相同(直推式 vs 归纳)。在实际应用中,归纳迁移的微调方法最为常用。

三、预训练模型

1. 预训练的概念

预训练(Pre-training)是指在一个大规模通用数据集上训练一个基础模型,使其学习到通用的特征表示或语言知识。这个预训练过程完成后,模型权重被保存下来,可以用于下游任务的初始化或特征提取。预训练的核心前提是:在大规模数据上学到的低级特征(如边缘、纹理、语法结构等)在不同任务之间是通用的。

2. 计算机视觉预训练模型

在计算机视觉领域,ImageNet数据集(包含1000类、超过1400万张图像)是最常用的预训练基准。以下主流的视觉架构均有ImageNet预训练版本:

3. NLP预训练模型

自然语言处理领域经历了从词向量(Word2Vec、GloVe)到预训练语言模型的范式转变。现代NLP几乎完全依赖于大规模预训练模型:

4. HuggingFace Hub模型库

HuggingFace Hub是目前最大的预训练模型开源社区,托管了超过50万个模型和10万个数据集。通过HuggingFace的transformers库,可以轻松加载各类预训练模型并进行微调:

from transformers import AutoTokenizer, AutoModelForSequenceClassification # 一行代码加载预训练模型 tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese") model = AutoModelForSequenceClassification.from_pretrained( "bert-base-chinese", num_labels=2 )

HuggingFace不仅提供了模型加载接口,还提供了Trainer API、数据集库(datasets)、评估指标库(evaluate)等全套生态工具,大大简化了NLP迁移学习的工作流程。

四、迁移学习策略

1. 特征提取器(Feature Extraction)

特征提取策略的核心思想是:将预训练模型作为一个固定的特征提取器,冻结其所有权重参数,只训练新添加的分类器。具体做法是,去掉预训练模型的原始分类层(通常是全连接层),将剩余部分作为特征提取器,输入新的数据得到特征向量,然后在这些特征向量上训练一个新的分类器(如线性SVM、逻辑回归或小型全连接网络)。

这种方法的优点是训练速度快、需要的数据量少、不容易过拟合。适用于目标数据集较小(几百到几千张图片)且与源域数据(如ImageNet)相似度较高的场景。

2. 微调(Fine-tuning)

微调是在预训练模型的基础上,使用目标任务的数据对整个网络(或部分网络)进行继续训练。微调的策略更加灵活:可以选择以较小的学习率更新所有的网络层,也可以只微调最后几层而冻结前面的层。

微调的关键注意事项包括:使用比从头训练更小的学习率(通常为1e-5到5e-5),避免破坏预训练学到的良好特征;可以结合学习率衰减策略,对靠近输入的层使用更小的学习率(discriminative fine-tuning);在数据量充足的情况下,微调通常比特征提取取得更好的性能。

3. 逐层解冻(Progressive Unfreezing)

逐层解冻是介于特征提取和微调之间的一种策略。初始阶段,所有预训练层都被冻结,只训练新添加的分类器。随着训练的进行,从最后一层开始逐步解冻预训练网络的层,使其参与训练。这种方法的好处是既能保留预训练模型的低级特征,又能让高级特征适应新的目标任务。

具体实现步骤为:第一轮训练只更新分类头;第二轮解冻最后一个卷积块或Transformer块,与分类头一起训练;依此类推,直到所有层都被解冻或达到满意的性能。每次解冻后需要降低学习率以防止过拟合。

4. 策略选择指南

目标数据量与源域数据相似度推荐策略说明
小(< 1K)特征提取冻结全部卷积层,训练新分类器
小(< 1K)微调顶层冻结大部分层,微调最后几层卷积
中(1K-10K)微调少量层保持大部分预训练权重不变
中(1K-10K)微调较多层让模型学习与目标域更匹配的特征
大(> 10K)任意全模型微调可以用较小学习率微调全部层

核心原则:目标数据量越小,越应该冻结更多预训练层;目标数据与源域数据差异越大,越应该微调更多的层。合理的选择策略可以避免过拟合并最大化迁移学习的效果。

五、PyTorch迁移学习实现

1. 加载预训练模型

PyTorch的torchvision.models模块提供了丰富的预训练视觉模型,通过参数weights='IMAGENET1K_V1'即可加载在ImageNet上预训练的权重:

import torch import torch.nn as nn import torch.optim as optim from torchvision import models # 加载预训练的ResNet-50 model = models.resnet50(weights='IMAGENET1K_V1') print(model) # 查看网络结构

2. 特征提取实现

特征提取模式下,我们需要冻结所有卷积层参数,并替换最后的全连接层:

# 冻结所有参数 for param in model.parameters(): param.requires_grad = False # 替换最后的全连接层(ImageNet 1000类 -> 自定义 N 类) num_classes = 10 # 目标分类数 model.fc = nn.Sequential( nn.Linear(2048, 512), nn.ReLU(inplace=True), nn.Dropout(0.5), nn.Linear(512, num_classes) ) # 只优化新添加的分类层 optimizer = optim.Adam(model.fc.parameters(), lr=1e-3) criterion = nn.CrossEntropyLoss() # 训练循环 for epoch in range(num_epochs): for inputs, labels in dataloader: outputs = model(inputs) loss = criterion(outputs, labels) optimizer.zero_grad() loss.backward() optimizer.step()

3. 微调实现

微调模式允许更新预训练权重,通常使用较小的学习率:

# 加载预训练模型,不冻结参数 model = models.resnet50(weights='IMAGENET1K_V1') # 替换分类头 model.fc = nn.Linear(2048, num_classes) # 为不同层设置不同的学习率 params_to_update = [] for name, param in model.named_parameters(): if param.requires_grad: params_to_update.append(param) # 对新分类头用稍大学习率,预训练层用小学习率 optimizer = optim.SGD([ {'params': model.fc.parameters(), 'lr': 1e-3}, {'params': [p for n, p in model.named_parameters() if p.requires_grad and 'fc' not in n], 'lr': 1e-4} ], momentum=0.9) # 训练循环与特征提取相同,但会更新所有层

4. 逐层解冻实现

逐层解冻需要逐步解冻网络的各层,通常从分类头开始,逐步向输入端推进:

model = models.resnet50(weights='IMAGENET1K_V1') # 第一步:只训练新分类头 for param in model.parameters(): param.requires_grad = False model.fc = nn.Linear(2048, num_classes) # 训练几轮... # 第二步:解冻最后一个残差块(layer4) for param in model.layer4.parameters(): param.requires_grad = True # 降低学习率继续训练 # 第三步:解冻更多层 for param in model.layer3.parameters(): param.requires_grad = True # 进一步降低学习率继续训练

5. NLP迁移学习实现(BERT微调)

使用HuggingFace transformers库可以轻松实现BERT的微调:

from transformers import ( AutoTokenizer, AutoModelForSequenceClassification, Trainer, TrainingArguments ) # 加载中文BERT tokenizer和模型 tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese") model = AutoModelForSequenceClassification.from_pretrained( "bert-base-chinese", num_labels=2 ) # 数据预处理 def tokenize_function(examples): return tokenizer( examples["text"], padding="max_length", truncation=True, max_length=128 ) # 配置训练参数 training_args = TrainingArguments( output_dir="./results", num_train_epochs=3, per_device_train_batch_size=16, per_device_eval_batch_size=64, warmup_steps=500, weight_decay=0.01, logging_dir="./logs", learning_rate=2e-5, ) # 创建Trainer trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset, ) # 开始微调 trainer.train()

实践要点:特征提取适合小数据集且与源域相似的场景;微调适合数据量充足或与源域差异较大的场景;逐层解冻提供了介于两者之间的灵活性。在PyTorch中,通过`requires_grad`属性控制参数是否参与训练,使用不同学习率对微调效果有显著影响。

六、迁移学习的优势

1. 大幅减少训练时间

预训练模型已经在大规模数据集上完成了最消耗计算资源的训练阶段。在迁移到新任务时,通常只需要数小时甚至数十分钟的训练时间,相比从头训练的数天到数周,效率提升极为显著。例如,在ImageNet上训练ResNet-50需要约3-4天(4块V100 GPU),而在自定义数据集上微调相同的模型通常只需1-2小时。

2. 显著降低标注数据需求

迁移学习使得在小样本场景下训练有效模型成为可能。在没有迁移学习的情况下,训练一个视觉分类模型通常需要数万张标注图像才能达到可接受的精度。而使用迁移学习,仅需数百到数千张标注图像就能获得相近甚至更好的性能。在NLP领域,BERT等预训练模型在情感分析等任务上仅需数百条标注样本即可达到较好的效果。

3. 更好的泛化性能

在大规模数据上预训练的模型已经学习到了丰富且通用的特征表示。这些特征通常比从有限目标数据中学到的特征具有更好的泛化能力。预训练模型在目标域上的测试性能往往显著优于从头训练的模型,特别是当目标域数据量不足时。预训练模型学到的知识起到了正则化的作用,有效提升了模型在未见数据上的表现。

4. 有效降低过拟合风险

过拟合是机器学习中数据量不足时最常见的问题。预训练权重提供了一种先验知识(Prior Knowledge),约束了模型的参数空间。即使目标数据集很小,模型也不容易完全偏离合理的特征表示空间。这相当于隐式地在模型中引入了强正则化,使得模型在训练集有限的情况下依然能够保持良好的泛化能力。

5. 加速研究迭代

在学术研究和工业实践中,快速迭代至关重要。迁移学习让研究人员和工程师能够在已有的最佳模型基础上快速构建新任务的原型系统。不必从头训练完整模型,就可以在短时间内验证新想法和新方法的效果,极大地加速了从研究到产品的转化过程。

七、应用案例

1. 图像分类迁移(ImageNet预训练到自定义分类)

这是迁移学习最经典的应用场景。例如,一家农业科技公司需要从无人机拍摄的图像中识别作物病害。由于病害图像数据采集困难,该公司仅有2,000张标注数据。通过使用在ImageNet上预训练的ResNet-50进行特征提取,在2,000张数据上训练新的分类器,最终达到了92%的准确率。相比之下,从头训练同样架构的模型准确率仅为68%,并且需要更多的训练时间。

关键点:选择与ImageNet特征具有一定通用性的预训练模型(ResNet/EfficientNet),根据目标数据量选择合适的迁移策略(小数据用特征提取,中等数据用微调)。

2. 目标检测迁移

目标检测模型(如Faster R-CNN、YOLO、SSD)的骨干网络(Backbone)几乎都使用ImageNet预训练初始化。以Faster R-CNN为例,其骨干网络(如VGG-16或ResNet-50)加载ImageNet预训练权重,而检测头部(RPN和R-CNN部分)随机初始化。在COCO数据集上,使用预训练骨干的检测器相比随机初始化,mAP提高了约15-20个百分点,且收敛速度加快了3-5倍。

应用场景包括自动驾驶中的车辆和行人检测、工业质检中的缺陷检测、安防监控中的异常行为检测等。在这些场景中,大部分检测模型都受益于ImageNet预训练的骨干网络。

3. NLP情感分析迁移(BERT微调)

情感分析是NLP中迁移学习的代表性应用。传统方法需要基于词袋模型或Word2vec构建特征,然后训练分类器。使用BERT微调后,该过程被简化为加载预训练模型并在标注数据上微调。

具体案例:对中文电商评论进行正面/负面情感分类。使用bert-base-chinese模型微调,仅需1,000条标注数据,在测试集上即可达到95%以上的准确率。而使用传统的TF-IDF + SVM方法,在同样的数据上准确率约为85%。BERT的优势在于它能理解上下文语义,而不仅仅是关键词匹配。例如,"这个产品真的不差"这样的句子,传统方法容易因"不"字而误判为负面,而BERT能正确识别其为正面评价。

4. 少样本学习(Few-shot Learning)

少样本学习是迁移学习的极端形式,目标是在每个类别仅有1-5个样本的情况下完成分类任务。少样本学习通常与迁移学习结合使用:首先在大规模数据集上进行预训练,然后在少量目标样本上进行快速适配。

主流方法包括:基于度量的方法(如孪生网络Siamese Network、原型网络Prototypical Networks),通过学习一个度量空间使得同类样本靠近、异类样本远离;基于优化的方法(如MAML,Model-Agnostic Meta-Learning),训练一个模型初始化参数使其能够通过少量梯度更新步骤快速适应新任务;基于参数生成的方法,利用预训练模型的先验直接预测新任务的分类器权重。

在药物发现领域,少样本迁移学习被用于预测新化合物的活性。由于新化合物的实验数据极少(通常不足10个样本),研究人员使用预训练的分子图神经网络作为起点,结合原型网络进行少样本分类,显著提高了新药物候选分子的筛选效率。

总结:迁移学习和预训练模型已经成为现代机器学习的基石技术。无论计算机视觉还是自然语言处理,"预训练 + 微调"的范式已经取代了"从头训练"的传统方法。掌握迁移学习的核心概念和实现技术,是每一个深度学习从业者的必备技能。随着预训练模型规模的不断增长(如GPT系列、ViT等),迁移学习的效能也在持续提升,推动了人工智能在更多领域的实际落地。