이번 주는 우산을 챙긴 날이 조금 있었던 기억이 든다. 쏟아진 날도, 부슬비가 내린 날도 있었다. 이때문인지 날씨가 조금 뜨거워지려 하다가도 시원하고 쾌적했던 것 같은 느낌이다. 여름옷은 저번 주에 전부 꺼내 놓았지만, 일주일 내내 바람막이만 입었던 한 주였다. 봄가을이 짧아지고 있는 오늘날이지만, 올해 봄은 작년보다는 길게 느껴지는 것 같기도 하다. 이런 시원한 날씨가 적어도 5월 말까지는 이어졌으면 하는 바람이다.
💻 What?
-
- Introductory Deep Learning: `import torch`
이번 주로 whitebox 기반의 머신러닝에 대한 수업이 끝났다. 지난 주에 이어서 Supervised Learning Model인 Decision Tree, Random Forest, Gradient Boosting, Linear Regression, Logistic Regression, Unsupervised Learning Model인 K-Means Cluster에 배웠다. 또한 Linear Model 최적화의 핵심인 Gradient Descent에 대해 배웠다. 이후 딥러닝 개론을 시작했다. 딥러닝도 광의의 머신러닝의 한 부류지만 통상적인 의미의 머신러닝과 구분되는 차이점이 무엇인지 배우고, 간단하게 정형 데이터를 학습시켜보기도 했다. 단순하지만 초대규모 연산을 수행하는 딥러닝 특성 상, 코어가 많아 병렬 연산에 특화된 GPU가 필요하다. 이에 강사님은 나중에 모델을 본격적으로 학습시킬 때는 Google Colab을 사용하여 GPU가 탑재된 클라우드 컴퓨팅 환경에서 작업하는 것을 권장하셨다. 아울러 우리는 딥러닝 구현 라이브러리로 tensorflow가 아닌 pytorch를 사용하기 때문에, pytorch의 핵심 자료 구조인 tensor에 대해 자세히 다루었다.
-
- 첫 번째 PCCE
수요일 오후 6시 30분, 수업이 끝난 뒤 간단한 간식거리를 먹은 뒤 인생 첫 코딩 테스트를 경험했다. 프로그래머스에서 주관하는 시험 중 PCCE(Programmers Certified Coding Essential)에 응시했고, 약 50분 간 시험에 응시했다. 시험이 끝난 뒤 당일 수업 복습을 아주 잠깐 하다가 집으로 돌아갔다
😮 So What?
-
- 어려운 건 항상 이론
항상 느끼지만 머신러닝, 딥러닝이라는 것이 코드로 구현하는 것도 일이지만, 각 모델의 개념, 원리, 연산 과정을 이해하는 일이 나에게는 제일 어려운 것 같다. 특히 최적화 알고리즘인 Gradient Descent는 나중에 배울 신경망 모델 핵심 개념 중 하나인 Backpropagation과도 매우 밀접한 관련이 있기 때문에, 이번에 꼭 짚고 넘어가겠다는 생각으로 연필로 몇 번이고 끄적였다.
Gradient Descent
실제 값과 모델이 예측한 값 사이의 오차를 식으로 표현한 Loss Function이 있고, 이 Loss Function을 최소화하는 최적의 Loss Function Parameter를 찾는다. 즉, Loss Function의 도함수가 0이 되는 지점을 향하도록 반복적으로 Parameter를 update하는 과정을 Gradient Descent라고 한다.
예를 들어 설명변수와 반응변수가 각각 하나인 단순 선형 회귀 모델이 있고, Loss Function으로 MSE를 사용한다고 가정하자.
$\hat{y} = wx + b$
$\text{MSE}(w, b) = \cfrac{1}{2}\cdot\sum_{i=1}^n{(\hat{y_i} - y_i)^2}$
MSE를 최소화하기 위해 식 안에서 어떤 부분을 만져야할 지 살펴보니, $y_i$는 관측치 자체이기 때문에 수정할 수 없다. 따라서 $\hat{y}_i$를 만져보기로 한다. 또 $\hat{y}_i$에서 만져볼 수 있는 부분은 관측치 $x$를 제외한 $w$와 $b$가 되겠다.
다음으로는 MSE를 최소화하기 위해 $w$와 $b$를 변화시키는 방향을 잘 찾아야 한다. 이를 위해 미분을 활용하여 $w$와 $b$에 대한 MSE의 기울기를 계산하면 다음과 같다:
$\cfrac{\partial \text{MSE}}{\partial w} = \sum_{i=1}^n (\hat{y}_i - y_i) \cdot x_i$
$\cfrac{\partial \text{MSE}}{\partial b} = \sum_{i=1}^n (\hat{y}_i - y_i)$
이 기울기들은 현재의 $w$, $b$ 값에서 MSE가 얼마나, 어떤 방향으로 변하는지를 나타낸다. 따라서 Gradient Descent에서는 이 기울기의 반대 방향으로 $w$와 $b$를 조금씩 이동시키며 다음과 같이 업데이트한다(기울기의 방향은 MSE가 증가하는 방향이므로, 그 반대로 이동해야 MSE가 감소한다):
$w_{t+1} = w_t - \text{LearningRate} \cdot \cfrac{\partial \text{MSE}}{\partial w_t}$
$b_{t+1} = b_t - \text{LearningRate} \cdot \cfrac{\partial \text{MSE}}{\partial b_t}$
여기서 $\text{LearningRate}$는 Parameter가 한 번에 얼마나 크게 이동할지를 결정하는 값이다. 이 과정을 반복하면 $w$와 $b$는 점점 MSE가 작아지는 방향으로 조정되며, 모델의 예측 성능은 점차 향상된다.
신경망 모델은 기본적으로 선형성을 띠는 여러 모델(뉴런)들이 네트워크 구조를 이루어 결합한 형태이다(활성화 함수 이야기는 다음으로 미룬다). 이러한 특성 덕분에 신경망 기반의 딥러닝 모델 역시 Gradient Descent를 통해 Parameter를 최적화할 수 있다.
위 과정을 pytorch 소스코드로 나타내면 다음과 같다.
import torch
import torch.nn as nn
model = nn.Linear(3, 2) # 3 features, 2 targets
loss_fn = nn.MSELoss()
optimizer = torch.optim.SGD( # Stochastic Gradient Descent
model.parameters(),
lr = 0.00001 # Learning Rate
)
epochs = 5000 # 5000 Iterations
for epoch in range(epochs):
pred = model(inputs) # inputs는 관측치 저장된 (n, 3) 2D tensor
loss = loss_fn(pred, targets) # torch.nn.functional.mse_loss(pred, targets) targets는 관측치 저장된 (n,2) 2D tensor
loss.backward() # Gradient 계산
optimizer.step() # Parameter 업데이트
optimizer.zero_grad() # 다음 계산을 위해 기존 Gradient를 저장하고 있는 속성 초기화
-
- 알고리즘.. 늘긴 늘었는데...

