안녕하세요!
자연어 처리에서 컴퓨터가 문자를 이해하게 만드는 첫 번째 단계는 단어를 숫자로 바꾸는 것입니다. 단순한 인덱싱을 넘어 단어의 '의미'와 '문맥'을 담아내는 임베딩 기술들에 대해 알아봅시다.
1. 워드 임베딩 (Word Embedding)
워드 임베딩은 단어를 고차원의 희소 벡터(원-핫 인코딩) 대신, 저차원의 밀집 벡터(Dense Vector)로 변환하는 기법입니다.
- 원-핫 인코딩의 한계: 단어의 종류가 늘어날수록 벡터의 길이는 무한정 길어지고(희소성), 단어 간의 유사성을 전혀 계산할 수 없습니다.
- 임베딩의 장점: 벡터 공간에 단어를 배치하여 단어 간의 거리나 방향을 통해 의미적 유사성을 계산할 수 있습니다.
1-1. Embedding Layer
신경망 내부에서 단어 인덱스를 밀집 벡터로 매핑하는 층입니다. 학습 가능한 파라미터로 구성되어 모델이 특정 태스크를 수행하면서 최적의 단어 표현을 스스로 찾아갑니다.
1-2. 랜덤 초기화 vs 사전 훈련된 임베딩
- 랜덤 초기화: 처음에는 무작위 값으로 시작하여 현재 가진 데이터셋에 맞게 최적화됩니다. 특정 도메인(예: 의료, 법률)에 특화된 언어 모델을 만들 때 유리합니다.
- 사전 훈련된 임베딩 (Pre-trained): 대규모 말뭉치(위키피디아 등)에서 이미 학습된 Word2Vec, GloVe 등을 가져와 사용합니다. 데이터가 부족한 상황에서 성능을 비약적으로 높일 수 있습니다.
2. Word2Vec: 주변 단어로 의미를 추론하다
Word2Vec은 "비슷한 문맥에서 등장하는 단어들은 비슷한 의미를 가진다"는 가정하에 학습합니다.
2-1. CBOW (Continuous Bag of Words)
- 핵심: 주변 단어(Context)를 보고 중심 단어(Target)를 예측합니다.
- 예시: [공원에서, 귀여운, (?), 산책시키며, 행복한] -> (?)에 들어갈 말이 '강아지를'임을 예측.
- 특징: 학습 속도가 빠르고 데이터가 많을 때 안정적입니다.
2-2. Skip-gram
- 핵심: 중심 단어(Target)를 보고 주변 단어(Context)를 예측합니다.
- 특징: CBOW보다 계산량이 많지만, 드물게 등장하는 단어(Rare words)를 학습하는 능력이 더 뛰어납니다.
2-3. SGNS (Negative Sampling)
모든 단어에 대해 소프트맥스를 계산하는 것은 매우 무겁습니다. SGNS는 정답인 단어 쌍에는 1(Positive)을, 무작위로 뽑은 오답 단어 쌍에는 0(Negative)을 부여하여 이진 분류 문제로 단순화함으로써 연산 효율을 극대화합니다.
3. 실습: NSMC 데이터셋으로 Word2Vec 학습하기 (Gensim)
네이버 영화 리뷰 데이터를 활용하여 한국어 단어 임베딩을 직접 구현하는 코드입니다.
# 환경 설정 및 데이터 로드
!pip install konlpy mecab-python
!bash <(curl -s https://raw.githubusercontent.com/konlpy/konlpy/master/scripts/mecab.sh)
import urllib.request
from konlpy.tag import Mecab
from gensim.models.word2vec import Word2Vec
import pandas as pd
# 데이터 로드 및 결측치 제거
urllib.request.urlretrieve("https://raw.githubusercontent.com/e9t/nsmc/master/ratings.txt", filename="ratings.txt")
train_data = pd.read_table('ratings.txt').dropna(how='any')
# 정규 표현식을 통한 한글 외 문자 제거
train_data['document'] = train_data['document'].str.replace("[^ㄱ-ㅎㅏ-ㅣ가-힣 ]","")
# 불용어 정의 및 토큰화
stopwords = ['도', '는', '다', '의', '가', '이', '은', '한', '에', '하', '고', '을', '를', '인', '듯', '과', '와', '네', '들', '지', '임', '게']
mecab = Mecab()
tokenized_data = []
for sentence in train_data['document']:
temp_X = mecab.morphs(sentence)
temp_X = [word for word in temp_X if not word in stopwords]
tokenized_data.append(temp_X)
# Word2Vec 모델 학습
# vector_size: 임베딩 차원, window: 컨텍스트 윈도우 크기, sg: 0(CBOW) 또는 1(Skip-gram)
model = Word2Vec(sentences=tokenized_data, vector_size=100, window=5, min_count=5, workers=4, sg=0)
# 결과 확인
print(model.wv.most_similar('블록버스터'))
4. FastText: 단어의 뼈대(Subword)까지 분석하다
FastText는 Word2Vec의 확장판으로, 단어를 n-gram 문자 조각으로 쪼개서 학습합니다.
- 장점:
- OOV(Out-of-Vocabulary) 대응: 학습 데이터에 없던 단어라도 'apple'과 'apples'처럼 형태가 비슷하면 의미를 추론할 수 있습니다.
- 한국어 적합성: 교착어인 한국어에서 '행복', '행복한', '행복하게'의 공통 부분인 '행복'을 인식할 수 있습니다.
자모 단위 n-gram 처리 (한국어 심화)
한국어의 특성을 극대화하기 위해 '남동생'을 'ㄴㅏㅁㄷㅗㅇㅅㅐㅇ'처럼 자모로 분해하여 학습하는 방식이 매우 효과적입니다.
!pip install hgtk fasttext
import hgtk
# 자모 분해 함수 정의
def word_to_jamo(token):
def to_special_token(jamo):
return jamo if jamo else '_'
decomposed_token = ''
for char in token:
try:
cho, jung, jong = hgtk.letter.decompose(char)
decomposed_token += to_special_token(cho) + to_special_token(jung) + to_special_token(jong)
except:
decomposed_token += char
return decomposed_token
# FastText 학습 예시 (자모 데이터 기반)
import fasttext
# 'tokenized_data.txt'는 자모 단위로 전처리된 텍스트 파일
model = fasttext.train_unsupervised('tokenized_data.txt', model='cbow')
# 유사도 확인 (오타가 있어도 의미를 찾아냄)
print(model.get_nearest_neighbors(word_to_jamo('남동쉥'), k=5))
5. GloVe: 전역 통계 정보를 활용하다
GloVe(Global Vectors)는 Word2Vec과 달리 동시 발생 행렬(Co-occurrence Matrix)을 사용하여 코퍼스 전체의 통계 정보를 반영합니다.
- 원리: 단어 $i$와 $j$가 함께 등장하는 빈도수를 행렬로 만들고, 그 통계적 관계를 가장 잘 설명하는 벡터를 찾습니다.
- 특징: Word2Vec이 국소적인 문맥(윈도우)에 집중한다면, GloVe는 말뭉치 전체의 전역적 특징을 더 잘 잡아냅니다. 특히 단어 간의 선형 관계(King - Man + Woman = Queen)를 매우 잘 나타내는 것으로 알려져 있습니다.
요약 및 결론
| 알고리즘 | 특징 | 장점 |
| Word2Vec | 주변 단어 예측 중심 | 빠르고 대중적임, 유사도 측정에 강함 |
| FastText | 단어 내부 서브워드 활용 | 오타 및 희귀 단어에 강함, 한국어에 유리 |
| GloVe | 전체 통계(동시 발생) 기반 | 전역적인 의미 관계(추론) 학습에 탁월 |
학습 데이터가 많고 일반적인 유사도가 중요하다면 Word2Vec을, 형태소 변화가 심하거나 오타가 섞인 데이터라면 FastText를 추천합니다.
'개념 정리 step2 > 멀티모달(Multi-modal)' 카테고리의 다른 글
| [딥러닝 NLP] NLU에서 트랜스포머 어텐션까지 핵심 개념 정리 (1) | 2026.01.16 |
|---|---|
| [RNN] 시퀀스 데이터와 순환 신경망(RNN) 학습 정리 (1) | 2026.01.15 |
| [NLP 기초] 자연어 처리의 시작: 토큰화와 벡터화 (0) | 2026.01.13 |
| [Deep Learning] TensorFlow 기초와 날씨 분류 모델 실습 (0) | 2026.01.12 |
| [CV Archive] YOLOv8 Segmentation: 스타벅스 로고 추출하기 (0) | 2026.01.11 |