想象你是一家大型电气工厂的厂长。厂里的老工人个个手艺精湛,流水线一天能产出上千件标准产品,这条产线是你花十年、砸了几亿资金才建成的。这天,一个大客户下了新订单:要一批“会语音识别的家电”。怎么办?最笨的办法是把整条产线停掉,把每个老工人重新培训成新工种——这就是“全量微调”:成本高、耗时长,还会让老工人把原来的手艺忘得一干二净(灾难性遗忘)。聪明的厂长会在老工人身边加装几个小小的“调节站”——它们不改变原有工序,只在关键位置对半成品做一点点调整,让产品满足新规格。老工人原样干活,新技能全由小调节站学会。这套思路,就是本文的主角:小参数适配器,英文叫 Adapter。

岗位关联

学完本文,你能快速上手 Adapter 这种参数高效微调方法:在消费级 GPU 上低成本微调大模型、用一个底座模型同时服务多个下游任务。这是大模型工程落地与求职面试中最实用的技能之一。

目录
  1. 可视化演示
  2. 适配器核心概念
  3. 瓶颈层架构
  4. 插入位置选择
  5. 维度大小调控
  6. 参数冻结技术
  7. 训练效率优化
  8. 实操落地流程
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示小参数适配器的瓶颈架构原理、参数量对比与多策略雷达评估,涵盖LoRA/Prefix/Adapter方法。

本节配有交互动效(进入视口后自动加载,约 3KB)。

适配器架构原理 冻结基础模型层,仅训练适配器模块 降维投影D + 升维投影U构成瓶颈结构 h = Wx + BAx, B↓ A↑ 适配器通过低秩分解实现参数高效微调

适配器核心概念

回到工厂。全厂重训老工人(微调全部参数)既贵又险,还可能“忘本”。而加装调节站则完全不同:你只需在关键工位旁边放一台小机器,老工人的手艺完全不碰,调节站会根据新订单的规格,在每一件半成品经过时做微调。工厂一天工都不用停,就能开始生产新产品。

在深度学习中,这个“调节站”就是插入到预训练 Transformer 层之间的小型神经网络模块。训练时,把预训练权重(老工人)冻结,只训练新增的 adapter 参数(调节站)。由于 adapter 参数量很少,通常只占全模型的 0.5%~5%,所以被称为“小参数适配器”。

Adapter 的核心思想是“模块化微调”:不改动原模型的行为骨架,只在外围叠加一个轻量模块来承载新任务的知识。原模型保留通用语言能力(老手艺),adapter 负责特定任务的能力(如问答、翻译、代码)。训练结束后,你只需要保存几十 MB 的 adapter 权重,换任务时换一份权重即可。

你看,工厂没有停一天工,也没有重新培训任何老工人,只加了几个调节站就让产线能生产新产品——这正是 Adapter 能成为高效微调主流方案的根本原因。

N适配器N全模型≈0.5%∼5%\displaystyle \frac{N_{\text{适配器}}}{N_{\text{全模型}}} \approx 0.5\% \sim 5\%
这个式子说明:适配器带来的可训练参数量只占整个模型的百分之一左右,这就是“小参数”名称的由来,也是“高效”二字的根基。
  1. 适配器参数量所有插入的 adapter 模块的参数总和,通常只有几十万到几百万个。
    N适配器N_{\text{适配器}}
  2. 全模型参数量预训练模型自身的总参数量,例如 70 亿、1750 亿。
    N全模型N_{\text{全模型}}
  3. 比值范围两者相比,适配器通常占 0.5%~5%,远小于全量微调所需的 100%。
    ≈0.5%∼5%\approx 0.5\% \sim 5\%

瓶颈层架构

调节站内部长什么样?想象一座机场安检通道:宽敞的候检大厅,进入一条很窄的检查走廊,再进入另一个宽敞大厅。窄走廊强制所有行李“浓缩”着逐一通过,只有最关键的信息被保留下来。这个“宽—窄—宽”的结构,就是瓶颈(Bottleneck)。

Adapter 的内部结构正是如此。它先通过一个降维矩阵把 d 维特征压到很小的 r 维(r \ll d),经过一个非线性激活函数,再用一个升维矩阵恢复成 d 维。中间的 r 就是“瓶颈维度”,整个模块叫“瓶颈适配器”(Bottleneck Adapter)。

