Embedding Layer (임베딩 층)
1. 개요
임베딩 층(Embedding Layer)은 자연어 처리(NLP) 및 딥러닝 모델에서 정수 형태로 인코딩된 범주형 데이터(주로 단어 인덱스)를 고정된 크기의 연속적인 수치형 벡터로 변환하는 신경망 층이다.
컴퓨터는 텍스트를 직접 처리할 수 없으므로 수치화 과정이 필수적이다. 초기에는 단어의 존재 여부만을 표시하는 원-핫 인코딩(One-hot Encoding) 방식이 사용되었다. 원-핫 인코딩은 단어 집합의 크기가 $V$일 때, 해당 단어의 위치만 1이고 나머지는 모두 0인 $V$차원의 벡터로 표현하는 방식이다. 그러나 이 방식은 다음과 같은 치명적인 한계가 있다.
- 차원의 저주: 단어 사전의 크기가 커질수록 벡터의 차원이 기하급수적으로 증가하여 메모리 낭비가 심하다.
- 의미론적 관계 부재: 모든 단어 벡터 간의 내적이 0이 되므로, '강아지'와 '개'가 유사한 의미라는 관계를 수학적으로 표현할 수 없다.
임베딩 층은 이러한 희소 표현(Sparse Representation)을 저차원의 밀집 표현(Dense Representation)으로 변환함으로써 효율적인 연산과 의미론적 정보 보존을 가능하게 한다.
2. 동작 원리
임베딩 층은 내부적으로 룩업 테이블(Lookup Table) 구조를 가진 가중치 행렬(Weight Matrix)로 동작한다. 입력으로 들어온 정수 인덱스는 이 행렬의 행 번호로 사용되어, 해당 행에 저장된 벡터를 그대로 추출하는 방식으로 작동한다.
변환 과정 메커니즘
입력 데이터가 단어 인덱스 $i$일 때, 임베딩 행렬 $W$의 $i$번째 행을 추출하는 과정은 수학적으로 원-핫 벡터 $x_{one-hot}$와 행렬 $W$의 행렬 곱과 동일하다.
$$\text{Embedding}(x) = x_{one-hot} \cdot W$$
(여기서 $x_{one-hot}$은 $1 \times V$ 벡터, $W$는 $V \times d$ 행렬이며, 결과값은 $1 \times d$ 벡터가 된다.)
연산 방식 비교 도식
- 원-핫 인코딩 방식: $\text{Input Index} \rightarrow \text{One-hot Vector} \rightarrow \text{Matrix Multiplication} \rightarrow \text{Dense Vector}$
- 임베딩 층 방식: $\text{Input Index} \rightarrow \text{Lookup Table (Index-based Access)} \rightarrow \text{Dense Vector}$
(임베딩 층은 불필요한 행렬 곱 연산을 생략하고 인덱스로 직접 접근하여 연산 효율성을 극대화한다.)
| 단계 |
입력/연산 |
형태 (Shape) |
설명 |
| 입력 |
단어 인덱스 (Integer) |
$(batch\_size, seq\_len)$ |
정수로 변환된 단어 시퀀스 |
| 매핑 |
가중치 행렬 $W$ |
$(vocab\_size, embed\_dim)$ |
학습 가능한 임베딩 파라미터 행렬 |
| 출력 |
임베딩 벡터 (Float) |
$(batch\_size, seq\_len, embed\_dim)$ |
각 단어가 밀집 벡터로 변환된 결과 |
3. 주요 특징 및 학습 방식
학습 가능한 가중치
임베딩 벡터의 값은 고정된 상수가 아니라, 모델의 다른 가중치들과 마찬가지로 역전파(Backpropagation) 알고리즘을 통해 학습된다. 모델이 주어진 태스크(예: 감성 분석, 기계 번역)를 수행하면서 손실 함수(Loss Function)를 최소화하는 방향으로 단어 벡터의 값들이 미세하게 조정된다. 결과적으로 유사한 문맥에서 자주 등장하는 단어들은 벡터 공간상에서 서로 가까운 위치에 배치되게 된다.
차원 수(Embedding Dimension) 결정
임베딩 차원($d$)은 하이퍼파라미터로 설정하며, 일반적으로 50, 100, 300, 768 등이 사용된다.
- 차원이 너무 낮으면: 단어가 가진 복잡한 의미론적 정보를 충분히 담지 못해 표현력이 떨어진다.
- 차원이 너무 높으면: 모델의 파라미터 수가 급증하여 과적합(Overfitting) 위험이 커지고 연산 비용이 증가한다.
4. 패딩(Padding) 처리와 마스킹(Masking)
실제 딥러닝 모델은 고정된 크기의 텐서를 입력으로 받지만, 문장의 길이는 제각각이다. 이를 해결하기 위해 패딩과 마스킹 기법을 사용한다.
- 패딩(Padding): 가장 긴 문장의 길이에 맞춰 짧은 문장의 빈 공간을 특정 값(보통
0)으로 채우는 기법이다.
- 마스킹(Masking): 패딩으로 채워진
0 값은 실제 의미가 없는 데이터이므로, 모델이 이를 학습에 반영하지 않도록 무시하는 처리 과정이다. 마스크 행렬을 사용하여 패딩 토큰에 해당하는 위치의 값을 매우 작은 음수($-\infty$)로 치환하거나, 어텐션 스코어 계산 시 제외하는 방식으로 처리하여 패딩 영역의 영향력을 제거한다.
5. 구현 및 활용 예제
PyTorch 프레임워크를 이용한 임베딩 층 구현 예시는 다음과 같다.
import torch
import torch.nn as nn
# 1. 환경 설정
vocab_size = 10 # 단어 사전 크기
embed_dim = 4 # 임베딩 차원
seq_len = 3 # 문장 길이 (단어 개수)
padding_idx = 0 # 패딩 토큰의 인덱스 설정
# 2. 임베딩 층 선언 (padding_idx를 설정하면 해당 인덱스의 벡터는 0으로 고정되며 학습되지 않음)
embedding_layer = nn.Embedding(vocab_size, embed_dim, padding_idx=padding_idx)
# 3. 입력 데이터 (정수 인덱스 형태의 텐서)
# 예: [1, 5, 2] (정상 문장), [3, 0, 0] (패딩이 포함된 짧은 문장)
input_indices = torch.LongTensor([[1, 5, 2], [3, 0, 0]]) # batch_size=2
# 4. 임베딩 층 통과
embedded_output = embedding_layer(input_indices)
print(f"입력 형태: {input_indices.shape}") # torch.Size([2, 3])
print(f"출력 형태: {embedded_output.shape}") # torch.Size([2, 3, 4])
print(embedded_output)
# 결과 확인 시 padding_idx=0인 위치의 벡터는 [0., 0., 0., 0.]으로 출력됨
6. 사전 학습된 임베딩 (Pre-trained Embedding)
모델을 처음부터 학습시키는 대신, 대규모 말뭉치(Wikipedia, Common Crawl 등)로 미리 학습된 임베딩 벡터를 가져와 사용하는 방식이다. 이는 전이 학습(Transfer Learning)의 일종으로, 데이터셋이 적은 환경에서 성능을 크게 향상시킨다.
주요 알고리즘 비교
| 알고리즘 |
핵심 원리 |
주요 특징 |
한계점 |
| Word2Vec |
주변 단어로 중심 단어 예측 (CBOW/Skip-gram) |
분포 가설 기반, 연산 속도 빠름 |
문맥에 따른 의미 변화 반영 불가 |
| GloVe |
전역 동시 등장 빈도(Co-occurrence) 분석 |
통계적 정보와 예측 모델의 결합 |
대규모 동시 등장 행렬 생성 비용 발생 |
| FastText |
단어를 n-gram 단위(Subword)로 분해 |
OOV(Out-of-Vocabulary) 문제 해결 가능 |
모델 크기가 커지고 학습 시간이 증가 |
미세 조정(Fine-tuning) 여부
- Frozen (고정): 사전 학습된 벡터를 그대로 사용하며 가중치를 업데이트하지 않는다. 학습 속도가 빠르고 과적합을 방지한다.
- Non-frozen (미세 조정): 사전 학습된 벡터를 초기값으로 사용하되, 현재 태스크에 맞게 가중치를 다시 학습시킨다. 도메인 특화 데이터셋일 때 성능이 더 좋다.
위에서 언급한 Word2Vec, GloVe, FastText는 단어당 하나의 고정된 벡터만 갖는 정적 임베딩(Static Embedding) 방식이다. 반면, BERT나 GPT와 같은 최신 모델은 문맥에 따라 동일한 단어라도 주변 단어와의 관계에 따라 다른 벡터로 변환하는 동적 임베딩(Contextualized Embedding) 방식을 사용하여 다의어 처리 능력을 획기적으로 높였다.
7. 유사도 측정 및 시각화
임베딩 벡터의 핵심은 거리 기반의 의미 표현이다. 두 단어 벡터 $\mathbf{u}$와 $\mathbf{v}$ 사이의 유사도는 주로 코사인 유사도(Cosine Similarity)로 측정한다.
$$\text{Cosine Similarity} = \frac{\mathbf{u} \cdot \mathbf{v}}{\|\mathbf{u}\| \|\mathbf{v}\|}$$
- 값의 범위: $-1$에서 $1$ 사이. $1$에 가까울수록 두 벡터의 방향이 일치하며 의미적으로 유사함을 뜻한다.
- 시각화: 고차원 벡터를 2차원이나 3차원으로 투영하기 위해 t-SNE나 PCA 알고리즘을 사용한다. 시각화 결과, '왕'과 '여왕', '사과'와 '배'와 같은 유사 단어들이 군집(Cluster)을 이루는 것을 확인할 수 있다.
8. 요약 및 비교
| 비교 항목 |
원-핫 인코딩 (One-hot) |
임베딩 층 (Embedding) |
| 표현 방식 |
희소 표현 (Sparse) |
밀집 표현 (Dense) |
| 차원 수 |
단어 사전 크기 ($V$) |
사용자 정의 저차원 ($d$) |
| 메모리 효율 |
매우 낮음 (대부분이 0) |
높음 (실수 값으로 채워짐) |
| 의미 관계 |
표현 불가 (모든 벡터 직교) |
표현 가능 (거리/각도로 표현) |
| 학습 여부 |
비학습 (Non-trainable) |
학습을 통해 최적화 가능 |
# Embedding Layer (임베딩 층)
## 1. 개요
**임베딩 층(Embedding Layer)**은 자연어 처리(NLP) 및 딥러닝 모델에서 정수 형태로 인코딩된 범주형 데이터(주로 단어 인덱스)를 고정된 크기의 연속적인 수치형 벡터로 변환하는 신경망 층이다.
컴퓨터는 텍스트를 직접 처리할 수 없으므로 수치화 과정이 필수적이다. 초기에는 단어의 존재 여부만을 표시하는 **원-핫 인코딩(One-hot Encoding)** 방식이 사용되었다. 원-핫 인코딩은 단어 집합의 크기가 $V$일 때, 해당 단어의 위치만 1이고 나머지는 모두 0인 $V$차원의 벡터로 표현하는 방식이다. 그러나 이 방식은 다음과 같은 치명적인 한계가 있다.
- **차원의 저주**: 단어 사전의 크기가 커질수록 벡터의 차원이 기하급수적으로 증가하여 메모리 낭비가 심하다.
- **의미론적 관계 부재**: 모든 단어 벡터 간의 내적이 0이 되므로, '강아지'와 '개'가 유사한 의미라는 관계를 수학적으로 표현할 수 없다.
임베딩 층은 이러한 희소 표현(Sparse Representation)을 저차원의 밀집 표현(Dense Representation)으로 변환함으로써 효율적인 연산과 의미론적 정보 보존을 가능하게 한다.
## 2. 동작 원리
임베딩 층은 내부적으로 **룩업 테이블(Lookup Table)** 구조를 가진 가중치 행렬(Weight Matrix)로 동작한다. 입력으로 들어온 정수 인덱스는 이 행렬의 행 번호로 사용되어, 해당 행에 저장된 벡터를 그대로 추출하는 방식으로 작동한다.
### 변환 과정 메커니즘
입력 데이터가 단어 인덱스 $i$일 때, 임베딩 행렬 $W$의 $i$번째 행을 추출하는 과정은 수학적으로 원-핫 벡터 $x_{one-hot}$와 행렬 $W$의 행렬 곱과 동일하다.
$$\text{Embedding}(x) = x_{one-hot} \cdot W$$
(여기서 $x_{one-hot}$은 $1 \times V$ 벡터, $W$는 $V \times d$ 행렬이며, 결과값은 $1 \times d$ 벡터가 된다.)
### 연산 방식 비교 도식
- **원-핫 인코딩 방식**: $\text{Input Index} \rightarrow \text{One-hot Vector} \rightarrow \text{Matrix Multiplication} \rightarrow \text{Dense Vector}$
- **임베딩 층 방식**: $\text{Input Index} \rightarrow \text{Lookup Table (Index-based Access)} \rightarrow \text{Dense Vector}$
*(임베딩 층은 불필요한 행렬 곱 연산을 생략하고 인덱스로 직접 접근하여 연산 효율성을 극대화한다.)*
| 단계 | 입력/연산 | 형태 (Shape) | 설명 |
| :--- | :--- | :--- | :--- |
| **입력** | 단어 인덱스 (Integer) | $(batch\_size, seq\_len)$ | 정수로 변환된 단어 시퀀스 |
| **매핑** | 가중치 행렬 $W$ | $(vocab\_size, embed\_dim)$ | 학습 가능한 임베딩 파라미터 행렬 |
| **출력** | 임베딩 벡터 (Float) | $(batch\_size, seq\_len, embed\_dim)$ | 각 단어가 밀집 벡터로 변환된 결과 |
## 3. 주요 특징 및 학습 방식
### 학습 가능한 가중치
임베딩 벡터의 값은 고정된 상수가 아니라, 모델의 다른 가중치들과 마찬가지로 **역전파(Backpropagation)** 알고리즘을 통해 학습된다. 모델이 주어진 태스크(예: 감성 분석, 기계 번역)를 수행하면서 손실 함수(Loss Function)를 최소화하는 방향으로 단어 벡터의 값들이 미세하게 조정된다. 결과적으로 유사한 문맥에서 자주 등장하는 단어들은 벡터 공간상에서 서로 가까운 위치에 배치되게 된다.
### 차원 수(Embedding Dimension) 결정
임베딩 차원($d$)은 하이퍼파라미터로 설정하며, 일반적으로 50, 100, 300, 768 등이 사용된다.
- **차원이 너무 낮으면**: 단어가 가진 복잡한 의미론적 정보를 충분히 담지 못해 표현력이 떨어진다.
- **차원이 너무 높으면**: 모델의 파라미터 수가 급증하여 과적합(Overfitting) 위험이 커지고 연산 비용이 증가한다.
## 4. 패딩(Padding) 처리와 마스킹(Masking)
실제 딥러닝 모델은 고정된 크기의 텐서를 입력으로 받지만, 문장의 길이는 제각각이다. 이를 해결하기 위해 패딩과 마스킹 기법을 사용한다.
- **패딩(Padding)**: 가장 긴 문장의 길이에 맞춰 짧은 문장의 빈 공간을 특정 값(보통 `0`)으로 채우는 기법이다.
- **마스킹(Masking)**: 패딩으로 채워진 `0` 값은 실제 의미가 없는 데이터이므로, 모델이 이를 학습에 반영하지 않도록 무시하는 처리 과정이다. 마스크 행렬을 사용하여 패딩 토큰에 해당하는 위치의 값을 매우 작은 음수($-\infty$)로 치환하거나, 어텐션 스코어 계산 시 제외하는 방식으로 처리하여 패딩 영역의 영향력을 제거한다.
## 5. 구현 및 활용 예제
PyTorch 프레임워크를 이용한 임베딩 층 구현 예시는 다음과 같다.
```python
import torch
import torch.nn as nn
# 1. 환경 설정
vocab_size = 10 # 단어 사전 크기
embed_dim = 4 # 임베딩 차원
seq_len = 3 # 문장 길이 (단어 개수)
padding_idx = 0 # 패딩 토큰의 인덱스 설정
# 2. 임베딩 층 선언 (padding_idx를 설정하면 해당 인덱스의 벡터는 0으로 고정되며 학습되지 않음)
embedding_layer = nn.Embedding(vocab_size, embed_dim, padding_idx=padding_idx)
# 3. 입력 데이터 (정수 인덱스 형태의 텐서)
# 예: [1, 5, 2] (정상 문장), [3, 0, 0] (패딩이 포함된 짧은 문장)
input_indices = torch.LongTensor([[1, 5, 2], [3, 0, 0]]) # batch_size=2
# 4. 임베딩 층 통과
embedded_output = embedding_layer(input_indices)
print(f"입력 형태: {input_indices.shape}") # torch.Size([2, 3])
print(f"출력 형태: {embedded_output.shape}") # torch.Size([2, 3, 4])
print(embedded_output)
# 결과 확인 시 padding_idx=0인 위치의 벡터는 [0., 0., 0., 0.]으로 출력됨
```
## 6. 사전 학습된 임베딩 (Pre-trained Embedding)
모델을 처음부터 학습시키는 대신, 대규모 말뭉치(Wikipedia, Common Crawl 등)로 미리 학습된 임베딩 벡터를 가져와 사용하는 방식이다. 이는 **전이 학습(Transfer Learning)**의 일종으로, 데이터셋이 적은 환경에서 성능을 크게 향상시킨다.
### 주요 알고리즘 비교
| 알고리즘 | 핵심 원리 | 주요 특징 | 한계점 |
| :--- | :--- | :--- | :--- |
| **Word2Vec** | 주변 단어로 중심 단어 예측 (CBOW/Skip-gram) | 분포 가설 기반, 연산 속도 빠름 | 문맥에 따른 의미 변화 반영 불가 |
| **GloVe** | 전역 동시 등장 빈도(Co-occurrence) 분석 | 통계적 정보와 예측 모델의 결합 | 대규모 동시 등장 행렬 생성 비용 발생 |
| **FastText** | 단어를 n-gram 단위(Subword)로 분해 | **OOV(Out-of-Vocabulary)** 문제 해결 가능 | 모델 크기가 커지고 학습 시간이 증가 |
### 미세 조정(Fine-tuning) 여부
- **Frozen (고정)**: 사전 학습된 벡터를 그대로 사용하며 가중치를 업데이트하지 않는다. 학습 속도가 빠르고 과적합을 방지한다.
- **Non-frozen (미세 조정)**: 사전 학습된 벡터를 초기값으로 사용하되, 현재 태스크에 맞게 가중치를 다시 학습시킨다. 도메인 특화 데이터셋일 때 성능이 더 좋다.
### 정적 임베딩 vs 동적 임베딩
위에서 언급한 Word2Vec, GloVe, FastText는 단어당 하나의 고정된 벡터만 갖는 **정적 임베딩(Static Embedding)** 방식이다. 반면, BERT나 GPT와 같은 최신 모델은 문맥에 따라 동일한 단어라도 주변 단어와의 관계에 따라 다른 벡터로 변환하는 **동적 임베딩(Contextualized Embedding)** 방식을 사용하여 다의어 처리 능력을 획기적으로 높였다.
## 7. 유사도 측정 및 시각화
임베딩 벡터의 핵심은 **거리 기반의 의미 표현**이다. 두 단어 벡터 $\mathbf{u}$와 $\mathbf{v}$ 사이의 유사도는 주로 **코사인 유사도(Cosine Similarity)**로 측정한다.
$$\text{Cosine Similarity} = \frac{\mathbf{u} \cdot \mathbf{v}}{\|\mathbf{u}\| \|\mathbf{v}\|}$$
- **값의 범위**: $-1$에서 $1$ 사이. $1$에 가까울수록 두 벡터의 방향이 일치하며 의미적으로 유사함을 뜻한다.
- **시각화**: 고차원 벡터를 2차원이나 3차원으로 투영하기 위해 **t-SNE**나 **PCA** 알고리즘을 사용한다. 시각화 결과, '왕'과 '여왕', '사과'와 '배'와 같은 유사 단어들이 군집(Cluster)을 이루는 것을 확인할 수 있다.
## 8. 요약 및 비교
| 비교 항목 | 원-핫 인코딩 (One-hot) | 임베딩 층 (Embedding) |
| :--- | :--- | :--- |
| **표현 방식** | 희소 표현 (Sparse) | 밀집 표현 (Dense) |
| **차원 수** | 단어 사전 크기 ($V$) | 사용자 정의 저차원 ($d$) |
| **메모리 효율** | 매우 낮음 (대부분이 0) | 높음 (실수 값으로 채워짐) |
| **의미 관계** | 표현 불가 (모든 벡터 직교) | 표현 가능 (거리/각도로 표현) |
| **학습 여부** | 비학습 (Non-trainable) | 학습을 통해 최적화 가능 |