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 크기)
이런 구조가 됩니다.
- conv1 → bn1 → layer1~4 → global pooling → fc(num_classes 크기)
- 그런데 num_classes=0을 주면 fc 레이어가 생성되지 않고, 마지막 global average pooling까지만 남습니다.
- 따라서 출력은 [batch_size, feature_dim] 형태의 임베딩 벡터가 됩니다.
- ResNet18의 경우 기본 feature dimension은 512.
ChatGPT의 말:
좋은 질문이에요 👍 딱 CNN 백본에서 “flatten → pooling → feature vector” 로 넘어가는 핵심 부분입니다.
ResNet18 마지막 feature map shape
입력 크기가 (batch=2, 3, 224, 224) 라면:
- Conv + Pooling + Residual blocks 거친 후
최종 feature map은
(2, 512, 7, 7)
즉, batch 2개 × channel 512 × 공간 크기 7×7. - 이 상태에서 바로 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) 를 평균 내서 벡터화하는 겁니다.
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개 공간 유지) 으로 넘겼을 때 장단점 비교도 필요하실까요?
나의 말:
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차원): 더 풍부한 정보를 담지만 과적합·계산비용 크다 → 데이터 충분하고 세밀한 구조 비교가 중요한 경우에 적합.
👉 보통 실무에서는
- 기본은 GAP (512차원) 으로 가고,
- Flatten 대신 Attention Pooling / R-MAC / GeM 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과 유사해 확장성 좋음.
'AI 활용 소프트웨어 개발 > AI, 머신러닝, 딥러닝' 카테고리의 다른 글
| 머신러닝 / Pipeline / ColumnTransformer / GridSearchCV (0) | 2025.11.18 |
|---|---|
| ONNX (Open Neural Network Exchange) (0) | 2025.09.15 |
| CNN 구조 안에서 커널(kernel), 스트라이드(stride), 채널(channel), MaxPooling, 다운샘플링(downsampling), Fully Connected Layer의 의미, 그리고 실제 계산 (5) | 2025.08.18 |
| Local GPU (Vscode) 환경 설정 및 사용하기 (0) | 2025.08.13 |
| YOLO 하이퍼파라미터 조정하기 (yaml 파일) (3) | 2025.08.11 |