Skip to content

输入关键词开始搜索

BERT-tiny 迁移学习实验:LoRA 的参数效率到底值不值


这次实验主要想验证一个问题:

在医学文本分类任务里,不同微调方式到底差在哪里?

我选了一个比较轻量的设置:

模型:BERT-tiny
数据集:PubMed-RCT20k
任务:医学论文摘要句子分类
硬件:NVIDIA A10
训练轮数:3 epoch

实验一共跑了四组:

random_init
freeze_bert
lora
full_finetune

最后结果如下:

方法AccuracyMacro-F1训练时间/s显存/MB可训练参数比例
random_init0.80320.731462.91294.83100.0000%
freeze_bert0.59270.475661.4396.400.0147%
lora0.76130.686661.88221.900.2011%
full_finetune0.82160.753761.72294.71100.0000%

结果比较直观:

full_finetune 效果最好
random_init 在全样本下表现也不错
lora 参数效率很高
freeze_bert 最省资源,但效果明显不足

迁移学习在 NLP 任务里非常常见。

一般情况下,我们不会直接从零训练一个语言模型,而是先拿一个已经预训练过的模型,再让它适应自己的下游任务。

比如 BERT 已经在大规模语料上学习过语言表示。

当我们要做医学文本分类时,可以直接复用它已有的语言知识,而不是让模型重新学习词汇、句法和基础语义。

不过,复用预训练模型也有很多方式。

有些方法只训练最后的分类头,有些方法更新整个模型,还有些方法只训练少量额外参数。

这次实验就是想比较这些策略的差异。


实验任务是医学文本分类。

数据集使用 PubMed-RCT20k。

这个数据集里的每条样本是一句医学论文摘要中的句子,模型需要判断这句话属于摘要中的哪个部分。

常见类别包括:

BACKGROUND
OBJECTIVE
METHODS
RESULTS
CONCLUSIONS

举个例子,输入可能是:

The patients were randomly assigned to the treatment group or control group.

模型需要判断它更像是方法部分、结果部分,还是背景部分。

这个任务本质上是一个多分类问题:

输入:一句医学文本
输出:摘要结构类别

这次没有直接用 bert-base-uncased,而是用了更小的模型:

prajjwal1/bert-tiny

原因很简单:这次实验重点不是刷最高准确率,而是比较训练策略。

BERT-tiny 参数量小,训练速度快,很适合做课程实验和策略对比。

它的优势是:

训练快
显存占用低
方便多组实验对比
A10 上一分钟左右就能跑完一组

如果换成 BERT-base,结果可能更接近正式论文实验,但训练时间也会明显增加。


这次实验比较了四种方法。

它们的区别主要在于两个问题:

是否使用预训练权重?
训练时更新哪些参数?

整理成表格就是:

方法是否使用预训练权重训练哪些参数含义
random_init全部参数不使用迁移学习,模型从零训练
freeze_bert只训练分类头把 BERT 当作固定特征提取器
loraLoRA 参数和分类头参数高效微调
full_finetune全部参数标准全参数微调

五、random_init:不用预训练的对照组

Section titled “五、random_init:不用预训练的对照组”

第一组是 random_init

这组只使用 BERT-tiny 的模型结构,不加载预训练权重。

也就是说,模型一开始什么都没有学过,所有参数都是随机初始化的。

BERT-tiny 结构
随机初始化
在医学文本分类数据上训练全部参数

这组实验的作用是提供一个对照。

它回答的是:

不使用预训练模型,直接训练这个任务,能做到什么程度?

结果是:

Accuracy = 0.8032
Macro-F1 = 0.7314
可训练参数比例 = 100%

这个结果其实不差。

原因也很容易理解:这次用的是全样本训练,而且 BERT-tiny 比较小,所有参数都可以更新,所以模型有足够空间去拟合这个任务。


第二组是 freeze_bert

这组加载了 BERT-tiny 的预训练权重,但冻结了 BERT 主体参数,只训练最后的分类头。

预训练 BERT-tiny
冻结 BERT 主体
只训练分类层

它的可训练参数非常少:

可训练参数量 = 645
可训练参数比例 = 0.0147%

结果是:

Accuracy = 0.5927
Macro-F1 = 0.4756
显存占用 = 96.40 MB

