class_docstr: The basic implementation for self-attention block/non-local block
  Input:
      N X C X H X W
  Parameters:
      in_channels       : the dimension of the input feature map
      key_channels      : the dimension after the key/query transform
      value_channels    : the dimension after the value transform
      scale             : choose the scale to downsample the input feature maps (save memory cost)
  Return:
      N X C X H X W
      position-aware context features.(w/o concate or add with the input)
code: def forward(self, x):  # skipcq: PYL-W0221
      batch_size, h, w = x.size(0), x.size(2), x.size(3)
      if self.scale > 1:
          x = self.pool(x)
  
      value = self.f_value(x).view(batch_size, self.value_channels, -1)
      value = value.permute(0, 2, 1)
      query = self.f_query(x).view(batch_size, self.key_channels, -1)
      query = query.permute(0, 2, 1)
      key = self.f_key(x).view(batch_size, self.key_channels, -1)
  
      sim_map = torch.matmul(query, key)
      sim_map = (self.key_channels**-0.5) * sim_map
      sim_map = F.softmax(sim_map, dim=-1)
  
      context = torch.matmul(sim_map, value)
      context = context.permute(0, 2, 1).contiguous()
      context = context.view(
          batch_size, self.value_channels, *x.size()[2:]
      )
      context = self.W(context)
      if self.scale > 1:
          context = F.interpolate(
              input=context,
              size=(h, w),
              mode="bilinear",
              align_corners=False,
          )
      return context
  
imports: import torch
  import torch.nn.functional
  from torch import nn
  from ..modules.activations import ABN
label_desc: Use image node_id 2 for calling the _SelfAttentionBlock obj's underlying member method code with example usage: obj.forward(x) and returns: context