코딩 테스트 당일, 시험이 끝나고 얼마 뒤에 결과가 바로 발표되었다. 결과는 여러 면에서 예상 밖이었다. 일단 10문제 중 3문제를 풀지 못했다. 항목 별로 한 문제씩 못 풀었었는데, 점수를 보니 그래도 푼 문제들은 다 맞은 모양이다.
시험 결과에서 두 가지가 내 예상을 벗어났는데, 하나는 코드 작성 항목의 두 문제 중 한 문제는 풀어냈다는 점이다. 암만 코딩 테스트 스터디에서 소스코드 작성 위주로 연습했다고는 해도, 홈페이지에서 제공하는 코드 작성 기출문제들은 코린이인 나한테는 난이도가 조금 있었다. 그럼에도 실전에서 한 문제는 풀어냈고, 50분 동안 정신없이 풀어서 기억이 안나지만, 문제 배점과 시험에 같이 응시한 학우님들과 나눈 이야기에 의하면 내가 푼 문제는 10번 문제인 듯하다(10번이 제일 난이도가 높은 경향이 있다고 한다). 이건 예상 외의 발전이다.
다른 하나는, 쉬울 거라 생각했던 디버깅, 빈칸 채우기에서 한 문제씩 못 풀었다는 것이다. 이 점은 내게 다소 충격적이었다. 쉽다고 여겼던 유형들도 한 문제 내에서 여러 함수들을 정의하고 논리 구조 자체가 복잡해지면 시험장에서는 아예 읽히지가 않는 수준이었다. 차라리 동일한 문제로 코드 작성을 하라고 했으면 제출이라도 했을 것 같다. 당장 문제 풀이도 중요하지만, 스터디에서 다른 사람들이 작성한 코드들도 자세히 살펴봐야겠다는 생각이 들었다.
🎈 Now What?
이번주의 복습은 pytorch와 친해지기이다. 다차원 배열을 다루는 numpy와 용법이 대체로 비슷하면서도 다른 점들이 몇 군데 보이더라. 강의안을 읽고 실습 코드들을 작성해보면서 이런 부분들을 numpy와 비교해보면 자연스레 pytorch와 numpy 모두 머릿속에 남을 수도 있겠다. 본격적으로 비정형 데이터 학습을 시작하면 다루게 될 자료구조의 형태는 최소 3차원일텐데 얼른 다차원 배열과 친해져야겠다.
그리고 남의 코드를 읽고 해석하는 게 어렵다는 것을 알게 된 이상, 앞으로 학우님들을 조금 괴롭혀봐야겠다. 학우님들이 내가 풀 수 있을 만한 문제를 푸는데 어려움을 겪고 있다면 조용히 문제와 소스 코드를 공유해달라고 부탁드려야겠다. 이게 리얼 디버깅 아니겠는가.
앞으로 배울 것들의 난이도가 점점 높아질 것이다. 지금처럼 모르는 것이 생기면 꼬리에 꼬리를 물어 질문하자. 그리고 결국 내 것으로 만들자. 나도 할 수 있다.
여담

