Fast Text

Juppi·2022년 12월 17일
0

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.skipgramfasttext.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://wikidocs.net/22883

https://frhyme.github.io/nlp/fasttext_pretrained_wiki/
https://nodoudt.tistory.com/24

profile
잠자면서 돈버는 그날까지

0개의 댓글