요즘 들어 잠이 많아졌다. 몇 주 전까지만 해도 5시간만 자고 나가서 하루 종일 수업을 들어도 몸이 버텨줬는데, 이번 주는 매번 6시간은 자야 침대에서 몸을 일으킬 수 있었다(그럼에도 5일 내내 수업 시작 전 10분, 20분 전에 도착하긴 했다). 프로젝트 준비하는 동안 바쁘게 보낸 지난 주의 여파가 아직 가시지 않은 걸까. 그래서인지 토요일에는 무려 열 시간을 자고 아침 열 시에 하루를 시작했다. 푹 자고 일어나면 정신이 맑은 느낌이 들고 기분도 좋지만, "주말이라도 아침 일찍부터 일어나서 뭔가 했어야 했는데"와 같은 약간의 죄책감도 든다. 이 부분은 얼마 전에도 고민했지만, 고치지 않기로 했다. 주말을 주말답게 보낼 줄도 알아야 다음주를 활기차게 시작할 수 있지 않겠는가. 그렇게 핑계를 늘어놓은 뒤, 아점과 함께 하루를 시작한 토요일이었다.
🎈 What?
이번 주부터 6월 말까지는 NLP(Natural Language Processing) 및 LLM(Large Language Model)에 대해 배우는 모양이다. 그래서 이번 주 5일 동안은 NLP의 기초에 대해 배웠다. 우선 문자열 데이터을 매우 유연하게 다루는 방법인 regular expression을 간단히 배우고, NLP의 기본적인 workflow, Embedding, RNN의 기본 구조에 대해 배우면서, 수업 시간 중 간단한 실습을 겸했다.
# NLP Workflow
# 1. Gathering Corpus
#
# 2. Preprocessing
# * Cleaning(Noises. e.g. Stop word)
# * Normalization(Stemming, Lemmatization, Morphological analysis, etc)
#
# 3. Tokenization
#
# 4. Embedding
#
# 5. Modeling
화요일에는 캠프에서 인프런 강의를 제공받았다. 본 캠프에서는 매 과목이 끝날 때마다 성취도 평가를 실시하고, 평과 결과에 따라 수준 별 보충 학습 자료를 제공한다. 저번에는 아쉽게 놓쳤던 심화 학습 자료를 이번 ML/DL 파트에서 받게 되었다. 이번에 받게 된 심화 학습 강의는 선형 대수 관련 강의로, 행렬과 기초 통계 지식이 필요했던 내게 최적이다.
그리고 같은 날 저녁, 새롭게 편성된 코딩 테스트 스터디에서 첫 스터디를 진행했다. 총 다섯 문제를 준비했고, 서로 풀어온 코드를 복기한 뒤에 해당 문제에서 쓰인 알고리즘과 스킬을 간단하게 되짚어보는 시간을 가졌다. 다섯 문제 모두 상이한 알고리즘을 다뤘기에 다소의 시간이 소요되었다.
😮 So What?
1. 나랏말싸미 듕귁에 달아...
난생 처음 배우는 NLP, 자연어를 다루는 분야다 보니 자연어의 특성에 대해 먼저 배우게 되었다. 앞서 소개한 NLP Workflow의 Preprocessing 부분은 흡사 고등학교 국어, 영어 문법 시간이었다. stem(어간), morpheme(형태소), POS(part of speech, 품사), lemma(표제어) 등의 용어들을 다루고 있으니 10년 전 학교에서 야자하던 기억이 떠올랐다.
Stemming
- Stem: Things that don't change
- painted, paint, painting → paint
- 보다, 보니, 보고 →
보
- Goal
- To make words which are semantically same but syntactically different a single state
- flower-0, flowers-1 -> flower - 0
- To make words which are semantically same but syntactically different a single state
- weakness
- imperfection
- new(adj), news(n) -> new
- need doublecheck with our eyes.
- imperfection
Lemmatization
- to make a word lemma
- e.g. am. is, are => be
- semantically precise results
- weakness
- low velocity, complex implementation
이번 주에 배운 내용 중 가장 핵심이 되는 내용은 Word Embedding과 RNN(Recurrent Neural Network)일 것이다. Embedding이란 여러 단어들을 특정 공간에 매핑했을 때 해당 공간 내에서 서로 근처에 있는 단어들은 의미도 비슷할 것이다는 컨셉(Distributed Representation) 하에 단어들을 실수들로 구성된 Vector(좌표에 매핑할 수 있는 형태)로 치환하는 작업이다. 이렇게 정형화된 형태로 치환된 후에 비로소 자연어를 모델에 학습시키고 예측 및 분석할 수 있다. 해당 처리는 Neural Network 기반이다.
단어를 sparse vector(각 token은 무수히 많은 0과 극소수의 not 0으로 이루어져 있음)로 치환하던 기존의 통계학적 접근법들과 달리(CountVectorizer, TF-IDF, etc.), Embedding은 dense vector(대부분 0이 아닌 실수 값으로 구성되며, 각 차원이 단어의 잠재적 의미를 표현함)로 만들어준다.
이쯤에서 Embedding이 왜 필요한지 다시 한 번 생각해보자. 우리는 특정 머신러닝 모델에 텍스트 데이터를 입력해서 해당 데이터를 처리하고 싶다. 우리는 데이터를 모델에 텍스트 상태 그대로 집어 넣을 수 없기 때문에, preprocessing -> tokenizing -> embedding해서 모델이 처리할 수 있는 형태로 데이터를 바꿔줘야 한다. 이 embedding을 해주는 별도의 객체가 존재하는데, 우리는 특정 입력에 대해 어떻게 embedding할 것인지, 즉 특정 입력 단어를 어떤 실수 값들로 구성해야 단어 고유의 의미를 유지한 채 분석 모델에 입력 가능한 형태로 바꿀 수 있는지에 대한 방법을 이 객체에 학습시켜야 한다. 학습의 기본 컨셉은 완성된 문장 내지 문서를 입력받으면 일부러 특정 단어에 빈 칸을 뚫어 놓고, 문장, 문서 내 주변 단어들을 참조하여 객체 스스로 빈칸을 채워보게끔 하는 것이다. 이러한 방법에는 대표적으로 CBOW(Continuous Bag of Words)와 Skip-gram이라는 두 가지 방법론이 있고, 이들의 차이는 '빈칸을 어떤 방식으로 만들 것인가'에 있다.
CBOW and Skip-gram
- Target and Window
- Window Size = 2 -> 2s behind and 2s in the front.
- GUESS!!
- CBOW: 나는 어제 ___ 함께 학교에 갔다.
- Skip-gram: __ __ 밥을 __ ___
더 나아가, Contextualized Word Embedding은 특정 문장 및 문서 내에서 단어가 쓰인 개별적인 맥락까지 고려하겠다는 개념이다. 앞서 설명한 Embedding은 '밤'이란 글자에 대해 하나의 고유한 vector를 할당할 것이다. 그런데 '밤'이 단 하나의 뜻만 지니는가? 아니다. 만약 embedding 객체가 '밤(night)'과 '밤(chestnut)'을 거의 동일한 횟수만큼 학습했다면, '밤'이라는 글자는 night과 chestnut 그 어느 쪽도 제대로 설명하지 못하는 애매한 vector를 받게 될 것이다. Contextualized Word Embedding은 이러한 문제를 해소하고자, 문장 내 문맥까지 같이 보겠다는 컨셉이다. 이 방법론 중 대표적인 것이 바로 RNN(Recurrent Neural Network)이다.