这组显存最低,但效果也是最差的。

原因很明确:只训练分类头,模型主体没有机会根据医学文本分类任务进行调整。

换句话说,它只是把预训练 BERT 当成一个固定特征提取器。

如果这个固定表示刚好适合当前任务,效果可能还可以;如果不够适配,分类头能做的事情就很有限。


第三组是 lora

LoRA 也是基于预训练模型的迁移学习方法。

它不是不用预训练模型,而是在预训练模型基础上只训练少量新增参数。

简单来说:

加载预训练 BERT
冻结原始模型主体
在注意力层加入 LoRA 低秩适配参数
训练 LoRA 参数和分类头

本实验中 LoRA 的可训练参数量是:

可训练参数量 = 8,837
可训练参数比例 = 0.2011%

结果是:

Accuracy = 0.7613
Macro-F1 = 0.6866
显存占用 = 221.90 MB

这个结果明显好于 freeze_bert

方法AccuracyMacro-F1
freeze_bert0.59270.4756
lora0.76130.6866

这说明,只训练分类头太弱,而 LoRA 提供了更强的任务适配能力。

它没有更新整个 BERT,但通过少量适配参数,让模型能够更好地适应医学文本分类任务。


八、full_finetune:预训练模型全参数微调

Section titled “八、full_finetune:预训练模型全参数微调”

第四组是 full_finetune

这组加载预训练 BERT-tiny,然后训练全部参数。

预训练 BERT-tiny
所有参数参与训练
完成医学文本分类任务适配

结果是:

Accuracy = 0.8216
Macro-F1 = 0.7537
可训练参数比例 = 100%

这是四组里面效果最好的。

它比 random_init 更高:

方法AccuracyMacro-F1
random_init0.80320.7314
full_finetune0.82160.7537

这说明预训练权重确实有帮助。

虽然 BERT-tiny 很小,但预训练模型作为初始点,仍然能让最终效果更好。


完整实验结果如下:

方法AccuracyMacro-F1训练时间/s显存/MB总参数量可训练参数量可训练参数比例
random_init0.80320.731462.91294.834,386,5654,386,565100.0000%
freeze_bert0.59270.475661.4396.404,386,5656450.0147%
lora0.76130.686661.88221.904,395,4028,8370.2011%
full_finetune0.82160.753761.72294.714,386,5654,386,565100.0000%

按分类性能排序:

full_finetune > random_init > lora > freeze_bert

按可训练参数量排序:

freeze_bert < lora << random_init = full_finetune

如果只看最高准确率,full_finetune 最好。

如果考虑参数效率,lora 更值得关注。


十、为什么 LoRA 没有超过 random_init

Section titled “十、为什么 LoRA 没有超过 random_init”

这个结果一开始容易让人困惑。

因为 LoRA 使用了预训练模型,而 random_init 没有使用预训练模型。

但是两者的训练自由度完全不同。

random_init:
不使用预训练权重,但训练全部参数。
lora:
使用预训练权重,但只训练 0.2011% 的参数。

这次实验使用的是全样本数据。

在数据量比较充足的情况下,BERT-tiny 这种小模型即使随机初始化,只要允许全部参数更新,也可以学得不错。

所以 random_initlora 高,并不代表 LoRA 没有价值。

更合理的理解是:

random_init 用大量可训练参数换来了更高性能,而 LoRA 用很少参数换来了还不错的效果。

LoRA 的优势不在于所有场景都超过全参数训练,而在于参数效率。


LoRA 最有意义的比较对象有两个。

两者都使用预训练模型,也都冻结了大部分参数。

但是结果差距很明显:

freeze_bert Accuracy = 0.5927
lora Accuracy = 0.7613

这说明 LoRA 的适配能力明显强于只训练分类头。

分类头只能利用固定特征,而 LoRA 能让模型内部的注意力层产生一定变化。

全参数微调效果最好,但成本也最大。

full_finetune 可训练参数 = 4,386,565
lora 可训练参数 = 8,837

全参数微调的可训练参数量约为 LoRA 的:

4,386,565 / 8,837 ≈ 496 倍

但 LoRA 的 Accuracy 达到了 full_finetune 的:

0.7613 / 0.8216 ≈ 92.7%

