Resumen del mecanismo común de atención del CV

Este artículo resume los mecanismos de atención comúnmente utilizados en el campo CV en los últimos años, entre ellos: SE (Squeeze and Excitation), ECA (Efficient Channel Attention), CBAM (Convolutional Block Attention Module), CA (Coordinate Attention for Efficient Mobile Network Design)

1. SE

El propósito es asignar diferentes pesos a diferentes canales en el mapa de características, los pasos son los siguientes:

  1. Exprima el mapa de características. Este paso es convertir el mapa de características del tamaño (N, C, H, W) a (N, C, 1, 1) a través de la agrupación promedio global, para lograr la fusión de información de contexto global
  2. Operación de excitación, este paso usa dos capas completamente conectadas, la primera capa completamente conectada usa la función de activación ReLU, y la segunda capa completamente conectada usa la función de activación Sigmoid para mapear los pesos entre (0, 1). Vale la pena señalar que para reducir la cantidad de cálculo para la reducción de dimensionalidad, la salida de la primera conexión completa usa 1/4 o 1/16 de la entrada
  3. El peso se multiplica por el mapa de características de entrada a través del mecanismo de transmisión para obtener el mapa de características con diferentes pesos

El código se implementa de la siguiente manera, 

import torch
import torch.nn as nn


