深度学习中的大多数计算都是为了提高速度性能而矢量化的,而对于自注意力也没有什么不同。如果为简单起见忽略 batch 维度,则 1×1 卷积后的激活将具有 (H, W, C) 的形状。第一步是将其重塑为形状为 (H×W, C) 的2D矩阵,并使用 θ θ θ 与 φ φ φ 的矩阵相乘来计算注意力图。在SAGAN中使用的自注意力模块中,还有另一个1×1卷积,用于将通道数恢复到与输入通道数相同的数量,然后使用可学习的参数进行缩放操作。
首先在自定义层的build()中定义所有 1×1 卷积层和权重。这里,使用频谱归一化函数作为卷积层的核约束:
class SelfAttention(Layer):
def init(self):
super(SelfAttention, self).init()
def build(self, input_shape):
n,h,w,c = input_shape
self.n_feats = h * w
self.conv_theta = Conv2D(c//8, 1, padding=‘same’, kernel_constraint=SpectralNorm(), name=‘Conv_Theta’)
self.conv_phi = Conv2D(c//8, 1, padding=‘same’, kernel_constraint=SpectralNorm(), name=‘Conv_Phi’)
self.conv_g = Conv2D(c//8, 1, padding=‘same’, kernel_const