【大模型学习】第十九章 什么是迁移学习
目录
1. 迁移学习的起源背景
1.1 传统机器学习的问题
1.2 迁移学习的提出背景
2. 什么是迁移学习
2.1 迁移学习的定义
2.2 生活实例解释
3. 技术要点与原理
3.1 迁移学习方法分类
3.1.1 基于特征的迁移学习(Feature-based Transfer)
案例说明
代码示例
3.1.2 基于模型的迁移(Model-based Transfer)
案例说明
BERT用于情感分析的例子
3.1.3 基于实例的迁移(Instance-based Transfer)
3.2 迁移学习的核心原理
4. 迁移学习架构
4.1 基本架构
4.2 源域与目标域的定义
4.3 知识迁移过程
1. 迁移学习的起源背景
1.1 传统机器学习的问题
传统机器学习方法(如监督学习)通常假设训练数据(源域)与测试数据(目标域)独立同分布(i.i.d.),且需要满足以下条件:
- 数据充足性:模型需依赖大量标注数据训练才能达到高性能。
- 场景一致性:模型仅在训练数据分布的范围内有效,无法适应新分布的数据。
1.2 迁移学习的提出背景
迁移学习(Transfer Learning)的提出旨在突破传统机器学习的限制,其核心思想是:将已学习的知识(模型、特征、参数等)从源任务(Source Task)迁移到目标任务(Target Task),以降低对目标域数据量和标注质量的依赖。
关键驱动力:
- 数据获取成本:标注数据昂贵(如医学图像需专家标注)。
- 领域差异普遍性:现实场景中数据分布动态变化(如用户兴趣迁移、传感器差异)。
- 模型泛化需求:避免在相似任务上重复训练模型,提升效率。
2. 什么是迁移学习
2.1 迁移学习的定义
迁移学习是一种机器学习范式,通过从源域(Source Domain)中提取知识并应用于目标域(Target Domain),提升目标任务的模型性能,即使源域与目标域的数据分布或任务不同。
2.2 生活实例解释
实例1:学骑自行车 → 学电动车
- 源任务:骑自行车(掌握平衡、转向)。
- 目标任务:骑电动车(动力方式不同,但平衡技能可迁移)。
- 迁移效果:减少学习电动车所需时间。
实例2:跨语言翻译
- 源任务:训练英语-法语翻译模型。
- 目标任务:德语-日语翻译。
- 迁移方式:复用词向量表示或注意力机制等通用语言结构知识.
3. 技术要点与原理
3.1 迁移学习方法分类
3.1.1 基于特征的迁移学习(Feature-based Transfer)
核心思想:基于特征的迁移学习旨在将源域和目标域的数据映射到一个共同的特征空间,使得两个领域的特征分布尽可能相似。这样做的目的是为了消除领域差异,从而可以使用源域中的知识来帮助目标任务的学习。
主要方法:
-
特征选择:这种方法试图识别那些在不同领域中保持不变的特征。例如,在图像处理中,边缘、纹理等低级特征可能在不同的图像集之间具有一定的共性。
-
特征变换:通过特定的变换技术来对齐两个领域之间的特征分布。这包括传统的降维技术如主成分分析(PCA),以及更现代的方法如自动编码器(Autoencoders)或对抗网络(GANs)。深度学习模型,尤其是卷积神经网络(CNNs),常被用于提取高级特征表示。
案例说明
以医学图像分类为例,假设我们有一个预训练的CNN模型,该模型是在ImageNet数据集上训练的。由于ImageNet包含了大量自然场景下的物体图片,其模型能够捕捉到一些通用的视觉特征,比如边缘、颜色、形状等。然而,这些特征对于医学图像来说可能是不够的,因为医学图像通常包含特定的病理特征。
我们可以利用这个预训练模型作为特征提取器,并针对医学图像的任务进行微调。具体步骤如下:
- 加载预训练模型:使用已经训练好的模型,例如ResNet。
- 冻结部分层:防止早期层的权重更新,因为它们捕捉的是通用特征。
- 替换或添加新的全连接层:根据新任务的需求调整输出类别数。
- 微调模型:使用医学图像数据集对模型进行微调。
代码示例
下面是一个简化的PyTorch代码片段,演示如何使用预训练的ResNet模型并对其进行微调:
import torch
from torchvision import models, transforms
from torch import nn, optim
from torch.utils.data import DataLoader
from torchvision.datasets import ImageFolder
# 加载预训练的ResNet-18模型
model = models.resnet18(pretrained=True)
# 冻结所有层参数
for param in model.parameters():
param.requires_grad = False
# 替换最后一层为适应新任务的分类器
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 2) # 假设我们要分类两类医学图像
# 设置设备
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)
# 数据预处理
data_transforms = {
'train': transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
'val': transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
}
# 加载数据集
image_datasets = {x: ImageFolder(f'./data/{x}', data_transforms[x]) for x in ['train', 'val']}
dataloaders = {x: DataLoader(image_datasets[x], batch_size=4, shuffle=True) for x in ['train', 'val']}
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.fc.parameters(), lr=0.001, momentum=0.9)
# 训练循环(这里简化了,实际应用中需要更多的控制逻辑)
for epoch in range(2): # 循环遍历数据集多次
print(f'Epoch {epoch}/{2 - 1}')
print('-' * 10)
for phase in ['train', 'val']:
if phase == 'train':
model.train() # 设置模型为训练模式
else:
model.eval() # 设置模型为评估模式
running_loss = 0.0
running_corrects = 0
for inputs, labels in dataloaders[phase]:
inputs = inputs.to(device)
labels = labels.to(device)
optimizer.zero_grad()
with torch.set_grad_enabled(phase == 'train'):
outputs = model(inputs)
_, preds = torch.max(outputs, 1)
loss = criterion(outputs, labels)
if phase == 'train':
loss.backward()
optimizer.step()
running_loss += loss.item() * inputs.size(0)
running_corrects += torch.sum(preds == labels.data)
epoch_loss = running_loss / len(image_datasets[phase])
epoch_acc = running_corrects.double() / len(image_datasets[phase])
print(f'{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}')
print('Finished Training')
3.1.2 基于模型的迁移(Model-based Transfer)
核心思想:基于模型的迁移学习指的是利用在源任务上训练好的模型参数或结构,并通过适当的调整来适配新的目标任务。这种方法能够显著减少新任务所需的标注数据量,同时加速训练过程。
主要方法:
-
参数共享:通常的做法是冻结预训练模型的部分层(特别是那些捕捉通用特征的低层),然后只对顶层进行微调以适应新的任务需求。例如,在卷积神经网络(CNNs)中,底层往往学习到的是基本的图像特征如边缘和纹理,这些特征在不同任务间具有一定的通用性。
-
多任务学习:联合训练源任务与目标任务,共享隐含表示。在这种设置下,多个相关任务被同时训练,它们之间共享一些隐藏层。这样做的好处是可以让模型从多个任务中学到更丰富的表示,有助于提高每个单独任务的表现。这种策略特别适合那些任务间存在相似性的场景。
案例说明
BERT(Bidirectional Encoder Representations from Transformers)是一个典型的例子,它展示了如何通过预训练获得强大的语言表示能力,并将其迁移到各种下游任务中。BERT首先在一个大规模的文本语料库上进行无监督的预训练,学习到了一种双向的语言表示形式。之后,对于特定的任务如情感分析、命名实体识别等,只需对BERT的顶层进行微调即可快速实现高性能的模型部署。
BERT用于情感分析的例子
假设我们要使用BERT来进行电影评论的情感分析,即判断一条评论是正面还是负面。我们可以遵循以下步骤:
- 加载预训练的BERT模型:可以使用Hugging Face提供的
transformers
库轻松加载预训练的BERT模型。 - 准备数据集:需要一个标记了情感标签的数据集,比如IMDb电影评论数据集。
- 微调BERT模型:将BERT的最后一层替换为一个分类层,根据你的具体任务需求调整输出维度。然后用你的数据集对该模型进行微调。
下面是一段简化的代码示例,演示如何使用BERT进行情感分析:
from transformers import BertTokenizer, BertForSequenceClassification
from torch.utils.data import DataLoader, Dataset
import torch
from sklearn.model_selection import train_test_split
# 假设已经有了标记好的数据集reviews (包含文本) 和 labels (0 或 1 表示负面或正面)
reviews = ["I love this movie", "This film was terrible"]
labels = [1, 0]
# 分割数据集
train_texts, val_texts, train_labels, val_labels = train_test_split(reviews, labels, test_size=0.2)
# 加载预训练的BERT tokenizer 和 model
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=2)
# Tokenize 数据
train_encodings = tokenizer(train_texts, truncation=True, padding=True)
val_encodings = tokenizer(val_texts, truncation=True, padding=True)
class GPReviewDataset(Dataset):
def __init__(self, encodings, labels):
self.encodings = encodings
self.labels = labels
def __getitem__(self, idx):
item = {key: torch.tensor(val[idx]) for key, val in self.encodings.items()}
item['labels'] = torch.tensor(self.labels[idx])
return item
def __len__(self):
return len(self.labels)
train_dataset = GPReviewDataset(train_encodings, train_labels)
val_dataset = GPReviewDataset(val_encodings, val_labels)
# 设置设备
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
model.to(device)
# 训练循环(简化版)
train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)
optim = torch.optim.AdamW(model.parameters(), lr=5e-5)
for epoch in range(3): # 进行三个epoch的训练
model.train()
for batch in train_loader:
optim.zero_grad()
input_ids = batch['input_ids'].to(device)
attention_mask = batch['attention_mask'].to(device)
labels = batch['labels'].to(device)
outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
loss = outputs[0]
loss.backward()
optim.step()
print('Finished Training')
3.1.3 基于实例的迁移(Instance-based Transfer)
核心思想:筛选源域中对目标域有用的样本,调整其权重参与训练。
- 方法:
- 重要性采样:通过权重调整(如TrAdaBoost)重用相关实例。
- 对抗训练:利用领域判别器区分源/目标样本,生成领域不变特征。
- 案例:在商品推荐中,复用用户历史点击数据中的相似行为样本。
3.2 迁移学习的核心原理
核心挑战:领域差异(Domain Shift)导致直接迁移性能下降。
解决思路:
- 领域适配(Domain Adaptation):缩小源域与目标域的数据分布差异(如MMD距离、对抗训练)。
- 知识抽象(Knowledge Distillation):提取源模型的通用知识(如特征表示、决策规则)。
- 渐进式迁移(Progressive Transfer):分阶段迁移,先传递低层特征,再调整高层语义。
4. 迁移学习架构
4.1 基本架构
迁移学习系统包含以下核心组件:
- 源域(Source Domain):包含充足标注数据,用于训练初始模型。
- 目标域(Target Domain):数据量少或未标注,需迁移知识提升性能。
- 迁移模块:实现知识迁移(如特征对齐、参数微调)。
架构:
源域数据 → 特征提取/模型训练 → 知识迁移 → 目标域适配 → 目标任务推理
4.2 源域与目标域的定义
- 源域(DsDs):由数据 XsXs 和标签 YsYs 组成,满足分布 P(Xs,Ys)P(Xs,Ys)。
- 目标域(DtDt):数据 XtXt 可能无标签,分布 P(Xt,Yt)≠P(Xs,Ys)P(Xt,Yt)=P(Xs,Ys)。
常见场景:
- 跨领域迁移:源域为合成图像,目标域为真实图像。
- 跨任务迁移:源任务为图像分类,目标任务为目标检测。
4.3 知识迁移过程
- 知识表示:将源域知识编码为可迁移形式(如模型参数、特征向量)。
- 迁移策略:选择适配方法(如微调、特征映射)。
- 目标域学习:结合迁移知识与目标数据,优化模型。
示例:在ResNet中,迁移ImageNet预训练的卷积核至医学图像分类任务,仅微调全连接层。