아직도 선선한 날씨가 계속되는 5월 중순이다. 사실 하루는 반바지를 입고 나갔던 적도 있었지만, 저번 주처럼 비가 한 두 번 오더니 계속 더위를 늦추고 있다. 나는 비를 썩 좋아하지 않는다. 출퇴근 시간대에 대중교통을 이용하는 나에게 우산은 엄청난 짐이다. 그러나 비가 갠 다음 날 바깥에 나가서 불어오는 시원한 바람을 맞고 있자면, 1호선 안에서 여러 젖은 우산들과 부대끼던 날을 잊게 해준다. 나는 비를 좋아했던 걸 지도 모르겠다. 어쨌든 이런 선선한 날씨가 계속 이어졌으면 좋겠다.
💻 What?
이번 주로 딥러닝 기초 강의가 끝났다. 이번 주에 배운 내용들은 대부분 하이퍼파라미터에 대한 내용들이다. 머신러닝의 하이퍼파라미터들은 모델 객체를 생성할 때 파라미터의 형식으로 지정헤주는 방식이었다면, 딥러닝은 모델 객체를 정의하는 방법 자체가 하이퍼파라미터인 느낌이다. Batch Normalization, Dropout 등 여러가지 최적화 기법들도 배웠다.
class model1(nn.Module):
def __init__(self):
super().__init__()
self.layer_1 = nn.Linear(50, 64)
self.layer_2 = nn.Linear(64, 32)
self.layer_3 = nn.Linear(32, 10)
self.a1 = nn.ReLU()
def forward(self, X)
X = self.layer_1(X)
X = self.a1(X)
X = self.layer_2(X)
X = self.a1(X)
return self.layer_3(X)
목요일부터 금요일 이틀 간은 두 번째 미니 프로젝트 기간이었다. “이탈 예측”이라는 대주제에서 특정 주제로 구체화한 뒤 팀원들과 탐색적 데이터 분석, 전처리, 베이스라인 모델 학습 및 성능 평가, 베스트 모델 하이퍼파라미터 튜닝 및 성능 평가, 결과 해석이라는 일련의 과정을 수행했다.
😮 So What?
1. 하이퍼파라미터의 향연
이번 주 수업을 통해 딥러닝 모델은 사용자가 직접 손을 대야 하는 부분이 머신러닝에 비해 현저히 많다는 것을 느꼈다. 딥러닝 기본 강의를 시작했을 때 강사님이 전통적인 머신러닝과 딥러닝의 차이를 말씀해주셨던 것이 기억난다.
Feature Extraction의 측면에서 보면, 기존 머신러닝 모델들은 주어진 데이터에서 중요한 특징이 무엇인지 정의하고 이들을 추출하는 과정을 도메인 지식과 데이터의 특성을 바탕으로 사람이 수작업(기술통계량, PCA 등)으로 진행하는 반면, 딥러닝은 이러한 것들을 모델이 알아서 다 해준다.
모델이 다 해준다는 말은, 데이터의 양과 모델 구조가 중요하다는 말이다. 이 모델 구조가 딥러닝에서 사람이 손수 정의해야 하는 부분인데, 모델이 Feature Extraction까지 맡아서 수행하는 딥러닝 특성 상 모델 구조를 정의하는 하이퍼파라미터가 머신러닝에 비해 현저히 많다. 지난 주에는 Learning Rate, Batch Size, Epochs, Loss Function, Optimizer, Layer 수, Unit 수, Activation Function 등 모델 구조와 학습(연산) 관련 기초 하이퍼파라미터들에 대해 배웠다면, 이번 주에는 넓은 의미의 하이퍼파라미터에 대해 배웠다고 할 수 있겠다.
- Dropout
너무 복잡한 신경망 기반 모델이 Overfit 되지 않도록 규제를 걸어주는 방법이다. 모델을 설계할 때 Dropout을 0과 1 사이의 확률값으로 입력하면 모델은 모든 유닛에 대해 해당 확률을 기반으로 학습을 비활성화하는 독립 시행을 실시한다. 이 과정은 매 배치마다 반복되기 때문에, 이전 배치에서 off였던 유닛들은 on이 될 수도 있고, 그 역도 가능하다. 또한 비율이 아닌 확률이기에, 가령 유닛이 30개인 모델에 Dropout을 0.3으로 설정한다면 매 배치마다 꼭 off인 유닛이 9개라는 보장은 없다.
모든 유닛들은 weight가 update되는 속도도, weight가 학습 및 추론 성능에 미치는 영향도 상이하다. 그래서 특정 유닛은 동일한 Batch Size로 동일한 Epochs를 학습하는 동안 다른 유닛에 비해 Overfitting 혹은 Underfitting에 더 많이 기여할 수도 있는데, Dropout은 이런 유닛들이 남들보다 덜 배울 여지를 남김으로써 전체 모델이 안정화되게 만들어준다.
import torch
import torch.nn as nn
class DropoutMLP(nn.Module):
def __init__(self):
super().__init__()
self.lr1 = nn.Linear(30, 16)
self.lr2 = nn.Linear(16, 5)
def forward(self, X):
X = self.lr1(X)
X = nn.ReLU()(X)
X = nn.Dropout(p=0.3)(X)
return self.lr2(X)
- Batch Normalization
네트워크가 깊어질수록 각 층의 입력 데이터 분포가 계속해서 바뀌는 현상이 생긴다(Internal Covariate Shift). 이는 학습을 느리게 하거나 불안정하게 만드는 원인이 된다. Batch Normalization은 이를 해결하기 위해 배치 단위로 평균과 분산을 계산해 정규화하고, 그 결과를 다시 학습 가능한 scale(γ)과 shift(β)로 조정하는 방식이다.
학습 시에는 배치의 평균과 분산을 사용하고, 추론 시에는 저장된 이동 평균을 사용한다. 보통 ReLU와 같은 Activation Function 이전에 Batch Normalization을 적용하며, Dropout 없이도 일반화 성능이 뛰어난 경우도 있다.
# forward
X = nn.Linear(256, 128)(X)
X = nn.BatchNorm1d(128)(X)
X = nn.ReLU()(X)
Dropout과 Batch Normalization은 함께 사용될 수도 있지만, 두 방식이 서로 충돌하는 경우도 있어 경험적으로 조합을 조절할 필요가 있다.
- Learning Rate Decay (StepLR & CosineAnnealing)
Learning Rate는 딥러닝에서 성능을 결정짓는 핵심 하이퍼파라미터다. 일정한 Learning Rate로만 학습하면 초기에는 빠르게 수렴하지만, 일정 시점 이후에는 더 이상 개선되지 않거나 local minima에서 발산하는 현상이 생긴다. 그래서 학습 도중 Learning Rate를 조절하는 전략이 필요하며, 이를 스케줄러로 구현한다.
가장 대표적인 방식이 StepLR이다. Step Size 간격으로 Learning Rate를 gamma만큼 곱해 감소시킨다. 학습을 구간별로 나누어 Learning Rate를 조절하고 싶을 때 적절하다.
from torch.optim.lr_scheduler import StepLR
scheduler = StepLR(optimizer, step_size=30, gamma=0.5)
좀 더 부드럽게 수렴시키고 싶을 때는 CosineAnnealingLR을 쓴다. Learning Rate가 코사인 곡선을 따라 완만하게 감소하기 때문에, 학습 후반부에 급격히 성능이 흔들리지 않고 안정적으로 수렴하는 데 효과적이다.
from torch.optim.lr_scheduler import CosineAnnealingLR
scheduler = CosineAnnealingLR(optimizer, T_max=50)
더 나아가, 일정 주기마다 Learning Rate를 다시 상승시켰다가 천천히 감소시키는 전략이 CosineAnnealingWarmRestarts다. 이 방식은 마치 모델이 다시 "재도전"할 수 있게 만들어주며, 새로운 최적점으로 탈출할 수 있는 여지를 제공한다. 특히, 여러 local minima를 탐색하면서 성능 향상을 기대할 수 있다.
from torch.optim.lr_scheduler import CosineAnnealingWarmRestarts
scheduler = CosineAnnealingWarmRestarts(optimizer, T_0=10, T_mult=2)
| 파라미터 | 설명 |
|---|---|
T_0 |
첫 번째 사이클의 길이 (Epoch 수) |
T_mult |
이후 주기의 증가 배수 (e.g. 10, 20, 40, …) |
eta_min |
학습률이 수렴할 때 도달할 최소 learning rate (기본값은 0) |
스케줄러의 선택은 모델 구조, 초기 Learning Rate 설정, 데이터셋의 난이도와도 밀접하게 연관되어 있으며, 단순한 하이퍼파라미터처럼 보이지만 모델 성능에 실질적인 영향을 미치는 중요한 튜닝 요소다.
2. 저 그런 기사 아닙니다
프로젝트 관련 이야기를 해보려 한다. 나는 캠프 입과 이전에도 AI와 데이터 분석에 흥미가 있어, 단기로 공부해서 빅데이터분석기사 자격증을 취득한 경험이 있다. 기초 지식이 어느 정도 쌓여있는 상태에서 캠프 수업을 들었기 때문에 이번에 실시한 프로젝트는 나에게 큰 어려움이 없을 것이라 생각했다. 자만하지 않고 복습도 하면서 수업을 들었는데, 실제로 데이터를 손수 구해서 모델을 구현해보려니 어려운 점이 한 두개가 아니었다. 항상 scikit-learn 데이터셋이나 유명한 .csv 파일로 실습하던 나는 이들이 얼마나 친절한 데이터인지 절실히 느꼈다. 우리 팀은 서울시 상권에 대한 공공데이터를 이용한 개인사업자 폐업 예측을 주제로 프로젝트를 진행했는데, 10만에서 많게는 100만 개 가량의 관측치를 다루는 정제되지 않은 데이터셋을 사용하려니 모델링 이전에 EDA와 전처리부터 난항이었다. 열 수가 30개가 넘는 데이터에서 multicollinearity Issue를 어떻게 해결할 것인지, 어떠한 파생변수들을 정의할 것인지, 팀원들과 오랜 시간 상의했다. 또한 이탈, 폐업이라는 특성 상 반응 변수는 불균형적일 수 밖에 없었는데, 이 때문에 모델의 예측 성능을 향상시킬 때 Recall(재현율)을 끌어올리는 것이 굉장히 어려웠다. 우여곡절 끝에 Recall 0.9🔺라는 결과와 함께 성능 평가를 마쳤을 때는 얼마나 뿌듯했는지 모른다.
개인적으로 나는 이번 프로젝트에서 내가 멱살 잡고 캐리하고 싶었지만 그러지 못했다. 머릿속에 든 건 정말 많았지만 프로젝트를 진행하면서 지식들이 머릿속에서 명료하게 정리되지 않았다? 조직화되지 않았다?는 것을 느꼈다. 매 작업마다 교재를 돌아보고, 너무 막히면 일부는 GPT에게 물어보고 진행했었는데, 돌이켜보면 부끄러운 기억이다. 강사님께서 PT가 끝난 이후 다른 팀들의 프로젝트들도 살펴보고, 발표한 사람들 수준까지는 아니어도 본인 것으로 만들라는 말씀을 하셨다. 이 말씀이 트리거가 되어 두 시간 정도 더 남아 머리를 식히면서 지난 프로젝트 기간을 돌이켜보고 다른 팀들의 결과물도 살펴보는 시간을 가졌다.
🎈 Now What?
다음 주부터는 딥러닝의 각론에 해당하는 부분을 배울 것이다. 이미지 데이터, 텍스트 데이터들을 다뤄볼 텐데, 이 부분에 대한 배경지식은 전무하다. 앞으로는 하루하루 당일 배운 내용을 복습하는 것도 벅찰 것이기에, 정신 바싹 차리고 따라가야 한다. 프로젝트도 끝났고, 일단 이번 주는 휴식을 취하려 한다. 휴식의 의미로 코딩 테스트 스터디 문제를 조금 만져봤다(?). 프로그래머스 기준 lv.1 ~ lv.3의 문제로 구성했더니 쉼은 커녕 머리가 더 뜨거워졌다🤯 남은 저녁 시간은 오롯이 쉼에 써야겠다. 만전을 기하자!
여담

