ResNet 다시 보기: 향상된 학습과 스케일링 전략
학습 방법이 모델 구조 변경보다 더 중요할까? 이 글에서는 ResNet-RS 논문을 자세히 살펴보며 이 질문에 답해 보려고 합니다. 이 글은 AI 번역본입니다. 오역이 있을 경우 댓글로 알려 주세요.
Created on September 15|Last edited on September 15
Comment
논문 | GitHub | 모델 체크포인트
소개
이상으로 인용 63,000회, ResNet 오늘날에도 컴퓨터 비전(CV) 연구의 최전선에 서 왔습니다. 최근의 대부분 CV 논문은 정확도, 속도, 혹은 둘 다에서의 개선을 보여 주기 위해 결과를 ResNet과 비교합니다.
예를 들어, EfficientNet-B4 ResNet-50와 유사한 FLOPs를 가진 아키텍처가 ImageNet top-1 정확도를 76.3%에서 83.0%로 향상시켰습니다! [참고문헌]
❓: 하지만 ImageNet top-1 정확도의 이러한 향상이 모델 아키텍처에서 비롯된 것일까요, 아니면 향상된 학습 및 스케일링 전략?
바로 이 질문이 Bello 등(2021)은 최근 논문에서 이에 대한 답을 찾고자 합니다. ResNet 재고찰: 향상된 학습 및 스케일링 전략이 과정에서 그들은 재스케일된 ResNet 아키텍처의 새로운 계열도 소개하는데, 이를 다음과 같이 부릅니다 ResNet-RS!
이 블로그를 왜 읽어야 할까요?
원문 논문을 그냥 내려받아 인쇄해서 읽으면 되지 않을까요? 이렇게 하지 말아야 할 이유 4가지는 다음과 같습니다:
- 이 블로그의 일환으로, 우리는 새로운 ResNet-RS 원래 논문에서 건너뛰었을지도 모를 개념들의 배경과 역사까지 모두 담아, 독자들에게 해당 아키텍처를 친절하게 소개합니다. 이를 통해 이 블로그 글은 초보자도 이해하기 쉽게 구성됩니다.
- 각 항목에 해당하는 논문, 설명, 블로그로 연결되는 링크를 함께 제공했습니다 훈련 및 정규화 전략 논문에서 언급된 예로는 모델 EMA, 라벨 스무딩, 확률적 깊이, RandAugment, 드롭아웃, 그리고 더 많은 것들!
사전 준비사항
ResNet-RS에서 제안된 구조적 변경 사항을 완전히 이해하려면, 독자들이 먼저 ResNet 아키텍처에 대해 충분히 숙지하고 있는 것이 좋습니다.
제14장 Fastai와 PyTorch로 배우는 딥러닝: 박사 학위 없이 만드는 AI 애플리케이션 작성자 제러미 하워드 그리고 실뱅 구제르 은(는) 다음 내용을 학습하는 데 훌륭한 자료입니다 ResNet!
ResNet-RS
소개를 마쳤으니 이제 본격적으로 살펴보겠습니다. 이 섹션에서는 다음과 같은 핵심 질문들에 답해 보겠습니다:
- 이 논문의 핵심 기여는 무엇인가요?
- 개선된 학습 전략은 무엇인가요?
- 모델 아키텍처 개선과 비교했을 때, 학습 및 스케일링 전략은 성능을 얼마나 향상시키나요?
- 저자들은 ResNet-RS를 학습할 때 어떤 데이터 증강 기법을 사용했나요? 그리고 이러한 기법들이 ImageNet top-1 성능 향상에 어떻게 기여하나요?

