ResNet 재조명: 향상된 훈련 및 스케일링 전략
학습 방법이 모델 아키텍처 변경보다 더 중요할까? 이 글에서는 ResNet-RS 논문을 깊이 살펴보며 이 질문에 답해 보려 합니다. 이 글은 AI 번역본입니다. 오역 가능성이 있다면 댓글로 자유롭게 알려 주세요.
Created on September 15|Last edited on September 15
Comment
논문 | GitHub | 모델 체크포인트
소개
이상으로 6만 3천 회 인용, 레즈넷 오늘날에도 컴퓨터 비전(CV) 연구의 최전선에 있어 왔습니다. 최근의 대부분 CV 논문은 정확도, 속도, 혹은 둘 다에서의 향상을 보여주기 위해 결과를 ResNet과 비교합니다.
예를 들어, EfficientNet-B4 ResNet-50와 유사한 FLOPs를 가진 아키텍처가 top-1 ImageNet 정확도를 76.3%에서 83.0%까지 향상시켰습니다! [참고자료]
❓: 하지만 ImageNet top-1 정확도의 이러한 향상은 모델 아키텍처에서 비롯된 것일까요, 아니면 개선된 학습 및 스케일링 전략?
바로 이 질문이 Bello 등(2021)은 최근 논문에서 이 질문에 답하려고 시도합니다 ResNet 다시 보기: 개선된 학습 및 스케일링 전략. 그 과정에서 이들은 재스케일된 ResNet 아키텍처의 새로운 계열을 소개하는데, 이는 ResNet-RS!
왜 이 블로그를 읽어야 할까요?
원문 논문을 그냥 다운로드해서, 필요하면 출력해 읽으면 되지 않을까요? 이렇게 하지 말아야 할 이유 4가지를 소개합니다:
- 이 블로그의 일환으로, 우리는 새로운 ResNet-RS 이 블로그 글은 원 논문에서 생략되었을 수 있는 개념들의 맥락과 역사까지 포함해 아키텍처를 독자들에게 설명함으로써, 초보자에게도 더 친절한 형태로 제공합니다.
- 각 항목마다 해당 논문, 설명, 그리고 블로그로 연결되는 링크를 함께 제공했습니다. 훈련 및 정규화 전략 논문에서 언급된 예시로는 모델 EMA, 라벨 스무딩, 스토캐스틱 깊이, RandAugment, 드롭아웃그리고 더 많은 내용!
사전 준비 사항
ResNet-RS 아키텍처에서 제안된 구조적 변경 사항을 완전히 이해하려면, 독자들이 ResNet 아키텍처에 대해 충분히 이해하고 있는 것이 좋습니다.
제14장 of 딥러닝 실전 가이드: Fastai와 PyTorch로 만드는 AI 애플리케이션 (박사 학위 없이도) 작성자 제러미 하워드 그리고 실뱅 귀게르 는 다음 내용을 배우기에 훌륭한 자료입니다 레즈넷!
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 학습 레시피에 대한 누적 추가 실험. 위에서 보라색, 초록색, 노란색은 각각 학습 방법, 정규화 방법, 그리고 아키텍처 개선을 의미합니다.
위의 표-1에서 학습 방법과 정규화 방법은 각각 보라색과 초록색으로 표시되어 있으며, top-1 정확도에 대한 각 방법의 기여도도 함께 제시되어 있습니다.
✅: 표-1에서 주목할 점은, 학습 에폭을 늘리면 top-1 정확도가 실제로는 -0.5% 감소하지만, 논문에 따르면 정규화 기법들을 함께 사용할 때에만 에폭 증가가 유효하다는 것입니다. 그렇지 않으면 과적합으로 이어집니다.
이제 아래에서 각 학습 및 정규화 전략을 자세히 살펴보겠습니다.
정규화 전략
가중치의 EMA
여기서 가중치의 EMA는 무엇을 의미하나요? EMA는 지수 이동 평균을 뜻합니다.
❓: 지수 이동 평균이란 무엇인가요?
예를 들어, 아담이 레모네이드를 판다고 해봅시다. 1일 차에는 레모네이드 5잔을 팔았고, 2일 차에는 3잔을 팔았습니다.
그렇다면 이틀 동안 그가 판 레모네이드의 평균 판매량은 다음과 같습니다. .
한편, 감쇠 계수가 0.99라면, 지수 이동 평균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)
👉: 이제 독자 여러분이 위에서 공유한 지수 이동 평균(Exponential Moving Average)의 정의와 구현을 직접 매핑해 보시기 바랍니다. 질문이 있거나, CV에서의 정규화 전략 맥락에서 EMA가 잘 이해되지 않는다면 언제든지 저에게 연락하거나 이 보고서 끝에 댓글을 남겨 주세요.
레이블 스무딩
❓: 레이블 스무딩이란 무엇인가요?
✅: Microsoft Excel로 이해하는 Label Smoothing Microsoft Excel을 사용해 레이블 스무딩을 아주 명확하게 설명한 훌륭한 블로그 글입니다! 레이블 스무딩에 대한 완전한 입문을 위해 독자 여러분께 그 블로그 글을 참고하시길 권합니다.
스토캐스틱 데pth
그래서 표-1에 따르면, 스토캐스틱 데pth는 top-1 정확도를 약 +0.2% 향상시킵니다. 그런데 스토캐스틱 데pth란 무엇일까요? 그리고 어떻게 구현할 수 있을까요? 이 섹션에서는 이러한 질문에 답해 보겠습니다.
❓: 스토캐스틱 데pth란 무엇인가요?