整个模块通常以残差方式接入:输入 h 直接跳连到输出端,适配器只贡献一个“增量”。这样即使适配器初始化为零附近,也不会破坏原模型的行为。降维、升维两个矩阵,加上中间的激活函数,构成一个参数极少的“瓶颈变换”。

就像安检通道虽然窄,但正因为窄,才强迫系统只萃取最关键的信息。瓶颈设计的巧妙之处在于:用极少的参数换来了对新任务足够强的表达能力。

hout=hin+f ⁣(hinWdown)Wup\displaystyle \mathbf{h}_{\text{out}} = \mathbf{h}_{\text{in}} + f\!\left(\mathbf{h}_{\text{in}} \mathbf{W}_{\text{down}}\right)\mathbf{W}_{\text{up}}
这是适配器的完整数据流:输入先被压缩进窄瓶颈,经过非线性变换,再展开回原来的宽度,同时保留一条直通的“近路”(残差)。
  1. 输入特征当前 Transformer 子层的输出,维度为 d。
    hin\mathbf{h}_{\text{in}}
  2. 降维投影将 d 维特征压缩到 r 维,r 通常只有 d 的百分之几。
    Wdown∈Rd×r\mathbf{W}_{\text{down}} \in \mathbb{R}^{d \times r}
  3. 非线性激活如 ReLU / GELU,给两层线性变换之间加入非线性,否则两层可合并成一层。
    f(⋅)f(\cdot)
  4. 升维投影将 r 维特征恢复为 d 维。
    Wup∈Rr×d\mathbf{W}_{\text{up}} \in \mathbb{R}^{r \times d}
  5. 残差融合将变换结果与原始输入相加,保证梯度顺畅、行为稳定。
    hout=hin+Δ\mathbf{h}_{\text{out}} = \mathbf{h}_{\text{in}} + \Delta

插入位置选择

调节站不是随便放的。放得太早,半成品还没成型,调了也白调;放得太晚,产品已经打包,来不及了。有经验的工程师会在每个质检点后面放一个:刚加工完、即将进入下一道工序之前,是最佳干预时机。

对应到 Transformer,最常用的位置是在每个 Transformer Block 内部、子层(多头注意力 / 前馈网络)的输出之后。经典做法(Houlsby 等)是在每个 Block 的注意力层和 FFN 层后各插一个适配器;实践中也有只在 FFN 后插一个的做法,参数更省。

无论插在哪里,都要配合残差连接使用。插入后的数据流可以写成:子层输出 z,经过适配器得到增量 A(z),再加回 z。这样适配器无论如何初始化,原模型的计算路径都不被破坏,训练时梯度也可以顺着残差近路顺利回传,这也是插入位置设计的核心约束。

就像质检点后面放调节站一样,插在子层输出之后,让适配器对“刚加工完的半成品”做最有效的微调,这就是插入位置的学问。

z=SubLayer(h),hout=z+A(z)\displaystyle \mathbf{z} = \mathrm{SubLayer}(\mathbf{h}), \qquad \mathbf{h}_{\text{out}} = \mathbf{z} + \mathcal{A}(\mathbf{z})
含义:先把输入交给原模型子层加工,得到半成品 z;再由适配器 A 对 z 做增量修正,最后把增量加回 z 本身。
  1. 子层输出多头注意力或前馈网络对输入 h 的加工结果。
    z=SubLayer(h)\mathbf{z} = \mathrm{SubLayer}(\mathbf{h})
  2. 适配器增量适配器对半成品 z 做瓶颈变换。
    A(z)\mathcal{A}(\mathbf{z})
  3. 残差加回增量与 z 相加,形成本层的最终输出。
    hout=z+A(z)\mathbf{h}_{\text{out}} = \mathbf{z} + \mathcal{A}(\mathbf{z})

维度大小调控

瓶颈走廊该修多宽?太窄,行李挤不过去,安检效率低(适配能力不足);太宽,建设成本高,人力和空间都浪费(参数太多)。好的工程师会先按经验定一个宽度,再根据实际的“客流量”(任务难度与数据量)调宽或调窄。

