PyTorch 自注意力机制实现:Attention 类详解
这段代码定义了一个名为 Attention 的类,继承自 nn.Module。该类实现了自注意力机制(self-attention)。
在类的构造函数中,接受四个参数 dim、heads、dim_head 和 dropout,其中 dim 表示输入数据的维度,heads 表示注意力头的数量,dim_head 表示每个注意力头的维度,dropout 表示 dropout 的概率,默认为 0。
在构造函数中,首先计算出内部维度 inner_dim,即 dim_head 乘以 heads。然后,保存头的数量 heads 和缩放因子 scale,缩放因子为 dim_head 的倒数。
接下来,通过 nn.Linear 定义了一个线性层 self.to_qkv,用于将输入数据 x 转换为查询(query)、键(key)和值(value)的表示。这里使用了一个线性层,并且将输出切分为三部分,分别对应查询、键和值。
然后,定义了一个序列模块 self.to_out,其中包含一个线性层和一个 dropout 层,用于将自注意力机制的输出转换为最终的输出。
在 forward 方法中,接受输入 x 和可选的掩码 mask。首先,通过 x.shape 获取输入 x 的形状,并计算出批次大小 b、序列长度 n、头的数量 h。
然后,将输入 x 通过线性层 self.to_qkv 进行查询、键和值的转换,并使用 chunk 方法将输出切分为三部分,分别对应查询 q、键 k 和值 v。同时,使用 rearrange 函数对查询、键和值的维度进行重排,以适应自注意力机制的计算。
接下来,通过 torch.einsum 函数计算注意力权重 dots,其中 q 和 k 进行点积操作,并乘以缩放因子 self.scale。这里使用了 einsum 函数进行张量运算,得到的 dots 张量的形状为 (b, h, n, n)。
然后,如果存在掩码 mask,则对注意力权重 dots 进行掩码操作。首先,将掩码进行扁平化并进行填充,以匹配注意力权重 dots 的形状。然后,使用掩码对注意力权重进行填充,并使用掩码值 mask_value 对未填充的位置进行屏蔽。最后,删除掩码变量。
接下来,对注意力权重进行 softmax 操作,得到归一化的注意力权重 attn。
然后,通过 torch.einsum 函数计算加权后的值 out,其中注意力权重 attn 与值 v 进行点积操作。这里同样使用了 einsum 函数进行张量运算,得到的 out 张量的形状为 (b, h, n, d)。
接下来,使用 rearrange 函数对 out 进行重排,将头的维度和特征维度合并为一个维度,得到形状为 (b, n, h * d) 的张量。
最后,将重排后的张量通过序列模块 self.to_out 进行线性变换和 dropout 操作,并返回最终的输出。
整体来说,这段代码实现了自注意力机制的计算过程,通过查询、键和值的线性变换和注意力权重的计算,将输入数据进行加权求和,得到最终的输出。
原文地址: https://www.cveoy.top/t/topic/cnIx 著作权归作者所有。请勿转载和采集!