AI 활용 소프트웨어 개발/AI, 머신러닝, 딥러닝

백본 특징 추출기, GAP, Attension Pooling , ContrastiveLoss

ha2yong 2025. 9. 4. 10:53

timm.create_model('resnet18', pretrained=True, num_classes=0) 이렇게 num_classes=0을 주면 마지막 분류용 FC 레이어(fully connected layer, classifier)가 제거되고, 특징 추출기(backbone) 로만 동작합니다.


동작 원리

  • 일반적으로 timm.create_model('resnet18', pretrained=True) 하면:
    • conv1 → bn1 → layer1~4 → global pooling → fc(num_classes 크기)
      이런 구조가 됩니다.
  • 그런데 num_classes=0을 주면 fc 레이어가 생성되지 않고, 마지막 global average pooling까지만 남습니다.
  • 따라서 출력은 [batch_size, feature_dim] 형태의 임베딩 벡터가 됩니다.
    • ResNet18의 경우 기본 feature dimension은 512.

 

나 궁금한거. 최종 feature map 7*7*512 의 shape 은 어떻게 2,512가 되는거야?

ChatGPT의 말:

좋은 질문이에요 👍 딱 CNN 백본에서 “flatten → pooling → feature vector” 로 넘어가는 핵심 부분입니다.


ResNet18 마지막 feature map shape

입력 크기가 (batch=2, 3, 224, 224) 라면:

  1. Conv + Pooling + Residual blocks 거친 후
    최종 feature map은
    (2, 512, 7, 7)
    즉, batch 2개 × channel 512 × 공간 크기 7×7.
  2. 이 상태에서 바로 classifier에 넣을 수 없으니, global pooling을 적용합니다.

Global Average Pooling (GAP)

timm에서는 num_classes=0일 때도 기본적으로 global_pool="avg" 가 적용돼요.

  • 각 채널별로 7×7 평균을 내서 1개의 값으로 압축합니다.
  • 따라서 (2, 512, 7, 7) → (2, 512, 1, 1) → squeeze → (2, 512).

즉, 공간 정보(7×7) 를 평균 내서 벡터화하는 겁니다.

 

gap를 통해서 압축형태이지만 공간적보는 유지한 feature map을 넘긴거구나

ChatGPT의 말:

맞습니다 👍 정확히 이해하셨어요.

다만 표현을 조금만 정리하면 좋아요:

  • (2, 512, 7, 7) → GAP → (2, 512)
  • 이 과정에서 **7×7의 공간적 분포 정보는 평균 연산으로 “압축”**되어 버려서, 최종 벡터는 채널 단위의 전역 요약(global summary)만 남습니다.
  • 즉, “어디에 무엇이 있는가(위치 정보)”는 사라지고,
    “이 채널에 어떤 패턴이 전반적으로 얼마나 강하게 나타났는가” 만 유지돼요.

그래서 GAP의 결과는 공간 구조를 버린 채널 요약 벡터입니다.


비유 🔎

  • (512개의 센서 × 7×7 그리드) = 지역별 측정치
  • GAP → 각 센서별 평균값만 남김
  • “센서별 평균값 벡터”가 바로 (batch, 512) 벡터

즉, 壓縮된 전역 표현(global descriptor) 이라서 분류기에는 적합하지만, 세밀한 위치정보를 활용하려는 경우(예: detection, segmentation)에는 flatten이나 다른 pooling을 씁니다.


👉 혹시 원하시는 게, Siamese 같은 임베딩 모델에서 GAP 말고 flatten(7×7=49개 공간 유지) 으로 넘겼을 때 장단점 비교도 필요하실까요?

나의 말:

혹시 원하시는 게, Siamese 같은 임베딩 모델에서 GAP 말고 flatten(7×7=49개 공간 유지) 으로 넘겼을 때 장단점 비교도 필요하실까요?

ChatGPT의 말:

좋은 포인트 잡으셨어요 👌
Siamese 네트워크 같은 임베딩 모델에서 GAP vs Flatten 은 성능과 표현력에서 차이가 크게 납니다.