对应到 adapter,这个宽度就是瓶颈维度 r。r 决定了两件事:表达容量(越大表达力越强)和参数量(与 r 近似成正比)。常见起点是 r = 16 或 32,任务复杂或数据充足时可以调到 64、128。

假设模型共 L 层、每层特征维度 d、瓶颈维度 r,每个 adapter 的参数量约为 2dr(down 矩阵 d×r,up 矩阵 r×d),全部 L 层加起来约 2Ldr。可以看到:r 翻倍,参数翻倍,训练与存储成本同步上升;r 过小则容易“欠拟合”,学不动新任务。

修多宽的走廊没有唯一答案,但它直接决定了成本与体量的平衡。实践中从 16 起步、按任务效果调宽或调窄,是最稳妥的做法。

Nadapter=L×(2dr+d+r)≈2Ldr\displaystyle N_{\text{adapter}} = L \times (2 d r + d + r) \approx 2 L d r
这是适配器参数总量的估算公式,清晰展示了 r 与参数量的线性关系,也是选择维度时的主要成本依据。
  1. 层数插入适配器的 Transformer 层数 L。
    LL
  2. 单个适配器矩阵降维 d×r 与升维 r×d 两个矩阵的参数量。
    2dr2 d r
  3. 偏置项若线性层带偏置,每层额外增加 d + r 个参数。
    d+rd + r
  4. 总参数量L 层累加,通常可近似为 2Ldr。
    ≈2Ldr\approx 2 L d r

参数冻结技术

装好调节站后,你要叮嘱老工人:“你们按原样干活,千万别改自己的习惯。”只有调节站的师傅去学新订单的规格。为什么?因为老工人的手艺是十年沉淀下来的通用能力,改坏了损失太大,而且学到的新技能可能只适用这一个订单。

在代码层面,这条“叮嘱”就是冻结(freeze):把原模型所有参数的 requires_grad 设为 False。这样反向传播时,梯度不会流向原模型参数,优化器也不会更新它们。只有 adapter 的参数(部分实现中还会额外放开 LayerNorm 参数)参与更新。

从梯度公式看,冻结等价于强制原参数梯度为零,原参数永远保持预训练时的值;而 adapter 参数则照常按优化器规则更新。这样做还有额外的“省钱”效果:Adam 优化器只需为 adapter 的参数量分配动量状态,显存占用大幅降低。如果需要更强效果,还可以做“渐进解冻”:先训练 adapter,再放开最后几层微调,作为折中方案。

冻结不是“偷懒”,而是对通用知识的保护:老工人不动,调节站专学新技艺,二者各司其职,这是 Adapter 能兼顾效果与效率的基石。

∂L∂θbase=0,θbase 不变,θadapter←θadapter−η∂L∂θadapter\displaystyle \frac{\partial \mathcal{L}}{\partial \theta_{\text{base}}} = 0, \quad \theta_{\text{base}} \text{ 不变}, \qquad \theta_{\text{adapter}} \leftarrow \theta_{\text{adapter}} - \eta \frac{\partial \mathcal{L}}{\partial \theta_{\text{adapter}}}
左边表示原模型权重梯度为零、不参与更新;右边表示适配器权重照常按梯度下降学习新任务。这是“冻结 + 适配”的数学表达。
  1. 原参数梯度置零冻结使基座参数在反向传播中的梯度恒为零。
    ∂L∂θbase=0\frac{\partial \mathcal{L}}{\partial \theta_{\text{base}}} = 0
  2. 原参数不变权重始终保持预训练时的数值。
    θbase 不变\theta_{\text{base}} \ \text{不变}
  3. 适配器正常更新按梯度下降更新 adapter 参数,学习率为 η。
    θadapter←θadapter−η∂L∂θadapter\theta_{\text{adapter}} \leftarrow \theta_{\text{adapter}} - \eta \frac{\partial \mathcal{L}}{\partial \theta_{\text{adapter}}}

训练效率优化

现在算一笔账:全厂重训的方案,要给几万名老工人重新发培训教材、租更大的培训教室(显存),培训期长达数月;加装调节站的方案,只培训几个新来的老师傅,一周就能上岗。成本差距是数量级的。

