FastText Pre-trained 한국어 모델 사용기

2019-07-22

1. FastText 소개

FastText는 Facebook에서 만든 word representation 과 sentence classification의 효율적인 학습을 위한 라이브러리입니다.

일반적으로 자연어처리에서 말뭉치 사전 데이터 수집하고 전처리하는 데 많은 시간이 소요됩니다.

그런데 facebook에서 fasttext를 소개하면서 무려 157개국의 언어에 대해 common crawler와 wikipedia의 데이터를 학습한 Pre-trained model을 제공하고 있습니다.

한국어도 제공하고 있습니다. 만세!

글에서는 미리 훈련된 데이터가 어느정도 성능이 나올 지 테스트 해보았습니다.

2. Fast Text 설치 및 pre-trained 모델 다운받기

FastText는 공개된 github 저장소 https://github.com/facebookresearch/fastText.git를 clone해서 하거나, gensim 이라는 파이썬 패키지에 포함되어 있어 gensim을 설치해서 사용할 수 있습니다.

여기서는 gensim을 설치해서 사용해보았습니다.

pip install gensim

미리 훈련된 한국어 모델은 데이터는 https://fasttext.cc/docs/en/crawl-vectors.html에서 제공하고 있습니다.

모델은 .vec .bin 의 두 가지 형태의 파일로 제공 하고 있는데, .vec 파일은 라인마다 단어에 대한 vector가 있는 형태이고 .bin 파일은 벡터 뿐만 아니라 dictionary와 모델의 하이퍼 파라미터와 같은 정보들이 모두 들어있는 형태입니다.

binary 파일을 사용하면 모델을 추가로 학습해서 개선할 수 있다고 합니다.

둘다 다운 받고 압축을 풀었보았습니다. (모델을 읽어서 쓸 때는 굳이 압축을 풀지 않고 사용해도 됩니다.)

gunzip cc.ko.300.vec.gz
gunzip cc.ko.300.bin.gz

(압축을 푸니 gunzip cc.ko.300.vec 은 4.5GB, gunzip cc.ko.300.bin 은 7.2GB로 용량이 매우 컸습니다. ㄷㄷ)

3. Pre-trained 한국어 모델 적용

미리 훈련된 모델로 비슷한 단어 추출해보기

훈련된 모델을 이용해서 파이썬 이라는 단어와 유사한 단어를 출력해보았습니다.

모델 파일의 크기가 매우 커서 그런지 모델을 로딩하는 시간이 거의 3분~4분 정도 걸립니다. (테스트 할때마다 시간이 오래걸려, 코드를 짤 때는 다른 테스트용 모델로 작업하고 모델만 바꿔서 돌렸습니다.)

from gensim import models

ko_model = models.fasttext.load_facebook_model('cc.ko.300.bin')

for w, sim in m_fasttext.similar_by_word('파이썬', 10):
    print(f'{w}: {sim}')

파이썬과 유사한 단어 결과:

Python: 0.565061628818512
자이썬: 0.5624369382858276
레일스: 0.5598082542419434
파이썬을: 0.5595801472663879
언어용: 0.5288202166557312
파이썬의: 0.5250024795532227
프로그래밍: 0.5225088000297546
wxPython: 0.5222088098526001
파이썬이나: 0.5201171636581421
함수형: 0.5187377333641052

아이언맨과 유사한 단어 결과:

아이언맨2: 0.6507514119148254
아이언맨과: 0.6068165302276611
아이언맨에: 0.5806230306625366
아이언맨의: 0.5622424483299255
스파이더맨: 0.5526455044746399
아이언맨3: 0.5465470552444458
아이언맨은: 0.5207207798957825
가디언즈오브갤럭시: 0.5029110908508301
헐크버스터: 0.5008623600006104
어벤져스: 0.4941202402114868

단어 간 유사도 비교

다음과 같이 단어의 유사도도 쉽게 비교해 볼 수 있습니다.

print(f"'아이언맨'과 '헐크'의 유사도: {m_fasttext.similarity('아이언맨', '헐크')}")
print(f"'아이언맨'과 '스파이더맨'의 유사도: {m_fasttext.similarity('아이언맨', '스파이더맨')}")
'아이언맨'과 '헐크'의 유사도: 0.4033605754375458
'아이언맨'과 '스파이더맨'의 유사도: 0.5526454448699951

아이언맨은 스파이더맨과 더 친한 것으로..

단어 벡터 시각화

이번에는 차원축소기법인 PCA를 사용해서 단어 벡터들을 2차원으로 축소시키고, 다음과 같이 2차원 그래프에 표현해보았습니다.

from sklearn.decomposition import PCA

words = [
    '사과',
    '바나나',
    '오렌지',
    '키위',
    '스파이더맨', 
    '아이언맨', 
    '헐크',
    '타노스',
    '캡틴아메리카',
    '어벤져스'
]
# matplotplib 폰트 설정을 안해서 그래프에서 한국어 라벨이 깨져서 아래 단어로 임시처리했습니다. ㅠ
word_labels = [
    'apple',
    'banana',
    'orange',
    'kiwi',
    'spider man', 
    'iron man', 
    'hulk',
    'thanos',
    'captin america',
    'avengers'
]
pca = PCA(n_components=2)
xys = pca.fit_transform([m_fasttext.wv.word_vec(w) for w in words])
xs = xys[:,0]
ys = xys[:,1]
plt.figure(figsize=(14, 10))
plt.scatter(xs, ys, marker='o')
for i, v in enumerate(word_labels):
    plt.annotate(v, xy=(xs[i], ys[i]))

결과:

그래프에서 사과, 바나나, 키위 같은 과일 단어들은 그리 가깝게 뭉쳐지진 않았지만, 아이언앤, 스파이더맨, 어벤져스 등의 특정 고유명사들은 연관된 단어들끼리 잘 뭉쳐진 걸 확인할 수 있었습니다. (왠일인지 헐크는 저멀리 떨어져 있지만…)

느낀점

  • pre-trained 모델이 생각보다 괜찮은 것 같은데, 모델을 로딩하는 시간이 매우 느립니다. ㅠ
  • 훈련된 모델에 데이터를 추가해서 더 학습이 가능한 걸로 보여서 특정 도메인에 맞는 학습 데이터를 더 수집해서 성능을 비교해보면 좋을 것 같습니다.
  • fasttext를 테스트해보면서 다른 공개된 한국어 모델이나 데이터셋을 찾아봤는데, 잘 정리된 곳을 찾진 못해서 따로 정리해보면 좋을 것 같습니다.