성수동의 카페 코에오에 주말 데이트를 다녀왔다. 날이 좋아 야외에 앉았다. 의자도 테이블도 작아 불편한 줄 알았지만 앉아보니 굉장이 편안했다. 야외에서 노트북으로 작업을 하거나 책을 읽는 몇몇 사람들이 이를 방증했다. 처음에는 따뜻한 에티오피아와 아이스 멕시코 티피카를 브루잉으로 주문해서 마셨다. 멕시코 커피는 매 번 후쿠오카의 Coffee County에서 전량 쓸어가던 생두인데, 이번에 한국에 소량 입고되어 소개하고 계시다고 한다. 두 잔 다 핵과류의 달콤한 뉘앙스가 살아 있어 맛있었다. 두 잔을 금세 비우고 아이스 아메리카노와 아이스크림 푸딩을 추가주문했다. 아메리카노도 쫀득해서 먹는 재미가 있었고, 푸딩은 일본 디저트 카페의 그것을 연상케 했다. 직원 분들의 차분하면서 에너제틱한 분위기도 인상깊었다. 커피를 저 낮은 테이블에 가져다 주시더니 쭈구려 앉으시고는 눈높이를 맞춘 뒤에 커피에 대한 설명을 해주시더라. 커피도, 공간도, 사람도, 마음 속에 오래 남을 좋은 기억이다.
여담
Obsidian을 사용해볼까 한다.
'SKN_13th' 카테고리의 다른 글
| [플레이데이터 SK네트웍스 Family AI 캠프 13기] 월간 회고: 5월 (0) | 2025.05.31 |
|---|---|
| [플레이데이터 SK네트웍스 Family AI 캠프 13기] 9주차 회고 (0) | 2025.05.25 |
| [플레이데이터 SK네트웍스 Family AI 캠프 13기] 7주차 후기 (0) | 2025.05.11 |
| [플레이데이터 SK네트웍스 Family AI 캠프 13기] 6주차 후기 (0) | 2025.05.04 |
| [플레이데이터 SK네트웍스 Family AI 캠프 13기] 월간 회고: 4월 (1) | 2025.04.27 |