技术账也很清晰。全量微调一个 1750 亿参数的模型,优化器(如 Adam)要对每个可训练参数保存两份动量状态,仅优化器显存就高达 8 × 1750 亿 ≈ 1400 GB;而 adapter 只有几千万参数,优化器显存降到数百 MB 量级。这直接决定了一块消费级显卡能不能跑得起微调。

具体来说:Adam 优化器对每个可训练参数约需 8 字节(两份动量各 4 字节)维护状态。全量微调时,这个开销乘以全模型参数量;而 Adapter 只乘以 adapter 参数量。此外,因为需要更新的参数少,单步计算量更小、收敛更平稳,训练耗时通常也明显缩短。需要留意的是:推理阶段 adapter 会额外增加两步矩阵乘法,延迟会略增,但通常可以接受。

培训教室从“全厂大会堂”缩成“一间小教室”,这就是 Adapter 带来的效率革命。省下的显存和预算,让你能用更小的机器完成大模型的定制。

M优化器≈8×Ntrainable 字节,M全量≫MAdapter\displaystyle M_{\text{优化器}} \approx 8 \times N_{\text{trainable}} \ \text{字节}, \qquad M_{\text{全量}} \gg M_{\text{Adapter}}
优化器显存与可训练参数量成正比,这是 Adapter 能大幅降低显存门槛的关键公式。
  1. Adam 的每参数开销两份动量状态各 4 字节,共约 8 字节。
    8×Ntrainable8 \times N_{\text{trainable}}
  2. 可训练参数全量微调时等于全模型参数,Adapter 时仅等于小模块参数。
    NtrainableN_{\text{trainable}}
  3. 显存对比全量微调的优化器显存远大于 Adapter 方案。
    M全量≫MAdapterM_{\text{全量}} \gg M_{\text{Adapter}}

实操落地流程

工程师上门装调节站的流程,一般是:先看产线图纸(读模型结构),再定制调节站型号(配置 adapter 参数),然后试运行(训练),最后拿样品和旧产品对比验收(评估)。每一步都有标准动作。

实操中,你可以直接用 HuggingFace 生态的 adapter-transformers 库,也可以像本文后面的 Python 演示一样用 PyTorch 自写。标准动作是:加载预训练模型 → 插入 adapter → 冻结原模型 → 仅训练 adapter → 保存 adapter 权重(通常只有十几到几十 MB)→ 换任务时加载对应权重。

评估环节最重要的指标是“效果差距”:用同一份验证集分别评估 adapter 微调后的模型与全量微调的模型,计算准确率(或其他指标)之差 Δ。如果 |Δ| 在 1% 以内,说明 adapter 以极少的训练成本达到了几乎等同全量微调的效果,这就是一次成功的落地。

从看图纸到验收,照着这条流程走就能复现“调节站”方案。关键是把成本降下来、把效果稳得住——这也是 Adapter 成为工程界心头好的原因。

Δ=AccAdapter−Acc全量,∣Δ∣≲1% 即视为高效达标\displaystyle \Delta = \mathrm{Acc}_{\text{Adapter}} - \mathrm{Acc}_{\text{全量}}, \qquad |\Delta| \lesssim 1\% \ \text{即视为高效达标}
用任务指标衡量 Adapter 与全量微调的差距,能直观回答“到底高不高效”这个问题。
  1. Adapter 指标Adapter 微调后的模型在验证集上的准确率。
    AccAdapter\mathrm{Acc}_{\text{Adapter}}
  2. 全量指标全量微调模型在同一验证集上的准确率。
    Acc全量\mathrm{Acc}_{\text{全量}}
  3. 差距判定差距小于约 1% 认为 Adapter 达到实用水平。
    ∣Δ∣≲1%|\Delta| \lesssim 1\%

AI 应用场景

场景 1:一个底座模型,多任务并行服务

阶段:模型部署 / 推理服务

解决的问题:传统多任务方案要为每个任务各保存一份全量微调模型,几百 GB 甚至上 TB 的存储让中小团队望而却步。用 Adapter 后,底座模型只存一份,每个任务只多一个几十 MB 的 adapter 权重,切换任务就像换一个“调节站”,无需重启服务。

