Fast Text
Fast Text
“Fast Text”란?
- 단어를 벡터로 임베딩하는 방법 중 하나
- 매커니즘 자체는 word2vec의 확장이라고 볼 수 있지만, word2vec은 “단어”를 쪼개질 수 없는 단위로 생각한다면, Fast Text는 하나의 단어 안에도 여러 단어들이 존재하는 것으로 간주함
- 즉, 내부 단어(subword)를 고려하여 학습 !
내부 단어 (subword)
-
Fast Text에서 각 단어는 글자 단위 n-gram의 구성으로 취급함
-
n을 몇으로 결정하는지에 따라 단어들이 얼마나 분리되는지 결정
-
n = 3, trigram
apple →
<ap,app,ppl,ple,pl>apple을 위 처럼 분리하고, 양 끝에 시작과 끝을 의미하는 <, > 을 도입하여 5개의 내부 단어 토큰을 생성함
여기에 추가적으로 기존단어에 <, >를 붙인 특별 토큰
<apple>을 추가함정리하자면, n = 3인 경우 apple이라는 단어에 대해서 Fast Text는 아래의 내부 단어 토큰을 벡터화 함
<ap,app,ppl,ple,le>,<apple> -
실제로 사용할 때는 n의 최솟값과 최대값으로 범위를 설정 가능
-
min = 3, max = 6
<ap,app,ppl,ppl,le>,<app,appl,pple,ple>,<appl,pple>, …,<apple>
-
-
subword를 벡터화한다는 것 = subword들에 대해서 Word2Vec을 수행한다는 것
-
subword들의 벡터값을 얻었다면, 단어 apple의 벡터값은 subword들의 벡터값의 총 합으로 구성 !
-
해당 방법은 Word2Vec에서는 얻을 수 없었던 강점을 가짐
Out Of Vocabulary 에 대한 대응
- Fast Text의 인공 신경망을 학습한 후에는 데이터 셋의 모든 단어의 각 n-gram에 대해 워드 임베딩이 됨
- 장점 : 데이터셋만 충분하다면 위와 같은 내부단어를 통해 OOV에 대해서도 다른 단어와의 유사도를 계산할 수 있다는 점
- birthplace란 단어를 학습하지 않은 상태
- 하지만, birth와 place라는 내부단어가 있었다면, Fast Text는 birthplace의 벡터를 얻을 수 있음
단어 집합 내 빈도 수가 적었던 단어(Rare Word)에 대한 대응
-
word2vec의 경우, 등장 빈도 수가 적은 단어(rare word)에 대해서는 임베딩 정확도가 높지 않다는 단점이 존재함
참고할 수 있는 경우의 수가 적다보니 정확하게 임베딩이 안되는 것
-
하지만 Fast Text의 경우, 단어가 rare word이더라도, 그 단어의 n-gram이 다른 단어의 n-gram과 겹치는 경우라면 word2vec과 비교하여 비교적 높은 임베딩 벡터 값을 얻을 수 있음 !
-
FastText가 노이즈가 많은 코퍼스에서 강점을 가진 것 또한 위와 같은 이유
- 모든 훈련 코퍼스에 오타(Typo)나 맞춤법이 틀린 단어가 없으면 이상적이겠지만, 실제 많은 비정형 데이터에는 오타가 섞여있음
- 그리고 오타가 섞인 단어는 당연히 등장 빈도수가 매우 적으므로 일종의 희귀 단어가 됨.
- 즉, Word2Vec에서는 오타가 섞인 단어는 임베딩이 제대로 되지 않지만 FastText는 이에 대해서도 일정 수준의 성능을 보일 수 있음
- 단어 apple과 오타로 p를 한 번 더 입력한 appple의 경우에는 실제로 많은 개수의 동일한 n-gram을 가질 것임
Python 으로 Fast Text 사용하기
Python 2.6이나 최신버전. C++ 확장을 빌드하려면 Cython이 필요하다
install
pip install fasttest
사용 예
이 패키지는 단어 표현, 텍스트 분류라는 두 가지의 주요 유스케이스를 가지고 있음.
단어표현 학습
논문 1에 나온 것과 같이 단어벡터를 학습하기 위해, fasttext.skipgram과 fasttext.cbow 함수를 아래와 같이 사용
import fasttext
# Skipgram model
model = fasttext.skipgram('data.txt', 'model')
print model.words
# CBOW model
model = fasttext.cbow('data.txt', 'model')
print model.words
data.txt는 utf-8로 인코딩된 텍스트를 포함하는 훈련 파일 디폴트로 단어 벡터들은 3에서 6자의 문자 n그램을 받음
최적화를 마치면, 프로그램은 두 개의 파일을 저장 -> model.bin, model.vec
model.vec 각 라인당 하나씩의 단어벡터를 갖고있는 텍스트 파일
model.bin 사전과 모든 하이퍼파라미터와 함께 모델의 파라미터를 포함하는 이진파일 이진파일은 이후에 단어벡터를 계산하거나 최적화를 재시작할 때 사용 가능
아래 fasttext(1) 명령은 동일한 기능을 수행
# Skipgram model
./fasttext skipgram -input data.txt -output model
# CBOW model
./fasttext cbow -input data.txt -output model
사전에 없는 단어에 대한 단어벡터 구하기
이전에 훈련된 모델은 사전에 없는 단어벡터를 계산하는데 사용될 수 있음
python print model['king'] # get the vector of the word 'king'
아래 fasttext(1) 명령은 위와 동일
shell echo "king" | ./fasttext print-vectors model.bin
단어 king의 벡터를 표준 출력으로 출력할 것 !
pre-trained 모델 로드하기
우리는 fasttext.load_model을 pre-trained 모델을 로드하기 위해 사용할 수 있음
model = fasttext.load_model('model.bin')
print model.words # list of words in dictionary
print model['king'] # get the vector of the word 'king'
텍스트 분류
이 패키지는 지도된 텍스트 분류 훈련에 사용될 수 있음 그리고 fastText로 pre-train된 분류기를 로드하는데 사용될 수 있음
분류기를 학습하기 위해, 아래 함수를 사용 가능
classifier = fasttext.supervised('data.train.txt', 'model')
아래 fasttext(1) 명령은 위와 동일합니다:
shell ./fasttext supervised -input data.train.txt -output model
data.train.txt은 각 라인에 라벨과 함께 학습 문장을 포함하는 텍스트 파일
디폴트로, 라벨은 문자열 label 이 앞에 붙은 단어 !
label_prefix 파라미터로 라벨의 접두사를 정의할 수 있습니다
classifier = fasttext.supervised('data.train.txt', 'model', label_prefix='__label__')
아래 fasttext(1) 명령은 위와 동일
shell./fasttext supervised -input data.train.txt -output model -label '__label__'
위 명령은 두 개의 파일을 출력합 -> model.bin, model.vec
모델이 학습되면, 우리는 test 셋에서 classifier.test 함수를 사용해서 1에서의 정확도(P@1)와 리콜(R@1)을 계산함으로써 이를 평가 가능
result = classifier.test('test.txt')
print 'P@1:', result.precision
print 'R@1:', result.recall
print 'Number of examples:', result.nexamples
아래 명령은 위와 동일
shell./fasttext test model.bin test.txt
텍스트 리스트에서 가장 가능성이 높은 라벨을 얻기 위해, classifier.predict 를 사용
texts = ['example very long text 1', 'example very long text 2']
labels = classifier.predict(texts)
print labels
# Or with the probability
labels = classifier.predict_proba(texts)
print labels
분류기로부터 k개의 상위 라벨을 얻기 위해 k 값을 명시 가능
labels = classifier.predict(texts, k=3)
print labels
# Or with the probability
labels = classifier.predict_proba(texts, k=3)
print labels
이 인터페이스는 fasttext(1) 예측 명령과 동일 같은 입력 셋을 사용한 같은 모델은 같은 예측을 가짐 !
reference
https://frhyme.github.io/nlp/fasttext_pretrained_wiki/ https://nodoudt.tistory.com/24