🤖 AI/ML

FastText

FastText

문자 n-gram을 사용한 임베딩. 미등록어(OOV) 처리에 강점.

📖 상세 설명

FastText는 Facebook AI Research(현 Meta AI)에서 2016년 개발한 단어 임베딩 및 텍스트 분류 라이브러리입니다. Word2Vec의 확장으로, 단어를 문자 n-gram의 합으로 표현하여 미등록어(OOV, Out-of-Vocabulary) 문제를 해결합니다. 157개 언어에 대한 사전 학습 모델을 제공하며, 한국어도 포함되어 있습니다.

FastText의 핵심 혁신은 subword 정보 활용입니다. "apple"이라는 단어를 "<ap", "app", "ppl", "ple", "le>"과 같은 n-gram으로 분해하고, 각 n-gram 벡터의 합으로 단어 벡터를 구성합니다. 이를 통해 학습 데이터에 없던 "apples", "pineapple" 같은 단어도 의미 있는 벡터를 얻을 수 있습니다.

FastText는 두 가지 모드를 지원합니다. Skipgram/CBOW 모드는 Word2Vec과 유사하게 단어 임베딩을 학습하고, Supervised 모드는 텍스트 분류를 수행합니다. 텍스트 분류에서 FastText는 deep learning 모델보다 학습 속도가 수백 배 빠르면서도 비슷한 정확도를 달성하여, 리소스가 제한된 환경에서 유용합니다.

실무에서 FastText는 빠른 프로토타이핑과 기준선(baseline) 모델로 활용됩니다. 스팸 분류, 언어 감지, 감성 분석 등에서 CPU만으로도 초당 수십만 건을 처리할 수 있습니다. 한국어 NLP에서는 형태소 분석 없이도 어느 정도 작동하지만, 형태소 분석을 적용하면 성능이 크게 향상됩니다.

💻 코드 예제

import fasttext
import fasttext.util
import numpy as np

# 1. 사전 학습된 한국어 모델 다운로드 및 로드
fasttext.util.download_model('ko', if_exists='ignore')  # 약 4.5GB
model = fasttext.load_model('cc.ko.300.bin')

# 단어 벡터 얻기
word_vector = model.get_word_vector("인공지능")
print(f"벡터 차원: {word_vector.shape}")  # (300,)

# 유사 단어 찾기
similar_words = model.get_nearest_neighbors("인공지능", k=5)
print("유사 단어:", similar_words)

# OOV 단어도 벡터 생성 가능 (FastText의 강점)
oov_vector = model.get_word_vector("인공지능개발자")
print("OOV 단어 벡터도 생성됨:", oov_vector[:5])

# 2. 텍스트 분류 모델 학습
# 학습 데이터 형식: __label__레이블 텍스트
# train.txt 예시:
# __label__positive 이 영화 정말 재미있어요
# __label__negative 시간 낭비였습니다

# 분류 모델 학습
classifier = fasttext.train_supervised(
    input='train.txt',
    epoch=25,
    lr=0.5,
    wordNgrams=2,  # bi-gram 사용
    dim=100,
    loss='softmax'
)

# 예측
prediction = classifier.predict("정말 좋은 제품이에요")
print(f"예측: {prediction}")  # (('__label__positive',), array([0.98]))

# 여러 문장 예측
texts = ["최악이에요", "추천합니다", "그냥 그래요"]
predictions = classifier.predict(texts)
print("배치 예측:", predictions)

# 모델 평가
result = classifier.test("test.txt")
print(f"정확도: {result[1]:.4f}")

# 3. 커스텀 임베딩 학습
# corpus.txt: 한 줄에 하나의 문장
custom_model = fasttext.train_unsupervised(
    input='corpus.txt',
    model='skipgram',  # 또는 'cbow'
    dim=100,
    minCount=5,
    minn=2,  # 최소 n-gram 길이
    maxn=5,  # 최대 n-gram 길이
    epoch=5
)

# 모델 저장
custom_model.save_model("my_fasttext.bin")

# 차원 축소 (메모리 절약)
fasttext.util.reduce_model(model, 100)  # 300 -> 100 차원

🗣️ 실무에서 이렇게 말하세요

NLP 프로젝트 킥오프 미팅에서

"스팸 분류기 빨리 만들어야 하는데 FastText로 먼저 baseline 잡겠습니다. GPU 없이도 CPU로 학습 30분이면 되고, 정확도 90% 넘으면 일단 배포하고, 나중에 BERT로 고도화하는 게 효율적일 것 같아요."

데이터 팀과 기술 논의 중

"제품 검색에 FastText 임베딩 쓰면 좋을 것 같습니다. 신제품명이 계속 추가되는데 FastText는 subword 기반이라 학습 안 된 제품명도 비슷한 제품 벡터를 만들어줘요. 'iPhone15ProMax'가 학습 데이터에 없어도 'iPhone', 'Pro', 'Max' n-gram으로 벡터를 만들 수 있거든요."

ML 엔지니어 면접에서

"FastText가 Word2Vec보다 좋은 점은 OOV 처리입니다. Word2Vec은 학습 안 된 단어가 나오면 UNK 토큰으로 퉁치는데, FastText는 문자 n-gram 벡터 합으로 의미 있는 벡터를 만들어요. 오타나 신조어가 많은 SNS 데이터 분석에서 특히 효과적입니다."

⚠️ 흔한 실수 & 주의사항

1
한국어에서는 형태소 분석 권장

FastText는 띄어쓰기 기반으로 동작하므로, 교착어인 한국어에서는 "먹었다", "먹고", "먹으면"이 다른 단어로 인식됩니다. 형태소 분석기(Mecab, Komoran 등)로 전처리하면 "먹+었+다"처럼 분리되어 의미 학습이 개선됩니다.

2
사전 학습 모델 용량 주의

FastText 사전 학습 모델(cc.ko.300.bin)은 약 4.5GB로 상당히 큽니다. 서버 배포 시 메모리 8GB 이상 필요합니다. fasttext.util.reduce_model()로 차원을 줄이거나, .vec 파일(텍스트 형식)로 필요한 단어만 추출해서 사용하세요.

3
분류 모델 학습 데이터 형식

supervised 학습 시 레이블 형식은 반드시 "__label__레이블명"이어야 합니다. 공백으로 구분되므로 레이블에 공백이 있으면 안 됩니다. 멀티레이블 분류는 "__label__A __label__B 텍스트" 형식으로 여러 레이블을 지정하세요.

🔗 관련 용어

📚 더 배우기