具体案例:某 SaaS 公司用同一个 7B 底座模型服务客服问答、法律咨询、代码生成三条产品线。全量微调方案需三份全量权重,常驻显存超过 40 GB;改用 Adapter 后底座常驻 14 GB,三个 adapter 按请求动态加载,存储与显存成本下降约 60%。

场景 2:低资源硬件上的领域微调

阶段:模型训练 / 监督微调

解决的问题:消费级显卡(如 24 GB 显存)无法承载全量微调大模型的优化器开销,动不动就 OOM。Adapter 冻结主模型后,优化器只为小模块开“账户”,训练显存与算力需求大幅下降,让单卡微调大模型成为可能。

具体案例:一位算法工程师在单张 RTX 4090 上微调 13B 模型,用于企业内部文档问答。全量微调直接显存溢出;用 Adapter(bottleneck = 32,冻结全部原参数)后,训练显存降至约 18 GB,2 小时完成训练,效果接近云端全量微调。

场景 3:持续学习与领域适应

阶段:模型更新 / 增量学习

解决的问题:全量微调在引入新领域数据时容易灾难性遗忘旧知识。Adapter 把不同领域的知识隔离在各目的“调节站”里,底座通用能力始终冻结保留,互不干扰,非常适合持续学习。

具体案例:某医疗 AI 团队需要在通用模型上依次适配病历摘要、影像报告生成、用药问答三个子任务。他们为每个子任务训练独立 adapter,切换任务只加载对应权重,避免了顺序微调带来的遗忘问题,还省下了三份全量模型的存储。

Python 演示

python61 行
import torchimport torch.nn as nn class BottleneckAdapter(nn.Module):    def __init__(self, d_model, bottleneck_dim):        super().__init__()        self.down = nn.Linear(d_model, bottleneck_dim, bias=False)        self.up = nn.Linear(bottleneck_dim, d_model, bias=False)        self.act = nn.ReLU()     def forward(self, x):        return self.up(self.act(self.down(x))) class BaseBlock(nn.Module):    def __init__(self, d_model):        super().__init__()        self.linear = nn.Linear(d_model, d_model)     def forward(self, x):        return self.linear(x) class ModelWithAdapter(nn.Module):    def __init__(self, d_model=16, bottleneck_dim=4, num_blocks=3):        super().__init__()        self.blocks = nn.ModuleList([BaseBlock(d_model) for _ in range(num_blocks)])        self.adapters = nn.ModuleList(            [BottleneckAdapter(d_model, bottleneck_dim) for _ in range(num_blocks)]        )     def forward(self, x):        for block, adapter in zip(self.blocks, self.adapters):            h = block(x)            x = x + adapter(h)        return x def freeze_base(model):    for p in model.blocks.parameters():        p.requires_grad = False    trainable = sum(p.numel() for p in model.adapters.parameters())    total = sum(p.numel() for p in model.parameters())    print(f"[冻结] 原模型参数 {total - trainable} 个冻结, 适配器 {trainable} 个可训练") def main():    torch.manual_seed(0)    model = ModelWithAdapter()    freeze_base(model)    X = torch.rand(512, 16) * 2 - 1    y = torch.sin(X) + 0.1 * X    opt = torch.optim.Adam(model.adapters.parameters(), lr=1e-2)    loss_fn = nn.MSELoss()    for epoch in range(50):        opt.zero_grad()        pred = model(X)        loss = loss_fn(pred, y)        loss.backward()        opt.step()        if (epoch + 1) % 10 == 0:            print(f"epoch {epoch + 1}: loss {loss.item():.4f}") if __name__ == "__main__":    main()
目的:用 PyTorch 从零实现“瓶颈适配器 + 冻结基座”的完整微调流程,演示 Adapter 的核心机制。运行后会看到只有适配器参数参与训练,损失逐步下降。
  1. self.down = nn.Linear(d_model, bottleneck_dim, bias=False)降维投影:把 d 维特征压进 r 维瓶颈,对应“窄走廊”。
  2. self.up = nn.Linear(bottleneck_dim, d_model, bias=False)升维投影:从瓶颈恢复出 d 维输出,对应“宽大厅”。
  3. x = x + adapter(h)残差融合:原特征不动,适配器只加一个增量,保护原模型行为。
  4. for p in model.blocks.parameters(): p.requires_grad = False冻结原模型权重,让梯度只流向“调节站”。
  5. opt = torch.optim.Adam(model.adapters.parameters(), lr=1e-2)优化器只管理适配器参数,显存与算力开销自然变小。

