[딥러닝] CNN Attention 기법 정리(SE(Squeeze-and-Excitation), CBAM(Convolutional Block Attention Module), ECA(Efficient Channel Attention))

2025. 6. 19. 18:08·Study/Computer Vision

- 이번 포스팅에서는 Vision Transformer 가 아닌, CNN 모델에서 사용되는 Attention 기법에 대해 정리하겠습니다.

사람 혹은 생명채라면 시각 데이터의 특정 부분에 위치적으로 중요하다 아니다를 판별할 수 있고, 이로써 판단의 중요한 근거로 사용하므로, 시각 신경 구조를 토대로 만들어진 CNN 의 Attention 개념을 이해한다면 보다 근본적인 비젼 어텐션이 가능해질 것이라 생각합니다.

 

(SEBlock(Squeeze-and-Excitation Block))

- 논문 : Squeeze-and-Excitation Networks (2017)

 

- SE Block 의 핵심 아이디어는 채널의 중요도를 표현하는 것에 있습니다.

쉽게 설명드리겠습니다.

CNN 은 KxK 크기의 커널을 통해 값의 위치적 특성에 집중하는 모델입니다.

C 개의 커널로 C 개의 위치적 특성을 뽑아내는 것이죠.

그런데, 위치적 특성이 모두 동등하게 최종 결과에 영향을 끼칠까요?

당연히 아닙니다.

추출된 특징 중 어떤 것은 결과에 영향이 클테지만 어떤것은 영향이 별로 없을 수도 있죠.

앞서 CNN 커널로 C 개의 형태적 특성들을 추출했다면, 중요한 값은 증폭시키고, 중요치 않은 값은 침묵시키는...

이런 개념이 SE Block 이고, 보시다시피 CNN 모델의 채널 단위 Attention 을 구하는 기법이라 볼 수 있습니다.

 

- SE Block 의 작업 프로세스는 아래와 같습니다.

1. 압축

입력 Feature 가 (B, C, H, W) 크기가 있다면, 이를 채널단위로 평균 풀링을 하여 압축하여 (B, C, 1, 1) 로 만듭니다.

즉, 채널별로 평균을 구하는 것이죠.

 

2. 중요도 검출

앞서 구한 (B, C, 1, 1) 을 펼치면, Batch 개수의 Channel 크기만큼의 벡터입니다.

이를 FC Layer Block(Fc -> Relu -> Fc -> Sigmoid) 에 넣어서 각 채널간 중요도를 검출하도록 합니다.

 

3. 중요도 반영

앞서 채널간 중요도를 구했으므로, 압축 하기 전의 입력 Feature 인 (B, C, H, W) 의 각 채널별로 중요도를 곱해줍니다.

이렇게 되면 중요한 채널은 강조되고, 덜 중요한 채널은 억제되어 결과 도출에 긍정적인 영향을 줍니다.

 

- 위와 같은 SE Block 은 가벼운 연산으로 채널간 중요도라는 개념을 반영할 수 있기에 매우 효과가 좋은 기법입니다.

구조 자체도 모듈 단위로 나누기 쉬운 뚜렷한 구조이므로 어느 CNN 모델에도 쉽게 적용이 가능하고요.

 

- SE Block 예시 코드

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