RNN도 이름 그대로 Neural Network이지만 기존 Embedding과 다른 점이 있다. 바로 각 forward 연산마다 이전 결과를 반영한다는 것이다. 이때 RNN은 hidden state라고 불리는 내부 메모리를 활용하여, 현재 단어를 처리할 때 이전까지의 단어 순서와 내용을 요약한 정보를 함께 고려한다. 그 결과, 동일한 단어라도 문맥에 따라 이 hidden state값이 달라지며, 이것이 바로 해당 단어의 문맥적인 의미를 포착한 vector가 된다. 따라서 '밤(night)'과 '밤(chestnut)'은 서로 다른 문맥이 반영된 Embedding 값을 가질 수 있게 된다.
import torch
import torch.nn as nn
# dummy data: 30 words, 100 batches, into 4 features
input_data = torch.randn((30, 100, 4))
rnn1 = nn.RNN(
input_size = 4,
hidden_size = 256, # the number of units
num_layers = 1
# batch_first = True, # if True -> (100, 30, 4)
# nonlinearity = 'relu', # default: 'tanh'
# bidirectional = True
)
o1, h1 = rnn1(input_data) # (every time steps, the last time step)
print(o1.shape, h1.shape, sep = '\n')
# torch.Size([30, 100, 256])
# torch.Size([1, 100, 256])
2. 첫 그룹 리딩
이번 스터디 그룹의 조장은 나다. 알고리즘이나 코딩을 어디서 배운 적은 없지만, 이번 기회가 내가 스터디를 준비하는 과정 속에서 배울 수 있는 기회라고 생각한다. 그래서 첫 스터디를 나름 심혈을 기울여 구성했다. 본 캠프에서 지원하는 프로그래머스 PCCE/PCCP에 대비해 프로그래머스 연습 문제를 다섯 개(Lv. 1 ~ Lv. 3) 선별했다. 주말에 먼저 풀어본 뒤, .ipynb 파일에 문제 별 여러 가지 접근법, 문제에 쓰인 알고리즘에 대한 기본적인 설명을 예시와 함께 담기도 했다(e.g. Greedy Algorithm -> 거스름돈).
이번 주에는 네 명이서 스터디를 진행했는데, 각자 빡세게 코드리뷰하고 알고리즘 초간단 스터디도 곁들이려니 네 명이서 두 시간을 녹여버렸다. 끝난 직후에 팀원분들과 진행 관련 얘기를 나눠봤는데, 시간도 시간이지만 아무래도 다섯 개의 알고리즘을 하루에 녹여낸다는 건 무리가 있는 듯하다. 나 또한 진행해보니 짧은 시간 동안 다섯 개를 빠르게 치고 가는 것은 겉핥기식일 수 있겠다는 생각을 했고, 한 주에 하나의 알고리즘과 진득하게 놀아봐야 체화가 될 것 같다. 그래도 단순 문제 풀이에서 끝나는 게 아닌 알고리즘 되짚기는 시간이 조금 걸려도 다들 괜찮아하신 것 같고, 무엇보다 나에게 정말 도움이 되기 때문에 이 부분은 놓치지 않고 싶다.
그래서 내린 결론은 "한 놈만 패자"다. 매주 특정 알고리즘 관련 문제만 준비해서, 그 알고리즘만 딥하게 다뤄보는 것이다. 내가 아직 문제만 보면 "아, 이건 DFS구나", "이건 딕셔너리 쓰는 문제구나"와 같이 머릿속에 바로 떠오르는 고수는 아니라 다른 알고리즘의 문제를 잘 못 고를 수 있겠지만, 이 부분은 팀원분들의 너른 양해를 구해야겠다. 어쨌든 누군가와 함께 배운다는 건 즐거운 일이다.