常见误区

误区“Adapter 跟普通的线性层差不多,想在哪个位置加就在哪个位置加,反正都是可学习参数嘛。”

正解Adapter 是“降维—激活—升维”的瓶颈结构,还必须配合残差连接使用。插入位置(子层输出之后)、非线性激活、残差近路都是整体设计的组成部分,缺一个都可能让训练不稳定或效果显著下降。就像调节站必须放在质检点之后才有意义。

为何常见:从直觉看,神经网络里加层似乎都是“多加参数”;但 adapter 的每个设计细节都围绕“参数少 + 不破坏原模型”两个目标,位置与结构是经过精心考量的。

误区“既然适配器参数本来就不多,那把瓶颈维度调大一点,容量更大,效果肯定更好。”

正解维度 r 越大,参数量线性上升(约 2Ldr),训练与存储成本同步增大;在小数据上,过大的 adapter 更容易过拟合。常用做法是从 16/32 起步,在验证集上比较,选择“效果够用”的最小维度,而不是一味加大。

为何常见:人们习惯认为“模型越大越好”,却忽视了 adapter 的定位是轻量增量,它与数据量、预算之间存在权衡。

误区“把那么大一个模型冻住,只有小 adapter 在学习,效果肯定不如全量微调吧。”

正解大量实验表明,在中等规模数据下 adapter 能达到接近甚至持平全量微调的效果。因为预训练模型已经具备很强的通用表示,新任务往往只需要在表示之上做轻量“调整”,这恰好是 adapter 擅长的。冻结恰恰保护了通用能力不被破坏。

为何常见:直觉把“更新的参数量”等同于“学习能力”,忽略了预训练权重的知识迁移价值——老工人的手艺本身就是最大的财富。

误区“Adapter 可训练参数这么少,训练快、推理也快,肯定无脑比全量微调快。”

正解训练阶段确实更快更省显存,但推理阶段 adapter 会在每一层多两次矩阵乘法,延迟往往略有增加。参数量少不等于计算量少——推理延迟由前向计算路径决定,而不是由可训练参数量决定。部署时要做延迟实测,必要时做算子融合优化。

为何常见:把“参数量”与“计算量”混为一谈,忽略了推理时前向计算要经过所有权重(包括冻结的基座)这一事实。

面试题

Q1. Adapter 参数高效微调的核心思想是什么?

单选题 · easy

  • A.冻结原模型权重,只训练新插入的小模块← 正确答案
  • B.用更大学习率重新训练全部原始权重
  • C.只修改输入词表并随机初始化嵌入层
  • D.复制多份模型分别训练后做模型融合

答案:A。Adapter 的思路是“老工人不动,只培训调节站”:冻结预训练权重,只训练新插入的小模块。B 是全量微调的思路,C 是词表技巧,D 是集成学习思路,三者都不符合参数高效微调的定义。

Q2. 在瓶颈适配器中,“瓶颈”指的是什么?

单选题 · easy

  • A.中间层维度远小于输入输出维度← 正确答案
  • B.输入输出维度小于中间层维度
  • C.所有中间层维度都保持完全一致
  • D.适配器一次只能处理一个数据样本

答案:A。“瓶颈”就像安检通道的窄走廊:中间层维度 r 远小于输入输出维度 d,信息被压缩后通过,这是 Adapter 参数少的根本原因。B 说反了,C 描述的是普通线性层,D 与维度无关。

Q3. 训练 Adapter 时,优化器应当更新哪些参数?

单选题 · easy

  • A.只更新适配器模块中新加入的参数← 正确答案
  • B.更新全部参数包括预训练模型的权重
  • C.只更新预训练权重不更新适配器权重
  • D.随机挑选部分原始模型的权重更新

答案:A。训练时把原模型参数 requires_grad 设为 False,优化器只管理适配器参数,这正是 Adapter 高效省显存的关键。B 是全量微调,C 和 D 逻辑上都不成立——只更新原模型或随机更新都会破坏预训练知识。

