在自然语言处理(NLP)领域,Google AI研究人员提出了BERT模型,它极大地推动了该领域的发展。2019年,研究人员进一步提出了ALBERT("A Lite BERT")模型,这是一种用于语言表示自监督学习的模型,它与BERT共享相同的架构基础。ALBERT模型的主要目标是通过采用不同的技术,例如嵌入矩阵的分解、参数共享和句子间连贯性损失,来改进BERT架构的训练和结果。本文将详细解释模型的组成部分以及如何在项目中使用它。
ALBERT模型的关键特性
ALBERT架构的骨干与BERT相同,采用了设计选择,例如i) 嵌入参数分解,ii) 跨层参数共享,iii) 句子间连贯性损失,以减少参数数量,从而降低内存消耗并提高BERT的训练速度。此外,采用了一种自监督损失,专注于建模句子间连贯性,并证明它一致地促进了多句子输入任务的执行。ALBERT-XXL模型仅使用BERT参数的约70%,在多个代表性下游任务的开发集得分上超过了BERT-large,包括SQuAD v1.1、SQuAD v2.0、MNLI、SST-2和RACE。
为什么需要ALBERT这样的模型?
考虑到当前最先进的模型通常具有数百甚至数十亿个参数,随着模型规模的扩大,可能会遇到内存限制问题。此外,分布式训练也可能减慢训练速度,因为通信开销与模型中的参数数量成正比。现有的解决方案包括模型并行化和智能内存管理。这些解决方案解决了内存限制问题,但并未解决通信开销问题。"A Lite BERT"(ALBERT)的架构被提出来应对这一挑战。
ALBERT模型架构
ALBERT架构的骨干与BERT相同,使用带有GELU非线性的变换器编码器。ALBERT在BERT的设计选择上做出了三个主要贡献:
i) 嵌入参数分解:在BERT以及后来的模型改进如XLNet和RoBERTa中,WordPiece嵌入大小E和隐藏层大小H是绑定在一起的,即E ≡ H。然而,无论是在建模还是在应用方面,这种策略都显得不太理想。通过将大型词汇嵌入矩阵分解为两个小型矩阵,将隐藏层大小与词汇嵌入大小分离。当H >> E时,这种参数减少是显著的。
ii) 跨层参数共享:跨层参数共享是另一种提高参数效率的技术。参数可以在不同方式上共享:仅在层之间共享前馈网络(FFN)参数,仅共享注意力参数,或在层之间共享所有参数。ALBERT默认的方法是在层之间共享所有参数。后来,在测试中发现,权重共享会影响网络参数的稳定。尽管与BERT相比,L2距离和余弦相似度有所下降,但它们仍然没有收敛到0,即使在24层之后。
iii) 句子间连贯性损失:与BERT类似,ALBERT在训练中也使用了掩蔽语言模型。然而,ALBERT没有使用NSP(下一句预测)损失,而是使用了一种新的损失,称为SOP(句子顺序预测)。NSP是一种二元分类损失,用于检查连贯性和确定下一句的主题。然而,SOP只寻找句子连贯性,避免了主题预测。与BERT一样,SOP损失使用正例(来自同一文档的两个连续段落)和负例(相同的两个连续段落,但顺序颠倒)。这迫使模型捕捉到关于话语级连贯性属性的细微差别。在测试中,结果表明NSP根本无法解决SOP任务(即,它学习了更容易的主题预测信号,并在随机基线水平上完成了SOP任务),而SOP可以在很大程度上解决NSP任务。因此,ALBERT模型在多句子编码任务的下游任务性能上持续提高。
ALBERT与BERT的比较
与BERT一样,ALBERT是在英文维基百科和Book CORPUS数据集上预训练的,包含16GB的未压缩数据。由于ALBERT架构中使用的参数减少技术,ALBERT模型与相应的BERT模型相比具有更小的参数大小。例如,BERT基础版比ALBERT基础版多9倍的参数,BERT Large比ALBERT Large多18倍的参数。
与同等的BERT模型相比,ALBERT模型由于通信和计算开销较小,因此具有更高的数据吞吐量。例如,如果以BERT-large作为基线,ALBERT-large在数据迭代中的速度大约是BERT-large的1.7倍,而ALBERT-XXL由于结构更大,速度大约是BERT-large的3倍。
局限性和偏见
即使用于此模型的训练数据相对中立,该模型仍可能做出有偏见的预测。
Huggingface的Transformers库提供了不同版本和大小的ALBERT模型。为了演示目的,本文将重点介绍如何加载模型并预测掩码。首先,必须安装并导入所有必要的包,并从AlbertForMaskedLM和AutoTokenizer分别加载模型和其分词器。然后,将整个输入(带有掩码)通过分词器传递以提取标记化的输出,随后用于预测掩码输入。
!pip install -q transformers
import torch
from transformers import AutoTokenizer, AlbertForMaskedLM
model_name = "albert-base-v2"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AlbertForMaskedLM.from_pretrained(model_name)
inputs = tokenizer("The capital of [MASK] is Delhi.", return_tensors="pt")
with torch.inference_mode():
logits = model(**inputs).logits
mask_token_index = (inputs.input_ids == tokenizer.mask_token_id)[0].nonzero(as_tuple=True)[0]
predicted_token_id = logits[0, mask_token_index].argmax(axis=-1)
tokenizer.decode(predicted_token_id)
>> Output: India
可以在这里尝试上述代码:.