그림 1: ResNet을 최첨단 성능으로 끌어올리기. ResNet-RS 아키텍처는 속도–정확도 파레토 곡선에서 EfficientNet을 능가하며, TPU에서 1.7x–2.7x, GPU에서 2.1x–3.3x의 속도 향상을 보인다. ResNet*은 256×256 이미지 해상도로 ImageNet에서 학습된 ResNet-200 아키텍처를 의미한다.
개인적으로 이 그림을 해석할 때는 ResNet 아키텍처(초록 점)를 중심으로 살펴보는 방식을 선호합니다. With 향상된 학습 및 정규화 전략 (이 글의 뒤에서 다루겠지만) 저자들은 top-1 정확도를 다음과 같이 끌어올릴 수 있었습니다 79.0% 까지 82.2%, 아키텍처 변경 없이추가적인 소규모 아키텍처 수정(이 글의 뒤에서 역시 다룹니다)을 통해, 저자들은 top-1 정확도를 더 높여�� 다음과 같이 끌어올릴 수 있었습니다 83.4%!
❓: 그렇다면 구체적으로 어떤 학습 방법과 아키텍처 변경이 있었나요?
그럼 이제 하나씩 살펴보겠습니다!
개선된 학습 및 정규화 기법
이 섹션에서는 ImageNet top-1 정확도를 79.0%에서 82.2%로 끌어올린 최신 학습 및 정규화 기법을 살펴봅니다. 아키텍처 변경 없이.

표 1: ResNet-RS 학습 레시피에 대한 누적적(Additive) 연구. 위의 보라색, 초록색, 노란색은 각각 학습 기법, 정규화 기법, 아키텍처 개선을 나타냅니다.
위의 표 1에서 학습 기법과 정규화 기법은 각각 보라색과 초록색으로 표시되어 있으며, top-1 정확도에 대한 각 기법의 기여도도 함께 제시되어 있습니다.
✅: 표 1에서 주목해야 할 핵심 포인트는, 학습 에폭을 늘리면 top-1 정확도가 실제로는 -0.5% 낮아지지만, 논문에서는 정규화 기법을 함께 적용할 때에만 에폭 증가가 유의미하다고 보고했다는 점입니다. 그렇지 않으면 오버피팅으로 이어집니다.
이제 아래에서 각 학습 기법과 정규화 전략을 하나씩 자세히 살펴보겠습니다.
정규화 전략
가중치의 EMA
여기서 말하는 가중치의 EMA는 무엇을 의미하나요? EMA는 지수이동평균을 뜻합니다.
❓: 지수이동평균이란 무엇인가요?
예를 들어, 아담이 레모네이드를 판다고 해봅시다. 1일 차에는 레모네이드를 5잔 팔았고, 2일 차에는 3잔을 팔았습니다.
그렇다면 이틀 동안 그가 판매한 레모네이드의 평균 잔수는 다음과 같습니다 .
한편, 감쇠 계수가 0.99라면, the 지수이동평균e는 .
✅ 최근 데이터에 더 높은 가중치를 부여하는 것이 바로 지수이동평균입니다.
❓: 그렇다면 ResNet-RS에서 정규화 전략을 개선한다는 맥락에서 EMA는 무엇을 의미하나요?
간단히 말해, 모델 가중치에 대해 지수이동평균을 적용한다는 뜻입니다. 즉, 마지막 에포크의 가중치에 더 높은 중요도를 부여하면서도, 이전 에포크들의 가중치도 일정 비율로 반영합니다.
❓: PyTorch에서 EMA는 어떻게 구현하나요?
class ModelEMA(nn.Module):def __init__(self, model, decay=0.9999, device=None):super(ModelEmaV2, self).__init__()# make a copy of the model for accumulating moving average of weightsself.module = deepcopy(model)self.module.eval()self.decay = decayself.device = device # perform ema on different device from model if setif self.device is not None:self.module.to(device=device)def _update(self, model, update_fn):with torch.no_grad():for ema_v, model_v in zip(self.module.state_dict().values(), model.state_dict().values()):if self.device is not None:model_v = model_v.to(device=self.device)ema_v.copy_(update_fn(ema_v, model_v))def update(self, model):self._update(model, update_fn=lambda e, m: self.decay * e + (1. - self.decay) * m)def set(self, model):self._update(model, update_fn=lambda e, m: m)
PyTorch에서 모델 가중치에 EMA를 적용하려면, 주어진 어떤 모델이든 다음과 같이 래핑하면 됩니다 ModelEMA 위에 공유한 클래스를 사용하고, 학습 중에는 다음을 호출하세요 model.update() 다음과 같이 모델 가중치의 EMA를 구합니다:
train_dataset, eval_dataset = create_datasets()train_dataloader, eval_dataloader = create_dataloaders()model = create_model()# wrap model in ModelEMA classema_model = ModelEMA(model)for epoch in EPOCHS:batch = next(iter(train_dataloader))loss = model(**batch)loss.backward()# apply EMA to model weightsema_model.update(model)
👉: 이제 독자 여러분이 위에서 공유한 지수이동평균(EMA)의 정의와 구현을 스스로 대응시켜 보시기 바랍니다. 질문이 있거나, CV의 정규화 전략 맥락에서 EMA가 잘 이해되지 않는다면 언제든지 저에게 연락하시거나 이 보고서 말미에 댓글을 남겨 주세요.
라벨 스무딩
❓: 라벨 스무딩이란 무엇인가요?
✅: Microsoft Excel로 설명하는 라벨 스무딩 Microsoft Excel을 사용해 라벨 스무딩을 설명한 훌륭한 블로그 글입니다! 라벨 스무딩에 대한 완전한 소개는 그 블로그 글을 참고하시길 바랍니다.
스토캐스틱 데pth
표 1에 따르면, 스토캐스틱 데프는 top-1 정확도를 약 +0.2% 정도 향상시킵니다. 그런데 스토캐스틱 데프란 무엇일까요? 또, 어떻게 구현할 수 있을까요? 이 절에서는 이러한 질문에 답해 보겠습니다.
❓: 스토캐스틱 데프란 무엇인가요?