Q4. Adapter 通常插入在 Transformer 层的什么位置?

单选题 · mid

  • A.多头注意力和前馈网络子层输出之后← 正确答案
  • B.输入词嵌入与位置编码的插入之前
  • C.输出层之后与损失函数计算的地方
  • D.训练数据进入模型之前的预处理

答案:A。Adapter 相当于放在“质检点后面”的调节站,即每个子层加工完成之后。B 属于输入端,C 属于损失端,D 属于数据处理端,都不是调整模型内部表征的合适位置。

Q5. 相比全量微调,Adapter 最直接的优势是什么?

单选题 · mid

  • A.可训练参数量大幅减少只需存小权重← 正确答案
  • B.模型推理速度显著提升计算量变小
  • C.完全不需要任何训练数据就能完成任务
  • D.预训练模型可以在没有 GPU 的环境运行

答案:A。Adapter 把可训练参数从千亿级降到百万级,只需保存几十 MB 权重。B 是常见误区——推理阶段反而多两次矩阵乘;C、D 与 Adapter 机制无关。

Q6. 关于瓶颈维度 r 的选择,下列说法正确的是?

单选题 · mid

  • A.r 越大适配能力越强但参数量线性增加← 正确答案
  • B.r 越大参数量越少适合低资源设备部署
  • C.r 越小适配能力越强但训练速度越慢
  • D.r 与输入维度无关可以任意设置数值

答案:A。参数量约等于 2Ldr,r 每翻倍参数就翻倍。r 增大容量上升、成本上升,r 过小又容易欠拟合,因此要从 16/32 起步按效果调整。B、C 说反了,D 忽略了 r 必须远小于 d 的前提。

Q7. 为什么 Adapter 瓶颈中需要非线性激活函数?

单选题 · hard

  • A.否则两层线性可以合并成等效单层变换← 正确答案
  • B.激活函数可以降低模型收敛时的显存
  • C.非线性能让参数量自动减少到一半
  • D.激活函数能把特征维度强制压缩变小

答案:A。没有非线性时,下采样矩阵与上采样矩阵相乘会合并成一个等效的线性变换,瓶颈结构就名存实亡了。激活函数是“窄走廊”里强制筛选信息的关卡,其余选项描述均不准确。

Q8. 关于参数冻结与训练策略,以下说法正确的有?

多选题 · mid

  • A.通常冻结预训练主体只训练适配器参数← 正确答案
  • B.部分实践会额外解冻 LayerNorm 参数← 正确答案
  • C.冻结所有参数包括适配器就能直接预测
  • D.冻结参数不参与前向计算所以不影响推理

答案:AB。A 是标准做法,B 是常见增强技巧(解冻 LN 能略微提升效果)。C 错误——适配器不训练就无法学习新任务;D 错误——冻结参数只是梯度不更新,前向计算仍然全程参与,是推理延迟的主要来源。

Q9. 关于 Adapter 推理阶段的影响,说法正确的有?

多选题 · hard

  • A.相比原模型多执行两次矩阵乘法运算← 正确答案
  • B.推理延迟通常比原模型略有增加← 正确答案
  • C.因为参数少推理速度必然大幅加快
  • D.适配器权重可以在不同任务间直接通用

答案:AB。Adapter 在每个插入位置多出降维、升维两步矩阵乘,延迟通常小幅上升,所以 A、B 正确。参数量与推理速度没有必然关系,C 是误区;每个任务的 adapter 需要单独训练,不能直接通用,D 错误。

Q10. Adapter 适合哪些真实的应用场景?

多选题 · mid

  • A.用一个基础模型服务多个下游任务← 正确答案
  • B.在消费级显卡上微调大语言模型← 正确答案
  • C.将训练好的适配器随模型一起分发← 正确答案
  • D.完全替代预训练模型的继续预训练

答案:ABC。多任务共享底座(A)、低显存微调(B)、小权重分发(C)都是 Adapter 的典型应用。D 错误——继续预训练需要更新底座自身的世界知识,Adapter 只是在底座之上做任务适配,无法替代大规模继续预训练。