마포구 경의선 숲길 근처, 시원한 바람이 부는 일요일 오후에 ‘나이스워크투데이’라는 카페에 방문했다. 이름에서 알 수 있듯, 공간 안에서 작업을 장려하는 흔치 않은 매장이다. 두 번째로 방문했고, 대략 한 시간 가까이 이 포스팅을 적고 나왔다. 은은하면서도 공간을 꽉 채우는 음악과, 높은 층고가 매력적이다. 날이 좋으면 왼쪽에 보이는 통창을 활짝 열어 테라스 석을 개방하는데, 테라스 너머로 보이는 경의선 숲길 풍경이 시선을 끈다. 당연히 커피도 맛있다. 에스프레소 베이스도 취향껏 원두를 선택할 수 있고, 업데이트 되는 싱글오리진 브루잉 라인업을 즐기는 것도 재미있다. 시그니쳐 밀크 커피도 두 종류 준비되어 있다.
'SKN_13th' 카테고리의 다른 글
| [플레이데이터 SK네트웍스 Family AI 캠프 13기] 8주차 회고 (0) | 2025.05.18 |
|---|---|
| [플레이데이터 SK네트웍스 Family AI 캠프 13기] 7주차 후기 (0) | 2025.05.11 |
| [플레이데이터 SK네트웍스 Family AI 캠프 13기] 월간 회고: 4월 (1) | 2025.04.27 |
| [플레이데이터 SK네트웍스 Family AI 캠프 13기] 4주차 회고 (1) | 2025.04.20 |
| [플레이데이터 SK네트웍스 Family AI 캠프 13기] 3주차 회고 (0) | 2025.04.13 |