本文目录导读:

BitFit是一种参数高效微调(PEFT,Parameter-Efficient Fine-Tuning)方法,全称为 “BIAS-terms Fine-Tuning”。
它的核心思想非常简单直接:在微调预训练大语言模型时,只更新模型的偏置项(Bias term)和特定归一化层的参数,而冻结其他所有参数(如权重矩阵、嵌入层等)。
以下是 BitFit 方法的详细解读:
核心原理
- 传统的全参数微调:需要更新模型中所有的权重矩阵和偏置项,对于拥有几十亿甚至上百亿参数的模型,这需要极大的显存和计算资源。
- BitFit:认为模型的绝大部分知识已经存在于预训练的权重矩阵中,微调只需要调整激活值的“阈值”或“偏移量”,它只更新那些加在激活函数之后的偏置向量以及归一化层中的可学习参数(如 LayerNorm 中的
beta和gamma)。 - 被更新的参数:
- 所有 Bias 参数:包括自注意力层(Q、K、V、输出投影)的 Bias,和前馈神经网络层(如 MLP 的线性层)的 Bias。
- 归一化层参数:Layer Normalization 中的缩放参数
gamma和偏移参数beta(在某些 Transformer 架构中,这些参数也被视为 Bias 的一种形式)。
工作流程
- 加载一个预训练好的模型(如 BERT、GPT-2、LLaMA 等)。
- 锁定模型中所有的权重矩阵(
W_Q,W_K,W_V等)和嵌入层。 - 只解锁模型中的偏置项(
bias)和 LayerNorm 的参数(gamma,beta)。 - 在特定下游任务的数据集上进行训练。
- 仅更新这些被解锁的少量参数,其他参数保持不变。
核心优势
- 极其高效:
- 参数数量极少:在 BERT-Base 模型中,可训练的 Bias 参数仅占模型总参数的 08%~0.09% 左右。
- 显存占用低:由于只更新少量参数,优化器的状态(如 Adam 的动量)也只需存储极少的参数,显著降低显存需求,这使得在单卡 GPU 上微调大模型成为可能。
- 通信开销小:在分布式训练或联邦学习中,只需同步极少量的梯度信息。
- 性能强劲:
- 在多项 NLP 基准任务(如 GLUE、SQuAD 等)上,BitFit 的表现与全参数微调相当,甚至在某些任务上略有优势。
- 尤其是在数据量较小或分布偏移较大的场景下,BitFit 表现出更好的泛化能力和鲁棒性(因为修改的参数少,不容易过拟合)。
- 实现简单:不需要像 LoRA 那样在模型中插入额外的适配器层,只需在 PyTorch 等框架中用
requires_grad属性标记即可实现。
与其他 PEFT 方法的对比
| 方法 | 可训练参数量 (BERT-Base) | 核心原理 | 优点 | 缺点 |
|---|---|---|---|---|
| 全参数微调 | 100% (~110M) | 更新所有权重 | 理论上限高 | 显存大,容易过拟合,存储成本高 |
| BitFit | ~0.08% | 只更新偏置项和 LayerNorm 参数 | 极轻量,显存低,不易过拟合 | 在某些复杂任务上可能性能略低于 LoRA;参数选择固定,灵活度不如 Adapter |
| LoRA | ~0.1% ~ 1% | 在权重矩阵旁添加低秩矩阵 | 可插拔,不影响推理速度,灵活 | 需手动选择应用层和秩 r |
| Adapter | ~3% ~ 6% | 在 Transformer 块中插入小型 FFN | 较为通用 | 增加模型层数,推理速度略有下降 |
代码实现示例 (PyTorch)
在实际代码中,实现 BitFit 非常直接:
import torch
from transformers import BertForSequenceClassification
model = BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=2)
# 遍历所有参数,冻结除 bias 和 LayerNorm 参数外的所有参数
for name, param in model.named_parameters():
# bias 名称包含 'bias',LayerNorm 参数名称包含 'LayerNorm' 或 'gamma'/'beta'
# 注意:在 HuggingFace 的 Bert 中,LayerNorm 的参数是 named 'gamma' 和 'beta'
if 'bias' in name or 'LayerNorm' in name or 'gamma' in name or 'beta' in name:
param.requires_grad = True
else:
param.requires_grad = False
# 检查可训练参数的数量
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
total_params = sum(p.numel() for p in model.parameters())
print(f"Trainable params: {trainable_params} ({100 * trainable_params / total_params:.4f}%)")
# 输出示例: Trainable params: 90112 (0.0818%)
# 然后正常进行训练
局限性与讨论
- 并非万能:虽然在很多任务上效果不错,但在某些需要大幅度调整模型行为的任务(如改变输出格式、学习新知识)上,单纯调整 Bias 可能不够,LoRA 或全参数微调可能更有效。
- 理论基础:为什么只改 Bias 就有效?直观理解是,Transformer 中的线性变换主要依赖权重矩阵学习特征模式,而 Bias 负责调整激活函数的输出偏移,以适应特定任务下特征分布的细微变化。
- 与其他方法结合:BitFit 可以与其他 PEFT 方法结合使用,例如先使用 LoRA 进行主要的适配,再配合 BitFit 进行微调。
BitFit 是一种极简、高效且有效的参数高效微调方法,它通过精确定位并只修改模型中的偏置项,在几乎不增加计算和存储成本的前提下,获得了与全参数微调相媲美的性能,它特别适合在计算资源有限、需要快速迭代或进行大量实验的场景下使用。