텍스트 벡터화: FastText의 이해

Subword 정보를 활용한 단어 임베딩

자연어 처리(NLP)에서 단어를 내부 단어(subword)의 벡터 합으로 표현하는 FastText 모델의 원리와 특징을 소개한다. OOV 문제 해결 및 형태론적 정보 활용의 이점을 살펴본다.

NLP
Deep Learning
저자

Kwangmin Kim

공개

2025년 01월 08일

1 요약

이 문서는 기존 Word2Vec이나 GloVe와 달리 단어를 내부 단어(subword)들의 집합으로 간주하여 임베딩하는 FastText 모델의 기본 원리를 설명한다.

  • 기존 방법의 한계와 FastText의 접근법:
    • Word2Vec, GloVe 등은 단어를 하나의 단위로 취급하여 OOV(Out-of-Vocabulary) 문제에 취약하고, 단어 내부의 형태론적 정보를 활용하기 어렵다는 한계가 있다.
    • FastText는 단어를 문자 n-gram(character n-grams)으로 분해하고, 이 n-gram 벡터들의 합으로 단어 벡터를 표현함으로써 이러한 문제를 해결하고자 한다.
  • FastText의 특징:
    • Subword 정보 활용: 각 단어는 고유 벡터와 함께 해당 단어를 구성하는 모든 문자 n-gram 벡터들의 합으로 표현된다.
    • OOV 문제 완화: 훈련 시 보지 못한 단어라도, 구성 n-gram이 훈련 데이터에 존재하면 해당 n-gram 벡터들을 조합하여 의미적으로 유사한 벡터를 생성할 수 있다.
    • 형태론적 정보 포착: 어근이나 접사와 같은 형태론적 특징을 공유하는 단어들은 유사한 n-gram을 공유하게 되어, 결과적으로 유사한 임베딩 벡터를 갖게 된다. 이는 특히 교착어에서 유용하다.
  • 결론: FastText가 subword 정보를 활용하여 OOV 문제 및 희귀 단어 처리에 강점을 가지며, 형태론적 특징을 임베딩에 반영하는 방식을 소개하고 정적 임베딩 분야에서의 의미를 요약한다.

2 텍스트 인코딩 및 벡터화

텍스트 벡터화
├── 1. 전통적 방법 (통계 기반)
│   ├── BoW
│   ├── DTM
│   └── TF-IDF
│
├── 2. 신경망 기반 (문맥 독립)
│   ├── 문맥 독립적 임베딩
│   │   └── Embedding Layer (딥러닝 모델 내 구성 요소)
│   ├── Word2Vec (CBOW, Skip-gram)
│   ├── FastText
│   ├── GloVe
│   └── 기타 모델: Swivel, LexVec 등
│
└── 3. 문맥 기반 임베딩 (Contextual Embedding)
    └── RNN 계열
        ├── LSTM
        ├── GRU
        └── ELMo

3 신경망 사용 (2008~2018): Static Word Embedding

3.1 FastText (2017)

  • Sub-word 정보 활용
  • 단어를 character n-gram으로 분해
  • 예: “apple” → {“ap”, “pp”, “pl”, “le”} + “apple”
  • 장점:
    • OOV(Out-of-Vocabulary) 문제 해결
    • 형태학적 정보 포착
    • 한국어와 같은 교착어에 효과적

3.1.1 기존 방법의 한계

  • Word2Vec/GloVe 문제:

    # 훈련 데이터에 없는 단어 (OOV)
    "사과" → [0.2, 0.4, 0.1, ...]  ✓ (학습됨)
    "사과들" → ???  ✗ (학습 안됨)
    "사과나무" → ???  ✗ (학습 안됨)
  • 한국어의 특별한 어려움:

    "먹다" → "먹는다", "먹었다", "먹고", "먹어서", "먹지만", ...
    수천 가지 변형이 가능하지만 모두 같은 어근 "먹"을 공유

3.1.2 FastText의 해결책

  • Subword 분해
  • Character n-gram 분해
    • 예시: “사과” (n=2,3으로 설정)
"사과" 분해:
- 2-gram: "<사", "사과", "과>"  # <, >는 단어 경계 표시
- 3-gram: "<사과", "사과>"
- 전체 단어: "사과"