也就是说,LoRA 只训练了极少的参数,但保留了相当一部分性能。

这就是它的价值。


显存占用如下:

方法显存/MB
freeze_bert96.40
lora221.90
full_finetune294.71
random_init294.83

freeze_bert 最省显存,因为它只训练分类头。

lora 显存高于冻结方法,但低于全参数训练。

full_finetunerandom_init 都训练全部参数,所以显存接近。

训练时间方面,四组差异不明显:

random_init 62.91s
freeze_bert 61.43s
lora 61.88s
full_finetune 61.72s

主要原因是模型太小,A10 也比较快。

所以这次实验里,训练时间不是最重要的指标。

更应该关注:

分类性能
显存占用
可训练参数比例

这次实验可以得出几个结论。

第一,full_finetune 效果最好。

Accuracy = 0.8216
Macro-F1 = 0.7537

说明预训练模型经过全参数微调后,能够很好地适应医学文本分类任务。

第二,random_init 在全样本条件下也表现不错。

Accuracy = 0.8032
Macro-F1 = 0.7314

这说明当数据量比较充足、模型规模比较小时,从零训练也可以取得较强结果。

第三,freeze_bert 成本最低,但效果明显不足。

可训练参数比例 = 0.0147%
Accuracy = 0.5927

这说明只训练分类头的表达能力有限。

第四,lora 在性能和成本之间取得了比较好的平衡。

可训练参数比例 = 0.2011%
Accuracy = 0.7613
Macro-F1 = 0.6866

它明显优于冻结 BERT,并且在只训练极少参数的情况下达到了全参数微调 92.7% 左右的 Accuracy。


这次实验之后,我对迁移学习的理解更具体了。

迁移学习不是简单地说:

用了预训练模型,所以一定更好。

更关键的是:

预训练权重怎么用?
哪些参数允许更新?
下游数据量有多少?
算力和显存是否受限?
目标是最高性能还是最高效率?

在这次实验里,四种方法各自代表一种选择:

方法适合场景
full_finetune追求最高效果
lora参数和显存受限,但希望保留较好效果
freeze_bert快速验证任务是否可行
random_init数据充足、模型较小、不依赖预训练权重

如果是课程实验,四组方法一起比较可以很好地说明迁移学习的不同使用方式。

如果是真实大模型场景,LoRA 的意义会更明显。

因为模型越大,全参数微调成本越高,而 LoRA 的参数效率优势也越重要。


十五、后续可以继续补充的实验

Section titled “十五、后续可以继续补充的实验”

这次实验已经能说明基本问题,但还可以继续扩展。

当前用的是全样本。

如果只取:

1000
3000
5000

条训练样本,结果可能会发生变化。

小样本条件下,预训练模型的优势通常会更明显,而随机初始化可能更难训练。

可以把 BERT-tiny 换成:

bert-base-uncased

或者医学领域模型:

BioBERT
PubMedBERT
ClinicalBERT

这样结果会更接近真实医学 NLP 场景。

当前 LoRA 只跑了一组配置。

后面可以比较:

r = 4 / 8 / 16
lora_alpha = 8 / 16 / 32
target_modules = query / value / key / dense

这样可以进一步观察 LoRA 参数量和性能之间的关系。

当前统一训练 3 epoch。

后续可以跑:

1 epoch
3 epoch
5 epoch
10 epoch

不同方法的收敛速度可能不一样。


这次实验的核心结论是:

全参数微调效果最好,LoRA 参数效率最高,冻结 BERT 最省资源但效果不足,随机初始化在全样本条件下也有较强表现。

更具体地说:

full_finetune:
使用预训练模型,训练全部参数,性能最高。
lora:
使用预训练模型,只训练少量适配参数,性能明显优于冻结 BERT,参数效率很高。
freeze_bert:
使用预训练模型,只训练分类头,资源开销最低,但任务适应能力不足。
random_init:
不使用预训练模型,训练全部参数,在全样本条件下表现不错。

这次实验让我更清楚地看到:

迁移学习不是一个固定答案,而是一组取舍:效果、参数量、显存、数据规模和训练成本都要一起看。

如果只追求指标,full_finetune 是最好的选择。

如果希望在较低训练成本下获得可接受效果,LoRA 更有代表性。