그림-2: 생존 확률의 선형 감소 스토캐스틱 데pth를 적용한 ResNet에서 =1 및 = 0.5.
이 아이디어는 그림-2에 제시되어 있습니다. 각 단계에는 잔차 경로(노란색)와 아이덴티티 경로가 있습니다. 스토캐스틱 데pth는 블록의 “생존” 확률에 따라 전체 잔차 경로의 출력을 무작위로 드롭합니다. 드롭 패스는 잔차 분기에서 가끔 열리거나 닫히는 게이트로 볼 수 있습니다. 게이트가 열려 있으면 출력이 통과되고, 블록은 원래 블록과 동일하게 동작합니다. 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 dropout)”은 아주 훌륭하게 설명되어 있습니다. 여기 에서 스탠퍼드의 CS231n 강의.
RandAugment
❓: RandAugment이란 무엇인가요?
✅: RandAugment는 처음으로 다음에서 소개되었습니다 RandAugment: 검색 공간을 줄인 실용적인 자동 데이터 증강 그리고 timm 문서의 일부로 설명되어 있습니다 여기.
드롭아웃
❓: 드롭아웃이란 무엇인가요?
✅: 독자 여러분께 다음 자료를 참고하시길 권합니다 정규화 섹션 의 CS231n: 시각 인식을 위한 합성곱 신경망엔 스탠퍼드의 강좌에서 더 자세한 정보를 확인해 보세요 드롭아웃.
가중치 감쇠 감소
저자들이 언급한 마지막 변경 사항 중 하나는 가중치 감쇠를 줄이는 것이었습니다.

표-2: 더 강한 정규화를 사용할수록 가중치를 더 작게 설정. 드롭아웃(DO), 확률적 깊이(SD), 라벨 스무딩(LS), RandAugment(RA) 등 정규화 방법을 조합했을 때의 다양한 정규화 설정에 대한 ImageNet 탑-1 정확도. 이미지 해상도는 ResNet-50에 224×224, ResNet-200에 256×256.
위의 표-2에서 보이듯, RandAugment와 label smoothing을 사용할 때는 기본 weight decay 값인 1e-4를 변경할 필요가 없습니다. 하지만 여기에 dropout 및/또는 stochastic depth를 추가하면, weight decay를 더 낮추지 않는 한 성능이 떨어질 수 있습니다. 직관적으로, weight decay는 정규화 역할을 하므로 여러 기법을 함께 사용할 때 과도한 정규화를 피하려면 그 값을 줄여야 한다는 뜻입니다.
학습 전략
저자들이 탑-1 정확도를 높이는 데 유용하다고 확인한 두 가지 주요 학습 전략은 다음과 같습니다 -
- 더 많은 에포크 동안 학습하세요(350에포크)
코사인 학습률 감쇠
❓: 코사인 학습률 감쇠란 무엇인가요?
✅: 친애하는 독자 여러분께 이렇게 권하고 싶습니다: "학습률을 다루는 방식 개선하기소개를 위해 Vitaly Bushaev의 글을 참고하세요 SGDR: 워밍 리스타트를 사용하는 확률적 경사 하강법.
ResNet-RS 아키텍처
지금까지 우리는 기본 ResNet의 top-1 정확도를 79.0%에서 82.2%로 끌어올리는 데 도움이 된 학습 및 정규화 전략을 살펴보았습니다. 아키텍처를 전혀 변경하지 않고도하지만 저자들은 소폭의 아키텍처 변경도 도입해 top-1 정확도를 83.4%까지 끌어올렸습니다! 이 섹션에서는 그러한 아키텍처 변경을 자세히 살펴보겠습니다.
본질적으로 저자들은 모든 병목 블록에 ResNet-D 수정과 Squeeze-and-Excitation(SE)을 도입했습니다.
스퀴즈 앤드 엑사이트이션
❓: 그렇다면 스퀴즈 앤드 엑사이트이션은 무엇을 의미하나요?
✅: 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 PyTorch에서의 모델 TIMM 그리고 다음에 대해 학습하고 Imagenette 데이터셋은 제공된 아래 텍스트:
ResNet-RS 모델 구현을 포함한 Colab 노트북
결론
이 블로그를 통해 독자 여러분께 ResNet-RS 아키텍처를 소개할 수 있었기를 바랍니다. 아래에 자유롭게 댓글을 남겨 주세요. 이 논문과 관련한 피드백을 듣거나 궁금한 점에 답변해 드리고 싶습니다. 읽어 주셔서 감사합니다!
Add a comment