그림 2: 생존 확률의 선형 감소 스토캐스틱 데프를 적용한 ResNet에서 =1 및 = 0.5
이 아이디어는 그림 2에 제시되어 있습니다. 각 단계마다 잔차 경로(노란색)와 아이덴티티 경로가 있습니다. 스토캐스틱 데프는 블록의 “생존” 확률에 따라 전체 잔차 경로의 출력을 무작위로 드롭합니다. 드롭 패스는 잔차 분기 위에 달린 게이트처럼 볼 수 있으며, 때때로 열리거나 닫힙니다. 게이트가 열려 있으면 출력이 통과하고, 블록은 원래 블록과 동일하게 동작합니다. ResNet 연구 논문.
독자께서는 다음을 참고하시기 바랍니다 논문 자세한 내용은 다음을 참고하세요.
❓: PyTorch에서 Stochastic Depth를 구현하는 방법은?
def drop_path(x, drop_prob: float = 0., training: bool = False):if drop_prob == 0. or not training:return xkeep_prob = 1 - drop_probshape = (x.shape[0],) + (1,) * (x.ndim - 1) # work with diff dim tensors, not just 2D ConvNetsrandom_tensor = keep_prob + torch.rand(shape, dtype=x.dtype, device=x.device)random_tensor.floor_() # binarizeoutput = x.div(keep_prob) * random_tensorreturn outputclass DropPath(nn.Module):def __init__(self, drop_prob=None):super(DropPath, self).__init__()self.drop_prob = drop_probdef forward(self, x):return drop_path(x, self.drop_prob, self.training)
👉: 독자께서 Stochastic Depth의 정의와 구현을 직접 대응해 보시길 권하지만, 아래에서 짧게 답하고 싶은 질문이 하나 있습니다.
❓: 입력을 왜 나누나요? x 에서 drop_path 위의 함수에서 …로 keep_prob?
이는 드롭아웃과 유사하게 입력 활성값을 스케일링하되, 대신 학습 중에 적용하기 위한 것입니다. 이러한 “역(inverted) 드롭아웃”에 대해서는 아주 훌륭한 설명이 있습니다. 여기 에서 스탠퍼드의 CS231n 강의.
RandAugment
❓: RandAugment이란 무엇인가요?
✅: RandAugment은 처음으로 다음에서 소개되었습니다 RandAugment: 검색 공간을 줄인 실용적인 자동 데이터 증강 그리고 timmdocs의 일부로 설명되어 있습니다 여기.
드롭아웃
❓: 드롭아웃이란 무엇인가요?
가중치 감쇠 감소
저자들이 언급한 마지막 변화 중 하나는 weight decay를 낮추는 것이었습니다.

