1. 从零理解Attention-mask:它到底在“遮”什么?
如果你刚开始接触Transformer模型,看到“Attention-mask”这个词,可能会觉得有点抽象。别担心,我第一次看到的时候也是一头雾水。简单来说,你可以把它想象成我们小时候做填空题时,老师为了防止我们偷看后面的答案,会用一张纸把后面的部分遮起来。Attention-mask在Transformer里干的就是这个“遮”的活儿,它告诉模型:“喂,看这里,别看那里!”
但为什么需要这个“遮罩”呢?这得从我们处理文本数据的实际情况说起。我们喂给模型的句子,长度千差万别,有的只有几个词,有的可能长达几百个词。而模型的计算,尤其是矩阵运算,要求输入必须是规整的、固定长度的。这就好比一个工厂的流水线,每个工位处理一个零件,如果零件大小不一,流水线就没法高效运转。所以,我们得把所有的句子都“填充”到同一个固定长度。短的句子后面就加上一堆没有实际意义的“[PAD]”标记。
问题来了。在Transformer核心的Self-Attention(自注意力)机制里,每个词都会和句子里的所有其他词(包括那些没用的[PAD])计算一个“亲密度”分数。如果我们不加以干预,这些填充的[PAD]也会参与到计算中,并且会分走一部分“注意力”。这就像你在认真听一个人讲话,旁边却一直有个机器在发出无意义的噪音,这个噪音虽然没内容,但也会干扰你的听力。Attention-mask的作用,就是精准地“屏蔽”掉这些噪音,让模型只关注真正有意义的词。
我刚开始学的时候,以为这个“屏蔽”就是简单地把对应位置的分数乘以0。但后来看源码才发现,事情没那么简单。因为后续的Softmax操作会把分数转换成概率分布,即使一个分数是0,经过指数运算e^0后也等于1,它依然会占据一部分概率。真正的做法要巧妙得多:不是把分数变0,而是把它变成一个极大的负数(比如-1e9),这样经过Softmax后,它的概率就无限接近于0了。这个“偷梁换柱”的细节,是理解Attention-mask如何生效的关键,也是很多初学者容易踩的坑。
2. Self-Attention机制快速回顾:没有它,就没有Mask
要彻底搞懂Mask,我们得先快速过一遍Self-Attention是怎么工作的。别怕,我用最直白的方式讲给你听。想象一下你读一段文章,读到“苹果”这个词时,你的大脑会瞬间关联到“水果”、“公司”、“手机”还是“吃”?这个快速关联和聚焦的过程,就是“注意力”。
在模型里,这个过程被数学化了。每个输入词(比如“苹果”)会通过三组可学习的参数矩阵,变身成三个向量:
- 查询向量(Query):代表“我(苹果)要找什么”。
- 键向量(Key):代表“我(苹果)有什么特征,能被别人找到”。
- 值向量(Value):代表“我(苹果)真正要贡献的信息内容”。
计算分四步走:
- 计算亲密度:用“苹果”的Query向量,去和句中所有词(包括“苹果”自己)的Key向量做点乘。点乘得分越高,说明这两个词关系越密切。
- 缩放:把得分除以一个常数(通常是Key向量维度的平方根),防止数值过大导致训练不稳定。
- 概率化:对得分进行Softmax操作,让一行的所有得分加起来等于1,变成一组概率分布。这表示“苹果”应该把多少“注意力”分配给其他每个词。
- 加权求和:用这组概率作为权重,对所有词的Value向量进行加权求和,得到“苹果”在这个位置最终的输出向量。
这个过程用矩阵运算可以一次性处理所有词,非常高效。但这里就暴露了问题:那些填充的[PAD]标记,它们也有自己的Key和Value向量。虽然它们本身没意义,但在第三步Softmax后,它们也会被分配到一定的概率权重,从而“污染”最终加权求和的结果。Attention-mask就是在第三步之前介入,修正这个问题的。
3. Attention-mask的实战:从理论到代码的跨越
理解了为什么需要Mask,我们来看看它在代码里到底长什么样,怎么用。这里我直接带你读Hugging Face Transformers库里的BERT源码,这是最权威的参考。
首先,我们得知道Mask张量是怎么来的。通常,分词器(Tokenizer)在编码句子时,会自动生成一个attention_mask。对于真实单词,它的值是1;对于填充的[PAD],值是0。比如句子“我爱AI”填充到长度8,Mask可能就是 [1, 1, 1, 1, 0, 0, 0, 0](假设有[CLS]和[SEP]标记)。
这个Mask的原始形状是 [batch_size, sequence_length]。但在Self-Attention计算中,注意力分数矩阵的形状

340

被折叠的 条评论
为什么被折叠?