(이 글을 보고 계신 여러분, 제 설명에 틀린 부분이 있다면 꼭 피드백 부탁드립니다...!!)
🎈 Now What?
주말 내내 다음 코딩 테스트 스터디 문제를 풀었다. 내가 뽑은 문제지만 참 어렵다. 난이도 자체는 저번 주가 더 어려운 것 같은데, 이번 문제들이 기본기를 많이 요하는 것 같다. 이제 스터디 자료를 만들어야 하는데 자료에 기본기 관련 내용도 살짝 녹여봐야겠다. 그리고 이번 주가 NLP를 위한 초석을 다지는 시간이었던 만큼, 배웠던 내용들을 주말 중으로 꼭꼭 씹어 먹어야겠다. 먹다 체하면 안될 텐데... 그리고 매 주마다 시간을 내서 선형 대수 강의를 적어도 한 편 씩 들어놓아야겠다. ML/DL 수업 때부터 행렬과 차원에 대한 개념이 정확하게 잡혀있지 않으면 기계학습의 모든 영역에서 발목잡힐 것이라는 점을 느꼈다. 뭐든지 기초...
여담
얼마 전부터 WJ님, JS님과 함께 2025년 국토교통 데이터 활용 경진대회에 나가기로 했다. 거듭된 회의 끝에 주제를 정하고 금요일에 참가 신청서를 제출했다. 처음 맛 보는 제품/서비스 개발, 쟁쟁한 분들과 겨루게 될 것이다. 일단 우리 아이디어를 실현하고 완주하는 것을 목표로 끝까지 열심히 달려보자고 서로 다짐했다. Team DOMICON let's go🔥🔥🔥
'SKN_13th' 카테고리의 다른 글
| [플레이데이터 SK네트웍스 Family AI 캠프 13기] 11주차 회고 (7) | 2025.06.08 |
|---|---|
| [플레이데이터 SK네트웍스 Family AI 캠프 13기] 월간 회고: 5월 (0) | 2025.05.31 |
| [플레이데이터 SK네트웍스 Family AI 캠프 13기] 8주차 회고 (0) | 2025.05.18 |
| [플레이데이터 SK네트웍스 Family AI 캠프 13기] 7주차 후기 (0) | 2025.05.11 |
| [플레이데이터 SK네트웍스 Family AI 캠프 13기] 6주차 후기 (0) | 2025.05.04 |