표 2: 더 강한 정규화를 사용할수록 가중치 감쇠를 줄이세요. 드롭아웃(DO), 스토캐스틱 데프(SD), 라벨 스무딩(LS), RandAugment(RA) 등 정규화 기법을 조합했을 때의 다양한 정규화 설정별 ImageNet top-1 정확도. 이미지 해상도는 ResNet-50에는 224×224, ResNet-200에는 256×256입니다.
위의 표 2에서 보이듯이, RandAugment와 label smoothing을 사용할 때는 기본 weight decay 값인 1e-4를 변경할 필요가 없습니다. 그러나 여기에 dropout 및/또는 stochastic depth를 추가하면, weight decay를 더 낮추지 않는 한 성능이 떨어질 수 있습니다. 직관적으로, weight decay가 정규화 기법으로 작용하므로 여러 기법을 함께 사용할 때 모델이 과도하게 정규화되지 않도록 그 값을 낮춰야 합니다.
훈련 전략
저자들이 top-1 정확도를 높이는 데 유용하다고 확인한 두 가지 주요 훈련 전략은 다음과 같습니다 —
- 더 많은 에폭 동안 훈련하세요(350에폭)
코사인 학습률 감쇠
❓: 코사인 학습률 감쇠란 무엇인가요?
✅: 사랑하는 독자 여러분께 이렇게 권하고 싶습니다: "학습률을 다루는 방식을 개선하기비탈리 부샤예프의 입문 자료를 참고하세요 SGDR: 웜 리스타트를 사용하는 확률적 경사 하강법.
ResNet-RS 아키텍처
지금까지 우리는 기본 ResNet의 top-1 정확도를 79.0%에서 82.2%로 끌어올리는 데 도움이 된 학습 및 정규화 전략을 살펴보았습니다. 아키텍처 변경 없이하지만 저자들은 소폭의 아키텍처 변경도 도입해 top-1 정확도를 83.4%까지 끌어올렸습니다! 이번 섹션에서는 그 아키텍처 변경 사항을 자세히 살펴보겠습니다.
본질적으로 저자들은 모든 보틀넥 블록에 ResNet-D 수정과 Squeeze-and-Excitation(SE)을 도입했습니다.
스크위즈 앤드 엑사이트레이션
❓: 그렇다면 Squeeze-and-Excitation은 무엇을 의미하나요?
✅: Squeeze-and-Excitation 네트워크의 개념을 완전히 이해하고 PyTorch 코드 구현까지 확인하려면 다음을 참고하세요 PyTorch 구현과 함께 알아보는 Squeeze-and-Excitation 네트워크.
ResNet-D
- 다운샘플링 블록의 잔차 경로에서 처음 두 합성곱의 스트라이드 크기를 서로 바꿉니다.
- 다운샘플링 블록의 스킵 연결 경로에 있는 스트라이드 2의 1×1 합성곱을, 먼저 스트라이드 2의 2×2 평균 풀링으로 바꾸고 그다음 스트라이드가 없는 1×1 합성곱으로 대체합니다.
- 스트라이드 2의 3×3 최대 풀링 레이어를 제거하고, 다음 병목 블록의 첫 번째 3×3 합성곱에서 다운샘플링이 이루어지도록 합니다.
이러한 수정 사항을 바탕으로, 업데이트된 아키텍처는 이제 다음과 같습니다:

그림 3: ResNet-RS 아키텍처 다이어그램. 출력 크기는 224×224 입력 이미지 해상도를 가정합니다. × 기호는 ResNet-101 아키텍처에서 해당 블록이 반복되는 횟수를 의미합니다.
이제 소개한 아키텍처 변경 사항들이 독자 여러분께 잘 와닿았기를 바랍니다. 다음 단계에서는 TIMM을 사용해 PyTorch에서 직접 구현해 보겠습니다. 궁금한 점이 있으시면 언제든지 연락 주시거나, 이 보고서 마지막에 댓글로 남겨 주세요.
PyTorch에서의 ResNet-RS
ResNet-RS 모델 구현을 위한 Colab 노트북
결론
이 블로그를 통해 소중한 독자 여러분께 ResNet-RS 아키텍처를 잘 소개해 드렸기를 바랍니다. 아래 댓글로 자유롭게 의견을 남겨 주세요. 이 논문과 관련된 피드백이나 질문에 기꺼이 답변드리겠습니다. 읽어 주셔서 감사합니다!
Add a comment