2.3 三种迁移策略:特征迁移、模型迁移与实例迁移


2.3 三种迁移策略:特征迁移、模型迁移与实例迁移

本节摘要:从"搬什么"的角度,迁移学习分为三条路线——特征迁移(搬学到的特征表示)、模型迁移(搬参数并继续训练)、实例迁移(搬样本并重新加权)。三者对应三种施工预算与代码形态:特征迁移把旧宅当样板房量尺寸,模型迁移直接住进去翻新,实例迁移把旧家具搬来重新摆位。本节对比三者的机制、适用条件与代价,并各给一段标志性代码。

三条路线的施工隐喻

  • 特征迁移:不买下整栋旧宅,只请测绘队来量它的户型——用源域学到的特征表示去刻画目标域数据,新模型建在这些特征之上
  • 模型迁移:整栋买下、直接入住、局部翻新——参数作为初始值继续训练,预训练加微调就是这条路线
  • 实例迁移:旧宅里的家具搬到新家重新摆位并按适配度取舍——源域样本带着权重进入目标任务的训练集

三条路线不互斥:微调时给源域样本加权、同时借用预训练特征,是工业界的常见组合。

路线一:特征迁移

特征迁移的核心动作:在源域上学一个特征映射,目标模型固定使用这个映射的输出。深度时代最典型的形态就是"冻结骨干、只训新头"的特征提取(第 4 章的施工模式一),但更一般的形态包括:源域学到的词向量、自监督表示、甚至手工特征族的迁移。

标志性代码形态——固定特征提取器:

import torch import torch.nn as nn class FeatureBank(nn.Module): """特征迁移:预训练编码器作为只读的特征供给方""" def __init__(self, encoder, feat_dim, n_classes): super().__init__() self.encoder = encoder for p in self.encoder.parameters(): p.requires_grad = False # 只读:量尺寸,不改房子 self.head = nn.Linear(feat_dim, n_classes) def forward(self, x): with torch.no_grad(): # 特征侧完全无梯度 feat = self.encoder(x) return self.head(feat) # 用随机张量演示一次前向的参数量分配 enc = nn.Sequential(nn.Linear(64, 128), nn.ReLU(), nn.Linear(128, 32)) model = FeatureBank(enc, 32, 5) trainable = sum(p.numel() for p in model.parameters() if p.requires_grad) total = sum(p.numel() for p in model.parameters()) print(f"可训练: {trainable}, 总参数: {total}, 占比 {trainable/total:.1%}") # 输出: 可训练: 165, 总参数: 12685, 占比 1.3%

适合:目标数据极少(几百条以内)、任务与源相近、要求训练快而稳。代价:天花板受限于源特征的表达力——户型不合适时,量得再准也没用。

路线二:模型迁移

参数即初始值,继续训练。这是预训练时代的绝对主流,标志代码就是 load_state_dict 后接目标任务的训练循环:

import torch import torch.nn as nn from torchvision import models # 模型迁移的标志动作:以预训练参数为初值 model = models.resnet18(weights=models.ResNet18_Weights.IMAGENET1K_V1) model.fc = nn.Linear(model.fc.in_features, 2) # 关键细节:新旧层的学习率应当不同(第4.4节展开) head_params = list(model.fc.parameters()) backbone_params = [p for n, p in model.named_parameters() if not n.startswith("fc.")] optimizer = torch.optim.AdamW([ {"params": backbone_params, "lr": 1e-4}, # 旧宅:小步慢行 {"params": head_params, "lr": 1e-3}, # 新头:快步学习 ]) n_bb = sum(p.numel() for p in backbone_params) n_hd = sum(p.numel() for p in head_params) print(f"骨干(低学习率组): {n_bb:,} 个参数") # 输出: 11,689,512 print(f"新头(高学习率组): {n_hd:,} 个参数") # 输出: 1,026 # 一个优化器、两组学习率——模型迁移路线的标准开工姿势

适合:数据中等以上、任务与源有一定差异、追求精度上限。代价:算力与显存开销大、超参敏感(学习率、冻结深度)、小数据易过拟合。

路线三:实例迁移

不搬参数,搬样本。当源域与目标域同任务但分布有偏时,给源域样本按"像目标域的程度"赋权(上一节的重要性加权就是它的引擎),或直接挑选高权重样本混入训练:

import numpy as np rng = np.random.default_rng(11) n_src = 5000 x_src = rng.normal(0, 1, (n_src, 4)) domain_score = rng.normal(0, 1, n_src) # 每个样本与目标域的相似度代理 weights = np.exp(domain_score / 2.0) # 软性权重,平滑放大相似样本 weights /= weights.sum() # 实例迁移的两种用法 # 用法一:加权采样进入训练集(采样占比与权重成正比) idx = rng.choice(n_src, size=1000, p=weights) print(f"加权采样后 domain_score 均值: {domain_score[idx].mean():.3f}") # 输出: 0.695 print(f"原始分布 domain_score 均值: {domain_score.mean():.3f}") # 输出: -0.004 # 采样后相似度均值从约 0 提到 0.7:训练集已被"摆位"到更像目标域的位置 # 用法二:硬筛——只保留权重前 30% 的样本 threshold = np.quantile(weights, 0.7) kept = (weights >= threshold).sum() print(f"硬筛保留样本: {kept} / {n_src}") # 输出: 1500 / 5000

适合:源域数据可获取且允许复用、任务相同或极近、分布偏移可测。代价:源数据合规成本、权重估计误差传导、无法利用源域模型的能力上限。

三路线决策对照

维度 特征迁移 模型迁移 实例迁移
搬运物 特征表示 模型参数 样本及权重
目标侧数据需求 极少即可 中等到大量 中等
训练成本 最低 最高 中等
性能上限 受源特征限制 通常最高 受源数据质量限制
典型场景 小样本原型 预训练-微调主线 同任务跨库合并
工程队行话 量户型 买宅翻新 搬家具摆位

⚠️ 常见坑:在源域数据合规存疑(如医疗、金融数据)时选实例迁移。参数迁移只复用"能力",实例迁移复用"数据本身",两者的法律边界完全不同。

💡 关键直觉:判断路线的最快问题是"你缺的是什么"——缺数据量用实例迁移借样本,缺特征质量用特征迁移借表示,两样都缺一点、且算力允许,就走模型迁移。

本节要点回顾

  • 三分法:特征迁移借表示、模型迁移借参数、实例迁移借样本,搬运物不同决定代码形态不同
  • 特征迁移:编码器只读、新头可训,演示中可训练占比百分之一点三,快而稳但上限受限
  • 模型迁移:参数即初值,标配动作是分组学习率(骨干慢、新头快)
  • 实例迁移:加权采样把源域有效分布拉向目标域,演示中相似度均值从约零提升到零点七
  • 合规提醒:搬样本与搬参数的法律属性不同,数据敏感场景慎用实例迁移

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U