class Se(nn.Module):
    def __init__(self, in_channel, reduction=16):
        super(Se, self).__init__()
        self.pool = nn.AdaptiveAvgPool2d(output_size=1)
        self.fc = nn.Sequential(
            nn.Linear(in_features=in_channel, out_features=in_channel//reduction, bias=False),
            nn.ReLU(),
            nn.Linear(in_features=in_channel//reduction, out_features=in_channel, bias=False),
            nn.Sigmoid()
        )

    def forward(self,x):
        out = self.pool(x)
        out = self.fc(out.view(out.size(0),-1))
        out = out.view(x.size(0),x.size(1),1,1)
        return out*x

2. CEPA

Puede consultar " Mecanismo de atención ECA-Net Learning Record_eca Mecanismo de atención_chen_zn95's Blog-CSDN Blog "

ECA también es un mecanismo de atención de canal. Este algoritmo ha realizado algunas mejoras sobre la base de SE. Primero, el autor de ECA cree que la reducción total de la dimensionalidad de la conexión en SE puede reducir la complejidad del modelo, pero esto también destruye la correspondencia directa entre los canales y sus pesos. La reducción de la dimensionalidad es seguida primero por la mejora de la dimensionalidad, de modo que la correspondencia entre los pesos y los canales es indirecta. Para resolver los problemas anteriores, el autor propone un método de convolución unidimensional para evitar el impacto de la reducción de la dimensionalidad en los datos.Los pasos son los siguientes:

  1. Apriete el mapa de características. Este paso es convertir el mapa de características del tamaño (N, C, H, W) a (N, C, 1, 1) a través de la agrupación promedio global, para lograr la fusión de información de contexto global (igual que el paso 1 de SE)
  2. Calcule el tamaño del kernel de convolución adaptable, k=\izquierda |  \frac{log_{2}^{C}}{\gamma }+\frac{b}{\gamma } \right |donde, C: el número de canales de entrada, b=1, γ=2; realice una operación de convolución unidimensional en las características procesadas en el paso 1 (para obtener información local de canales cruzados) y luego use la función de activación Sigmoid para mapear el peso entre 0 y 1
  3. El peso se multiplica por el mapa de características de entrada a través del mecanismo de transmisión para obtener el mapa de características con diferentes pesos

El código se implementa de la siguiente manera,

import torch
import torch.nn as nn
import math


class ECA(nn.Module):
    def __init__(self, in_channel, gamma=2, b=1):
        super(ECA, self).__init__()
        k = int(abs((math.log(in_channel,2)+b)/gamma))
        kernel_size = k if k % 2 else k+1
        padding = kernel_size//2
        self.pool = nn.AdaptiveAvgPool2d(output_size=1)
        self.conv = nn.Sequential(
            nn.Conv1d(in_channels=1, out_channels=1, kernel_size=kernel_size, padding=padding, bias=False),
            nn.Sigmoid()
        )

    def forward(self,x):
        out=self.pool(x)
        out=out.view(x.size(0), 1, x.size(1))
        out=self.conv(out)
        out=out.view(x.size(0), x.size(1), 1, 1)
        return out*x

3. CBAM

CBAM es un algoritmo que combina el canal y el mecanismo de atención espacial. El mapa de características de entrada se somete primero al mecanismo de atención del canal y luego a la operación del mecanismo de atención espacial. De esta manera, el propósito de fortalecer la región de interés se logra tanto desde el canal como desde el espacio.

Los pasos de implementación del mecanismo de atención del canal son los siguientes:

  1. Apriete el mapa de características. Este paso utiliza la agrupación promedio global y la agrupación máxima global para convertir el mapa de características del tamaño (N, C, H, W) a (N, C, 1, 1), logrando así la fusión de la información de contexto global.
  2. Los resultados de la agrupación máxima global y la agrupación promedio global están sujetos respectivamente a operaciones MLP. MLP se define aquí como la operación de capa totalmente conectada de SE. Es una capa totalmente conectada de dos capas con activación ReLU en el medio. Finalmente, las dos se agregan y luego se activan mediante la función Sigmoid.
  3. El peso se multiplica por el mapa de características de entrada a través del mecanismo de transmisión para obtener el mapa de características con diferentes pesos

Los pasos de implementación del mecanismo de atención espacial son los siguientes:

  1. Realice la agrupación máxima y la agrupación promedio en la dimensión del canal para obtener los resultados de la operación de atención del canal anterior, es decir, convierta el mapa de características a través del mecanismo de atención del canal de (N, C, H, W) a (N, 1, H, W), fusione la información de diferentes canales y luego concatene los resultados de la agrupación máxima y la agrupación promedio en la dimensión del canal
  2. Realice la operación de convolución en los resultados de los 2 canales superpuestos, el canal de salida es 1, el tamaño del kernel de convolución es 7 y, finalmente, el resultado de salida es procesado por Sigmoid
  3. El peso se multiplica por el mapa de características de entrada a través del mecanismo de transmisión para obtener el mapa de características con diferentes pesos

El código se implementa de la siguiente manera,

import torch
import torch.nn as nn
import math


class CBAM(nn.Module):
    def __init__(self, in_channel, reduction=16, kernel_size=7):
        super(CBAM, self).__init__()
        # 通道注意力机制
        self.max_pool = nn.AdaptiveMaxPool2d(output_size=1)
        self.avg_pool = nn.AdaptiveAvgPool2d(output_size=1)
        self.mlp = nn.Sequential(
            nn.Linear(in_features=in_channel, out_features=in_channel//reduction, bias=False),
            nn.ReLU(),
            nn.Linear(in_features=in_channel//reduction, out_features=in_channel,bias=False)
        )
        self.sigmoid = nn.Sigmoid()
        # 空间注意力机制
        self.conv = nn.Conv2d(in_channels=2, out_channels=1, kernel_size=kernel_size , stride=1, padding=kernel_size//2, bias=False)

    def forward(self,x):
        # 通道注意力机制
        max_out = self.max_pool(x)
        max_out = self.mlp(max_out.view(maxout.size(0), -1))
        avg_out = self.avg_pool(x)
        avg_out = self.mlp(avg_out.view(avgout.size(0), -1))
        channel_out = self.sigmoid(max_out+avg_out)
        channel_out = channel_out.view(x.size(0), x.size(1),1,1)
        channel_out = channel_out*x
        # 空间注意力机制
        max_out, _ = torch.max(channel_out, dim=1, keepdim=True)
        mean_out = torch.mean(channel_out, dim=1, keepdim=True)
        out = torch.cat((max_out, mean_out), dim=1)
        out = self.sigmoid(self.conv(out))
        out = out*channel_out
        return out

4. CA

Los SE son notablemente efectivos para mejorar el rendimiento del modelo, pero generalmente ignoran la información de ubicación. CA utiliza la agrupación global en las direcciones x e y para agregar las características de entrada en las direcciones vertical y horizontal en dos mapas de características sensibles a la dirección e incorpora la información de posición del mapa de características de entrada en el vector de características agregadas de la atención del canal. Estos dos mapas de características que incorporan información específica de la dirección se codifican en dos mapas de atención respectivamente, y luego estos dos mapas de atención se aplican al mapa de características de entrada por multiplicación para fortalecer la representación de la región de interés. Los pasos de implementación son los siguientes:

  1. Realice operaciones de agrupación adaptativa en el mapa de características de entrada a lo largo de las direcciones x e y, cambie el tamaño del mapa de características de (N,C,H,W) a (N,C,H,1), (N,C,1,W), realice una operación de permutación en la característica con un tamaño de (N,C,1,W), de modo que el tamaño de la característica se convierta en (N,C,W,1) y luego concatene estas dos características junto con (dim=2) para obtener un mapa de características con un tamaño de (N,C,H+ W, 1 )
  2. Realice una operación de convolución 1*1 en las características procesadas en el paso 1 (para la reducción de la dimensionalidad) y luego pase a través de las funciones de activación BN y h_swish
  3. Realice una operación de división (torch.split) en las funciones procesadas en el paso 2 a lo largo de dim=2 y divida las funciones en (N,C/r,H,1), (N,C/r,W,1), donde r es el factor de reducción de la dimensionalidad del canal. Luego, la operación de permutación se realiza en la característica de tamaño (N, C/r, W, 1), que se convierte en (N, C/r, 1, W). Finalmente, se realiza una operación de convolución 1*1 en las dos características anteriores (el propósito es cambiar el número de canales del mapa de características) y se procesa mediante Sigmoid.
  4. Multiplique las dos características del paso 3 con el mapa de características de entrada a través del mecanismo de transmisión (out = identidad * a_w * a_h) para obtener el mapa de características con diferentes pesos

[Hay un pequeño problema en la imagen a continuación, debería ser la operación de permutación en la función 1D Global Promedio Pool (W) ]

El código se implementa de la siguiente manera,

import torch
import torch.nn as nn
import math
import torch.nn.functional as F


class h_sigmoid(nn.Module):
    def __init__(self, inplace=True):
        super(h_sigmoid, self).__init__()
        self.relu = nn.ReLU6(inplace=inplace)

    def forward(self, x):
        return self.relu(x + 3) / 6

class h_swish(nn.Module):
    def __init__(self, inplace=True):
        super(h_swish, self).__init__()
        self.sigmoid = h_sigmoid(inplace=inplace)

    def forward(self, x):
        return x * self.sigmoid(x)

class CoordAtt(nn.Module):
    def __init__(self, inp, oup, reduction=32):
        super(CoordAtt, self).__init__()
        self.pool_h = nn.AdaptiveAvgPool2d((None, 1))
        self.pool_w = nn.AdaptiveAvgPool2d((1, None))

        mip = max(8, inp // reduction)

        self.conv1 = nn.Conv2d(inp, mip, kernel_size=1, stride=1, padding=0)
        self.bn1 = nn.BatchNorm2d(mip)
        self.act = h_swish()
        
        self.conv_h = nn.Conv2d(mip, oup, kernel_size=1, stride=1, padding=0)
        self.conv_w = nn.Conv2d(mip, oup, kernel_size=1, stride=1, padding=0)
        

    def forward(self, x):
        identity = x
        
        n,c,h,w = x.size()
        x_h = self.pool_h(x)
        x_w = self.pool_w(x).permute(0, 1, 3, 2)

        y = torch.cat([x_h, x_w], dim=2)
        y = self.conv1(y)
        y = self.bn1(y)
        y = self.act(y) 
        
        x_h, x_w = torch.split(y, [h, w], dim=2)
        x_w = x_w.permute(0, 1, 3, 2)

        a_h = self.conv_h(x_h).sigmoid()
        a_w = self.conv_w(x_w).sigmoid()

        out = identity * a_w * a_h

        return out

Supongo que te gusta

Origin blog.csdn.net/qq_38964360/article/details/131677227
Recomendado
Clasificación