🔹 GAP (Global Average Pooling) 사용

장점

  • 고정 길이 임베딩: 입력 크기가 달라도 항상 (batch, 512) 로 맞춰짐 → 학습과 비교가 쉬움.
  • 파라미터 수 감소: 공간 정보를 버려서 feature 차원이 작아짐 (512). 계산과 메모리 효율적.
  • Overfitting 억제: 위치 정보를 버리니 “전역적 패턴 요약”에 집중 → 소량 데이터일 때 유리.

단점

  • 공간 정보 손실: 위치/구조가 중요한 태스크(예: 얼굴 특징 비교, 세밀한 객체 구분)에는 불리.
  • 표현력이 제한적: 7×7의 세밀한 차이를 다 담을 수 없음.

🔹 Flatten (7×7=49 공간 유지 → 49×512 = 25088차원)

장점

  • 공간 정보 유지: (batch, 25088) 벡터에는 패턴이 어디에 나타났는지도 포함됨.
  • 구조적 차이 학습 가능: 두 이미지가 같은 패턴이라도 위치 차이가 있다면 구분할 수 있음.
  • 세밀한 비교에 유리: 얼굴 verification, 세밀한 문양 구분 같은 태스크에서 성능 개선 가능.

단점

  • 고차원 벡터: (512×7×7=25088) → 계산량/메모리 급증.
  • Overfitting 위험: 데이터가 적으면 불필요한 공간 정보까지 외워버림.
  • 일반화 성능 저하 가능성: 위치 변화(translation, rotation)에 민감.

🔹 결론 (Siamese 모델 관점)

  • GAP 기반 (512차원): 효율적이고, 비교 임베딩으로 안정적 → 얼굴/서명 인식 같은 전역 패턴 중심 태스크에 적합.
  • Flatten 기반 (25088차원): 더 풍부한 정보를 담지만 과적합·계산비용 크다 → 데이터 충분하고 세밀한 구조 비교가 중요한 경우에 적합.

👉 보통 실무에서는

  1. 기본은 GAP (512차원) 으로 가고,
  2. Flatten 대신 Attention Pooling / R-MAC / GeM pooling 같은 “강화된 풀링 기법”을 쓰기도 합니다.

 

Attention Pooling은 트랜스포머의 어텐션 기법처럼 이미지를 쪼개서 포지셔널 임베딩하면서 특징을 병렬로 전역의 관계를 파악하는 풀링이니?

ChatGPT의 말:

와 😃 정확히 감을 잡으셨어요. “어텐션 풀링”은 단순히 평균이나 최대값을 취하는 대신, 트랜스포머의 self-attention 아이디어를 활용해서 어떤 공간(feature map의 어느 위치)이 중요한지 가중치를 학습적으로 부여하는 풀링입니다.


🔹 Global Average Pooling (GAP) vs Attention Pooling

  • GAP: 각 채널에서 공간 위치별 값을 단순 평균 → 모든 위치가 동일하게 기여.
  • Attention Pooling: 공간 위치별 중요도를 학습 → 중요한 위치는 크게, 덜 중요한 위치는 작게 반영.

즉, “어디를 보아야 하는지”를 학습하는 게 핵심입니다.

 

🔹 포지셔널 임베딩

맞습니다 👍
트랜스포머와 마찬가지로, feature map은 위치 정보가 사라지기 때문에 positional embedding을 더해주면 성능이 더 좋아집니다.

  • 예: sinusoidal positional encoding, 2D learnable embedding.
  • 이렇게 하면 attention이 단순히 “무엇”뿐 아니라 “어디”에도 민감해져요.

🔹 장점

  • ✅ GAP보다 더 풍부하고 task-adaptive한 표현 → 중요한 공간 패턴 강조 가능.
  • ✅ Flatten처럼 고차원이 되지 않고, 출력은 (B, C)로 깔끔하게 유지.
  • ✅ Transformer block과 유사해 확장성 좋음.