FastText
FastText
문자 n-gram을 사용한 임베딩. 미등록어(OOV) 처리에 강점.
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 차원
"스팸 분류기 빨리 만들어야 하는데 FastText로 먼저 baseline 잡겠습니다. GPU 없이도 CPU로 학습 30분이면 되고, 정확도 90% 넘으면 일단 배포하고, 나중에 BERT로 고도화하는 게 효율적일 것 같아요."
"제품 검색에 FastText 임베딩 쓰면 좋을 것 같습니다. 신제품명이 계속 추가되는데 FastText는 subword 기반이라 학습 안 된 제품명도 비슷한 제품 벡터를 만들어줘요. 'iPhone15ProMax'가 학습 데이터에 없어도 'iPhone', 'Pro', 'Max' n-gram으로 벡터를 만들 수 있거든요."
"FastText가 Word2Vec보다 좋은 점은 OOV 처리입니다. Word2Vec은 학습 안 된 단어가 나오면 UNK 토큰으로 퉁치는데, FastText는 문자 n-gram 벡터 합으로 의미 있는 벡터를 만들어요. 오타나 신조어가 많은 SNS 데이터 분석에서 특히 효과적입니다."
FastText는 띄어쓰기 기반으로 동작하므로, 교착어인 한국어에서는 "먹었다", "먹고", "먹으면"이 다른 단어로 인식됩니다. 형태소 분석기(Mecab, Komoran 등)로 전처리하면 "먹+었+다"처럼 분리되어 의미 학습이 개선됩니다.
FastText 사전 학습 모델(cc.ko.300.bin)은 약 4.5GB로 상당히 큽니다. 서버 배포 시 메모리 8GB 이상 필요합니다. fasttext.util.reduce_model()로 차원을 줄이거나, .vec 파일(텍스트 형식)로 필요한 단어만 추출해서 사용하세요.
supervised 학습 시 레이블 형식은 반드시 "__label__레이블명"이어야 합니다. 공백으로 구분되므로 레이블에 공백이 있으면 안 됩니다. 멀티레이블 분류는 "__label__A __label__B 텍스트" 형식으로 여러 레이블을 지정하세요.