class SEBlock(nn.Module):
    def __init__(self, channels, reduction=16):
        super(SEBlock, self).__init__()
        self.fc1 = nn.Linear(channels, channels // reduction)
        self.fc2 = nn.Linear(channels // reduction, channels)

    def forward(self, x):
        b, c, h, w = x.size()
        z = F.adaptive_avg_pool2d(x, 1).view(b, c)  # Squeeze
        s = torch.sigmoid(self.fc2(F.relu(self.fc1(z)))).view(b, c, 1, 1)  # Excitation
        return x * s.expand_as(x)  # Scale

 

 

(CBAM (Convolutional Block Attention Module))

- 논문 : CBAM: Convolutional Block Attention Module (2018)

 

- SE Block 에서 발전한 개념의 CNN Attention 모듈입니다.

핵심적인 변화는,

어텐션 개념을 채널뿐 아니라 공간까지 확장했다는 것입니다.

즉, SE 보다 무겁지만 성능은 좋은 SE Block 의 개선 버전이라 생각하시면 됩니다.

 

- CBAM 은 두가지 단계로 구성됩니다.

1. 채널 어텐션

앞서 설명한 SE 의 채널 어텐션 개념과 동일합니다.

다른 점으로는, 어텐션 계산을 위한 겂을 AvgPool 뿐만 아니라, MaxPool 도 같이 사용한다는 것입니다.

참고로 평균 값은 데이터 전체적 평균값을 반영하기 위한 것이고, 최대 값은 가장 튀는 값의 정보를 반영하기 위한 것인데,

통계적 관점에서 봤을 때, 이상치가 될 수 있는 최대값보다는 분산값을 적용하는 것이 더 좋아보일수도 있지만, 어텐션에서는 강한 자극인 최대값이 더 효과적이라고 합니다.

 

어쨌건 채널간 두 풀링 값을 구하고, MLP 통과 후 Sigmoid 를 하여 채널간 어텐션 값을 구합니다.

class ChannelAttention(nn.Module):
    def __init__(self, in_planes, ratio=16):
        super(ChannelAttention, self).__init__()
        self.shared_mlp = nn.Sequential(
            nn.Linear(in_planes, in_planes // ratio),
            nn.ReLU(),
            nn.Linear(in_planes // ratio, in_planes)
        )

    def forward(self, x):
        b, c, h, w = x.size()
        avg_pool = torch.mean(x, dim=(2,3), keepdim=True).view(b, c)
        max_pool, _ = torch.max(x, dim=(2,3), keepdim=True)
        max_pool = max_pool.view(b, c)
        out = self.shared_mlp(avg_pool) + self.shared_mlp(max_pool)
        scale = torch.sigmoid(out).view(b, c, 1, 1)
        return x * scale

 

2. 공간 어텐션

앞서 채널 어텐션이 반영된 값을 받아 공간 단위 어텐션을 반영하는 과정입니다.

class SpatialAttention(nn.Module):
    def __init__(self, kernel_size=7):
        super(SpatialAttention, self).__init__()
        self.conv = nn.Conv2d(2, 1, kernel_size, padding=kernel_size//2)

    def forward(self, x):
        avg_pool = torch.mean(x, dim=1, keepdim=True)
        max_pool, _ = torch.max(x, dim=1, keepdim=True)
        concat = torch.cat([avg_pool, max_pool], dim=1)
        scale = torch.sigmoid(self.conv(concat))
        return x * scale

 

위에서 보시다시피 채널단위가 아닌 채널간의 평균과 최대값을 구해서(B, 1, H, W), 이를 합친 값(B, 2, H, W)을 선형 변환 후 sigmoid 로 중요도 값으로 변환하여 x 에 곱하는 것입니다.

채널간 어텐션과 다른점으로는, 선형 변환을 conv2d 로 하기 때문에, 전 구간을 순회하며 공간단위 어텐션을 구하는 것입니다.

그렇기에 커널 크기가 크면 큰 범위를 기준으로 판단하기에 정확도가 높아지지만 그만큼 연산량이 많아집니다.

 

- 위와 같은 두 어텐션을 조합한 CBAM 의 최종 코드는,

class CBAM(nn.Module):
    def __init__(self, channels):
        super(CBAM, self).__init__()
        self.channel_att = ChannelAttention(channels)
        self.spatial_att = SpatialAttention()

    def forward(self, x):
        x = self.channel_att(x)
        x = self.spatial_att(x)
        return x

 

위와 같이 단순합니다.

 

(ECA(Efficient Channel Attention))

- 논문 : ECA-Net: Efficient Channel Attention for Deep Convolutional Neural Networks (2020)

 

- SE 의 대표적인 단점인,

1. 두개의 FC 레이어를 사용함으로써 파라미터 수 증가

2. 전체 채널 관계를 학습하므로 복잡도 상승으로 인한 오버피팅 가능성 증가

이를 해결하기 위하여 보다 가벼운 채널 Attention 구조를 만들기 위해 고안된 채널 어텐션 기법입니다.

 

- 코드 구현

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

class ECABlock(nn.Module):
    def __init__(self, channels, k_size=3):
        """
        Args:
            channels (int): 입력 feature의 채널 수
            k_size (int): 1D convolution의 커널 크기 (보통 3, 5, 7 중 하나)
        """
        super(ECABlock, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)  # (B, C, 1, 1)
        self.conv = nn.Conv1d(1, 1, kernel_size=k_size, padding=(k_size - 1) // 2, bias=False)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        # x: (B, C, H, W)
        b, c, _, _ = x.size()
        y = self.avg_pool(x)              # (B, C, 1, 1)
        y = y.view(b, 1, c)               # (B, 1, C)
        y = self.conv(y)                  # (B, 1, C)
        y = self.sigmoid(y)              # (B, 1, C)
        y = y.view(b, c, 1, 1)           # (B, C, 1, 1)
        return x * y.expand_as(x)        # 채널별 attention 적용

 

코드상으로 파악했을 때,

SE 와 다른점으로는, FC 레이어가 사라지고, 인근 N개의 채널들과의 관계만을 단순한 conv 연산(1d conv)으로 구하여 sigmoid 로 확률화 한 것 뿐입니다.

확실히 모든 특징들에 대하여 연산을 수행하는 SE 보다 훨씬 가벼워 졌습니다.

저작자표시 비영리 변경금지 (새창열림)

'Study > Computer Vision' 카테고리의 다른 글

[딥러닝] Swin Transformer 정리 (Transformer 기반 컴퓨터 비전 백본, Window-based Self-Attention, Shifted Window)  (1) 2025.06.20
[딥러닝] EfficientNet V1, V2 정리 (Compound Scaling, NAS(Neural Architecture Search) 간단 소개, MB(Mobile Inverted Bottleneck)Conv + SE)  (1) 2025.06.20
[딥러닝] 이미지 특징 추출 CNN 모델 기법 정리  (0) 2025.06.12
[딥러닝] YOLO 시리즈 정리 v2~v4 (Word Tree, Feature Pyramid Network (FPN), PANet (Path Aggregation Network), SPP (Spatial Pyramid Pooling))  (5) 2025.06.10
[딥러닝] YOLO v1 정리 (1-stage 객체 탐지)  (0) 2025.06.09
'Study/Computer Vision' 카테고리의 다른 글
  • [딥러닝] Swin Transformer 정리 (Transformer 기반 컴퓨터 비전 백본, Window-based Self-Attention, Shifted Window)
  • [딥러닝] EfficientNet V1, V2 정리 (Compound Scaling, NAS(Neural Architecture Search) 간단 소개, MB(Mobile Inverted Bottleneck)Conv + SE)
  • [딥러닝] 이미지 특징 추출 CNN 모델 기법 정리
  • [딥러닝] YOLO 시리즈 정리 v2~v4 (Word Tree, Feature Pyramid Network (FPN), PANet (Path Aggregation Network), SPP (Spatial Pyramid Pooling))
Railly Linker
Railly Linker
IT 지식 정리 및 공유 블로그
  • Railly Linker
    Railly`s IT 정리노트
    Railly Linker
  • 전체
    오늘
    어제
  • 공지사항

    • 분류 전체보기 (106)
      • Programming (33)
        • BackEnd (18)
        • FrontEnd (2)
        • DBMS (1)
        • ETC (12)
      • Study (72)
        • Computer Science (20)
        • Data Science (17)
        • Computer Vision (16)
        • NLP (15)
        • ETC (4)
      • Error Note (1)
      • ETC (0)
  • 인기 글

  • 최근 글

  • 최근 댓글

  • 태그

    jvm 메모리 누수
    Kotlin
    단축키
    docker compose
    kotlin arraylist
    kotlin linkedlist
    localhost
    docker 배포
    unique
    list
    데이터베이스 제약
    network_mode: "host"
    논리적 삭제
    springboot 배포
    kotlin mutablelist
    지리 정보
    MacOS
  • 링크

    • RaillyLinker Github
  • hELLO· Designed By정상우.v4.10.0
Railly Linker
[딥러닝] CNN Attention 기법 정리(SE(Squeeze-and-Excitation), CBAM(Convolutional Block Attention Module), ECA(Efficient Channel Attention))
상단으로

티스토리툴바