IA³ 与其他低成本方法:VeRA / LoHa / LoKr / OFT / BOFT
LoRA 的参数已经够少了(约 0.5% base),但部分场景还想更小——多任务时每个任务挂一个、移动端推理减体积、 多 adapter 共存省 GPU 内存。本章讲一组比 LoRA 更"省"的方法。
8.1IA³(最便宜的开关)
IA³(Infused Adapter by Inhibiting and Amplifying Inner Activations)只学三个向量缩放 attention 的 K / V / FFN:
$$h_K = K \odot l_K,\;\; h_V = V \odot l_V,\;\; h_{FFN} = \text{FFN}(x) \odot l_{FFN}$$
每个 $l$ 是 dim-sized vector,参数量极小:
| 方法 | 典型 trainable%(7B 模型) | 论文同名 |
|---|---|---|
| LoRA r=8 | ~0.10% | LoRA |
| LoRA r=16 | ~0.20% | LoRA |
| IA³ | ~0.02% | (IA)³ |
| VeRA | ~0.03% | VeRA |
启用 IA³
from peft import IA3Config, get_peft_model, TaskType
cfg = IA3Config(
task_type=TaskType.CAUSAL_LM,
target_modules=["k_proj", "v_proj", "down_proj"],
feedforward_modules=["down_proj"], # ★ 哪些是 FFN(用乘法门控)
)
model = get_peft_model(model, cfg)
实现:src/peft/tuners/ia3/layer.py::IA3Layer。forward 简化版:
def forward(self, x):
if self.is_feedforward:
# FFN:先经过 base,再乘 l
result = self.base_layer(x) * self.ia3_l.unsqueeze(0)
else:
# K / V:先乘 l,再走 base(这样能合并进 base weight)
x = x * self.ia3_l.unsqueeze(0)
result = self.base_layer(x)
return result
IA³ 适用场景
- 多任务 / 多语言:每个语言挂一个 IA³ adapter(5 MB/个);
- 风格调整:客户专属语气、品牌口吻;
- 移动端:100+ adapter 共存可行。
不适合:领域知识增强(容量太小学不到新信息)、数学/代码(需要参数空间大)。
8.2VeRA:共享 A、B,只学缩放 vector
VeRA(Vector-based Random Adaptation)的洞察:LoRA 的 $A, B$ 矩阵其实没必要每层都不同,跨层共享一对随机冻结的 A, B,只学两个小 vector:
$$\Delta W = \Lambda_b\, B\,\Lambda_d\, A,\quad \Lambda_b, \Lambda_d \;\text{是 diag vector}$$
所有 layer 共享同一个 $A, B$(随机初始化后冻结),每层只有 $2d$ 个可训参数。
from peft import VeraConfig
cfg = VeraConfig(
r=256, # ★ 比 LoRA 大得多(共享所以可以)
target_modules=["q_proj", "v_proj"],
vera_dropout=0.0,
d_initial=0.1, # Λ_d 初始化值
)
model = get_peft_model(model, cfg)
实现:src/peft/tuners/vera/。注意 VeRA 因为共享 A, B,save_pretrained 默认不保存 A, B(推理时按种子重生成);如果需要可设 save_projection=True。
8.3LoHa / LoKr:换分解形式
两者都是把 LoRA 的"加性低秩"换成更紧凑的形式:
| 方法 | $\Delta W$ 形式 | 参数量 |
|---|---|---|
| LoRA | $BA$(rank-r 矩阵) | $2dr$ |
| LoHa | $(B_1 A_1) \odot (B_2 A_2)$(Hadamard 乘) | $4dr$,但等效秩 $r^2$ |
| LoKr | $B \otimes A$(Kronecker 积) | $d_1 r + d_2 r$,等效维度 $d_1 d_2$ |
LoHa 适合需要捕捉非线性交互的任务(如图像生成);LoKr 适合权重矩阵能自然拆分为两个维度(如 attention 的 multi-head × head_dim)。SD/SDXL 微调(Stable Diffusion)的 lycoris 库就是 LoHa/LoKr 思路。
8.4OFT / BOFT / HRA:正交家族
这一系列方法的思路完全不同:不加 $\Delta W$,而是用正交矩阵 $R$ 旋转 base weight:
$$W' = R W_0,\;\; R^\top R = I$$
正交保证训练前等价于 base、且不破坏 base 的"几何结构"。三种实现:
| 方法 | $R$ 怎么参数化 | 参数量 |
|---|---|---|
| OFT | 块对角正交矩阵 | $d \cdot b / 2$(b 是块大小) |
| BOFT | 蝶形分解:$R = R_1 R_2 \cdots R_K$ | $d \log_2 d$ |
| HRA | Householder 反射:$R = I - 2 v v^\top$(链式) | $kd$(k = 反射数) |
正交家族在视觉生成模型(Stable Diffusion)上效果好,原因是正交不破坏 base 学到的几何先验。NLP 上不如 LoRA。
8.5各方法实测对照(GLUE 基线)
| 方法 | trainable% | GLUE | 典型适用 |
|---|---|---|---|
| 全参 FT | 100% | 87.5 | 有钱有显存 |
| LoRA | 0.3% | 86.4 | 通用 |
| DoRA | 0.3% | 87.0 | +1pp,慢 30% |
| AdaLoRA | 0.3% | 87.1 | +1pp,慢 30% |
| IA³ | 0.02% | 83.5 | 多 adapter / 风格调 |
| VeRA | 0.03% | 84.1 | 共享 A,B 的 LoRA |
| OFT | 0.5% | 85.8 | 视觉生成 |
NLP 的甜点是 LoRA / DoRA / AdaLoRA,IA³ / VeRA 是"我极度计较参数量"时的特例。
8.6给方法做"二选一"的简化决策
| 你的需求 | 选 |
|---|---|
| 第一次跑 / 不确定 | LoRA r=16, alpha=32 |
| 显存紧 | QLoRA (LoRA + bnb 4bit) |
| 想再多 1-2 pp | + DoRA 或 AdaLoRA |
| 多 adapter 共存(>= 10 个) | IA³ 或 VeRA |
| SD/SDXL 微调 | LoHa / LoKr / OFT |
| 论文实验对比 / 探索 | 剩下的(VeRA / FourierFT / HRA…) |
8.7能不能多种方法一起上
同一个 base 上同时挂多种 tuner(如 LoRA + IA³)需要用 MixedModel。看 src/peft/mixed_model.py:
from peft import PeftMixedModel, LoraConfig, IA3Config
model = PeftMixedModel(base_model, lora_cfg, adapter_name="lora_a")
model.add_adapter("ia3_a", ia3_cfg)
model.set_adapter(["lora_a", "ia3_a"]) # 两个一起激活
注意 MixedModel 不支持 save_pretrained 的统一接口,需要每个 adapter 分别保存。
8.8近期 LoRA cousins 全表(2024–2026 新增)
本章前面提到 IA³ / VeRA / LoHa / LoKr / OFT。2024 以后还有大量新方法被并入 PEFT,全表覆盖这本书可能用得到的:
| 方法 | 位置 | 核心数学 | 关键字段 | typical 用 |
|---|---|---|---|---|
BOFT | tuners/boft/ | Butterfly 正交分解 | boft_block_size / boft_block_num | diffusion ControlNet |
HRA | tuners/hra/ | Householder 反射组合 | r(偶数)/ apply_GS | OFT 的稳定版 |
HIRA | tuners/hira/ | Hadamard 高秩适配 | r | 需要 expressive 但参数预算紧 |
FourierFT | tuners/fourierft/ | DFT 频谱学习 | n_frequency / scaling | 极小参数(< LoRA 10×) |
WaveFT | tuners/waveft/ | 小波域 | — | FourierFT 升级 |
ShiRA | tuners/shira/ | Sparse High-Rank Adaptation | r / mask_type / mask_fn | 稀疏高秩 |
RandLora | tuners/randlora/ | 共享稀疏随机基 + 对角缩放 | r / sparse / very_sparse / randlora_alpha | VeRA 的稀疏版 |
DeLoRA | tuners/delora/ | decorrelated LoRA | r | 解耦 A B 相关性 |
GraLoRA | tuners/gralora/ | Gradient-Regularized LoRA | — | 梯度正则 |
C3A | tuners/c3a/ | Channel-wise Circular Convolution | block_size | 分块循环卷积 |
Bone | tuners/bone/ | Block Affine | — | block-diag 仿射变换 |
Poly | tuners/poly/ | 多技能路由(Polytropon) | r / n_tasks / n_skills / n_splits | 多任务共享 + per-task router |
Trainable Tokens | tuners/trainable_tokens/ | 选择性 embedding 训练 | token_indices | 扩词表只训新 token |
Cartridge | tuners/cartridge/ | 模块化 adapter 系统 | — | 多 adapter 路由(实验) |
8.9三类"极小参数"方法对比(VeRA / FourierFT / IA³)
这三类是"参数比 LoRA 还少 5-10×" 的代表,但路线完全不同:
| 方法 | 共享什么 | 每层学什么 | 典型参数比例 |
|---|---|---|---|
VeRA | 全局随机 A、B 矩阵(fixed) | per-layer 对角缩放 λ_b, λ_d | ~0.05% 全模型 |
FourierFT | — | n_frequency 个频谱系数 | LoRA 的 1/10–1/16 |
IA³ | — | k_proj / v_proj / ffn 各一个缩放向量 | ~0.02% |
"什么时候选哪个?"
- 多 adapter / 风格切换 → IA³(参数太少效果有限但 cheap);
- 需要 high expressivity 但参数预算紧 → VeRA(shared random basis 比 IA³ 表达力强);
- 追求论文级最小参数 → FourierFT(频域稀疏,几千参数)。
8.10PromptTuningInit / MultitaskPromptTuningInit 枚举
Prompt 系算法在 ch09 详细讲。本节先把初始化方式枚举放这里,方便选型时一并查:
| 枚举 | 含义 |
|---|---|
PromptTuningInit.TEXT | 从一段文字初始化虚拟 token;要求 prompt_tuning_init_text + tokenizer_name_or_path |
PromptTuningInit.SAMPLE_VOCAB | 从词表随机抽 token |
PromptTuningInit.RANDOM | 纯随机 soft token(可能 off-manifold) |
MultitaskPromptTuningInit.TEXT | 同上 |
MultitaskPromptTuningInit.AVERAGE_SOURCE_TASKS | 用多个源任务 prompt 的均值 |
MultitaskPromptTuningInit.EXACT_SOURCE_TASK | 复制某个具体源任务的 prompt(用 prompt_tuning_init_task 指定 task ID) |
MultitaskPromptTuningInit.ONLY_SOURCE_SHARED | 只用源任务共享的 embedding |
MultitaskPromptTuningInit.RANDOM | 随机 |
Multitask Prompt Tuning 的额外字段:prompt_tuning_init_state_dict_path(源 checkpoint)+ prompt_tuning_init_task(task ID)+ num_ranks + num_tasks。
8.11这章你需要带走的
- IA³ 参数量 ~0.02%,适合多 adapter / 风格调整,不适合知识增强;
- VeRA 跨层共享 A, B 矩阵,只学缩放 vector;
- LoHa / LoKr 用 Hadamard / Kronecker 分解 ΔW,视觉生成常用;
- OFT / BOFT / HRA 是"正交旋转"派,不加 ΔW 而是 W' = R W₀;
- NLP 95% 场景 LoRA / DoRA / AdaLoRA 够用,其他方法多是论文实验;
- 同时用多种方法要走
PeftMixedModel。