최종 n-gram 집합: {"<사", "사과", "과>", "<사과", "사과>", "사과"}
  • 벡터 표현
    • 기존 Word2Vec:

      vector("사과") = lookup_table["사과"]  # 하나의 벡터
    • FastText:

      vector("사과") = vector("<사") + vector("사과") + vector("과>") + 
            vector("<사과") + vector("사과>") + vector("사과")
            # n-gram 벡터들의 합
  • OOV 문제 해결 과정
    • 새로운 단어 처리
    # 훈련 시 보지 못한 단어: "사과나무"
    
    # 1단계: n-gram 분해
    "사과나무" → {"<사", "사과", "과나", "나무", "무>", "<사과", "사과나", "과나무", "나무>", "사과나무"}
    
    # 2단계: 학습된 n-gram 벡터 찾기
    "<사": [0.1, 0.2, ...]     ✓ (있음)
    "사과": [0.3, 0.1, ...]    ✓ (있음)  
    "과나": [0.0, 0.0, ...]    ✗ (없음 → 0벡터)
    "나무": [0.2, 0.4, ...]    ✓ (있음)
    "무>": [0.1, 0.1, ...]     ✓ (있음)
    
    # 3단계: 합계 계산
    vector("사과나무") = sum(존재하는_ngram_벡터들) / 개수
    • 결과: “사과나무”는 “사과”와 “나무”의 의미를 모두 반영한 벡터를 얻음!
  • 형태학적 정보 포착
    • 한국어 예시
    훈련 데이터:
    "먹는다" → {"<먹", "먹는", "는다", "다>", ...}
    "먹었다" → {"<먹", "먹었", "었다", "다>", ...}  
    "먹고" → {"<먹", "먹고", "고>", ...}
    
    # 공통 n-gram "<먹", "먹"이 반복 학습됨
    # → "먹" 관련 의미가 강화됨
    
    새로운 단어 "먹거나":
    {"<먹", "먹거", "거나", "나>", ...}
    # "<먹" n-gram을 통해 "먹다"와 관련된 의미를 자동으로 얻음!
    • 영어 예시
    "running""run"
    "running" → {"ru", "un", "nn", "ni", "in", "ng", "run", "unn", "nni", ...}
    "run" → {"ru", "un", "run", ...}
    
    공통 부분: {"ru", "un", "run"}을 통해 관계 학습

3.1.3 실제 성능 비교

  • 한국어 형태소 분석 없이도 효과적
  • Word2Vec:
"좋다": [0.2, 0.4, 0.1, ...]
"좋은": ??? (없으면 <UNK>)
"좋아서": ??? (없으면 <UNK>)
  • FastText:
"좋다": [0.2, 0.4, 0.1, ...]
"좋은": [0.18, 0.38, 0.12, ...]  # "좋" n-gram으로 유추
"좋아서": [0.19, 0.39, 0.11, ...]  # "좋" n-gram으로 유추
  • 결과: 형태소 분석기 없이도 어근의 의미를 공유하는 벡터들을 얻을 수 있음!
  • Trade-off:
    • 장점: OOV 해결, 형태학적 정보 포착
    • 단점: n-gram 개수만큼 파라미터 증가
  • Word2Vec: 단어 수 × 벡터 차원
  • FastText: (단어 수 + 모든_ngram_수) × 벡터 차원

실용적 해결책: 빈도가 낮은 n-gram은 제외하여 크기 조절

4 결론

본 문서에서는 단어를 문자 n-gram들의 합으로 표현하여 임베딩하는 FastText 모델의 기본적인 아이디어와 작동 방식을 살펴보았다. FastText는 Word2Vec의 Skip-gram 모델을 기반으로 하면서 subword 정보를 추가적으로 활용하는 것이 핵심이다.

  • FastText의 주요 특징:
    • Subword 단위 임베딩: 단어를 더 작은 단위인 문자 n-gram으로 분해하고, 각 n-gram에 대한 임베딩 벡터를 학습한다. 최종 단어 임베딩은 해당 단어를 구성하는 n-gram 벡터들의 합 (또는 평균)으로 구성된다. 이로 인해 단어의 내부 구조와 형태론적 특징을 포착할 수 있다.
    • OOV 문제 대처: 훈련 말뭉치에 등장하지 않은 단어(OOV)에 대해서도, 해당 단어의 n-gram들이 훈련 과정에서 학습되었다면, 이를 조합하여 새로운 단어의 벡터를 추정할 수 있다. 이는 Word2Vec이나 GloVe가 OOV 단어에 대해 특별한 토큰(예: <UNK>)으로 처리하거나 무시하는 것과 대조적이다.
    • 희귀 단어 및 형태소 풍부 언어에 유리: 등장 빈도가 낮은 희귀 단어의 경우에도 구성 n-gram 정보를 통해 상대적으로 안정적인 임베딩을 얻을 수 있으며, 한국어와 같이 어미나 조사가 다양하게 변하는 교착어에서 형태론적 유사성을 잘 반영할 수 있다.
  • FastText의 의미:
    • FastText는 단어 자체뿐만 아니라 단어를 구성하는 내부 요소(subword)까지 고려함으로써 기존 정적 임베딩 방법론들의 한계를 일부 개선했다. 특히 OOV 문제에 대한 실용적인 해결책을 제시하고, 단어의 형태론적 정보를 임베딩에 자연스럽게 통합했다는 점에서 의미가 있다.
    • Word2Vec, GloVe와 함께 FastText는 다양한 NLP 문제에서 효과적인 단어 표현 방법으로 활용되며, 정적 임베딩 기법의 중요한 갈래를 형성한다.

결론적으로, FastText는 subword 정보를 활용하여 단어 벡터의 표현력을 높이고 OOV 문제에 강인함을 보이는 유용한 정적 임베딩 방법이다. 단순하면서도 효과적인 아이디어로 많은 자연어 처리 응용 분야에 기여했다.

Subscribe

Enjoy this blog? Get notified of new posts by email: