word2vec 기초개념 및 구현실습

2019-05-08

Data_Engineering_TIL_(20190508)

study program : https://www.fastcampus.co.kr/extension_des

[학습목표]

  • word2vec 기초개념 이해

[학습기록]

1. 자연어처리 관련 기초용어

1) Corpus (말뭉치)

  • 언어 연구를 위해 텍스트를 컴퓨터가 읽을 수 있는 형태로 모아 놓은 언어 자료

2) Semantics (의미)

  • 언어의 뜻이나 의미

3) Word Embedding

  • 단어를 벡터로 표현하여 의미를 나타내는 방법

  • word2vec과 같은 말

4) CBOW (Continuous Bag-of-Words)

  • 주변 단어를 가지고 가운데 들어갈 단어를 예측하는 모델

5) Skip-Gram

  • 단어 하나를 가지고 주변에 나올 단어를 예측 모델

  • 성능이 좋고 트레이닝 속도가 빨라서 인기

2. Word Embedding(word2vec) 개요

  • 인간의 언어는 단어와 의미가 연결되어 있다.

ex) ‘컴퓨터’를 생각하면 ‘데스크탑’과 ‘노트북’이 떠오른다.

  • one-hot encoding

ex)

1) 컴퓨터 : [0,0,0,0,0,0,1,0,0,0]

2) 노트북 : [0,0,0,0,0,0,0,1,0,0]

3) 슈퍼컴퓨터 : [0,0,0,0,0,0,0,0,1,0]

위와 같이 10차원 백터로 한다면 - 10가지의 단어를 표현할 수 있다.

일상단어를 표현하려면 2만 ~ 5만차원, 큰 단어목록은 50만차원 정도가 필요하다고 한다.

원핫인코딩은 단어사이의 관계를 표현할 수 없다는 한계가 있다.

ex) [0,0,0,0,0,0,1,0,0,0]^T x [0,0,0,0,0,0,0,1,0,0] = 0

  • Vector Representation

단어사이의 관계표현을 위해 방향성을 가진 벡터로 단어를 표현하는 방법이다.

비슷한 단어들끼리 비슷한곳에 위치하도록 한다.

인접한 단어를 보면 그 단어의 뜻을 할 수 있다.

moden statistical NLP의 핵심이다.

단순히 비슷한 뜻을 가진 단어가 근처에 있는것 뿐만 아니라 벡터공간의 위치가 의미를 가지도록 표현이 가능하다.

1

3. 언어모델

  • 연속된 단어들의 등장확률을 예측하는 모델

ex)

배가고파서 나는 밥을 ___

먹었다? 먹는다? 지었다? …

p(먹었다) = 0.25, p(먹는다) = 0.15, p(지었다) = 0.05, p(자동차) = 0.000001 …

  • 문장의 순서나 단어선택 등을 예측할 수 있기에, 자동번역 등 많은 NLP Task에 유용하다.

  • 확률적 언어 모델을 만드려면, 이전에 나오는 단어를 많이 참조할수록 정확하다.

ex) 2-gram, 3-gram, 4-gram, .. n-gram

n-gram을 늘릴수록 메모리가 엄청나게 필요하다.

이런 문제점을 해결해주는 것이 RNN(Recurrent Neural Networks)이다.

4. 확률적 언어모델

  • 중심 단어가 주어졌을때 주변 단어들이 나올 확률을 구하고, 이 확률을 높이는 방향으로 벡터를 계속해서 조정하는(계속해서 학습해나가는) 모델이다. 따라서 데이터가 많으면 많을수록 좋다.

2

  • 확률적 언어모델을 만드는 방법에는 두가지가 있다. 여러가지 단어가 있으면 빈칸을 채우는 방법이 있고, 하나의 단어가 있으면 주변의 단어가 나올 확률을 계산하는 방법이 있다.

5. word2vec

3

히든레이어에서 아웃풋레이어로 가는 세타값을 vector representation을 쓰겠다는 것이 Neural Net Language Model이다.

Neural Net Language Model을 학습해서 나오는 것이 위의 그림에서 봤던 벡터에서 남성, 여성 위치 이런결과가 나온다.

4

  • 손쉽게 사용할 수 있는 여러가지 word2vec 구현체

1) Gensim word2vec

2) TensorFlow word2vec

3) Apache Spark MLlib word2vec

4) FastText

  • Gensim

1) 텍스트 표현 및 처리를 위한 Python 라이브러리

2) TF-IDF, word2vec, document2vec 등의 알고리즘들을 포함

3) 간편한 사용법과 좋은 성능으로 많이 쓰임

4) 사용시 참고사항

4-1) CPU Multithread Gensim word2vec 이 GPU Word2veckeras 보다 빠르다

관련 URL : https://rare-technologies.com/gensim-word2vec-on-cpu-fasterthan-word2veckeras-on-gpu-incubator-student-blog/

4-2) word2vec 같은것은 여러번 돌려야하는 경우가 많고, 더 많은 데이터를 돌리면 더 잘 학습하는 경향이 있으므로 성능도 중요하게 평가해야함

4-3) Deepdist (http://deepdist.com/)

Gensim + Spark

Stochastic gradient updates 를 이용, 클러스터간 학습값을 공유

4-4) FastText같은 대안 알고리즘도 고려해야한다.

5. gensim 을 이용한 나무위키 string 데이터로 word2vec 학습 실습

[실습프리뷰]

1) gensim 라이브러리 설치

2) Corpus (말뭉치) 준비

나무위키 데이터를 사용한다.

3) Training word2vec model

4) Exploration

similarity 등을 활용하여 모델을 탐색하고 의미있는 사실들을 탐색한다.

[실습 상세내용]

from gensim import corpora, similarities
from gensim.models import Word2Vec

import os
import multiprocessing

input_filename = '_namuwiki_20180326_mini.txt'
model_path = r'C:\Users\minman\Desktop\0507실습'

class SentenceReader(object):
    def __init__(self, input_filename):
        self.input_filename = input_filename
 
    def __iter__(self):
        for line in open(input_filename, 'r', encoding='utf-8'):
            yield line.split(' ')

sentences_vocab = SentenceReader(input_filename) # a memory-friendly iterator
sentences_train = SentenceReader(input_filename) # a memory-friendly iterator

config = {
    'min_count': 10,  # 등장 횟수가 10 이하인 단어는 무시
    'size': 300,  # 300차원짜리 벡터스페이스에 embedding
    'sg': 1,  # 0이면 CBOW, 1이면 skip-gram을 사용한다
    'batch_words': 10000,  # 사전을 구축할때 한번에 읽을 단어 수
    'iter': 10,  # 보통 딥러닝에서 말하는 epoch과 비슷한, 반복 횟수
    'workers': multiprocessing.cpu_count(),
}
word2vec_model = Word2Vec(**config)
i = 0

for sentence in sentences_vocab:
    if (i<5):
        print(sentence)
        
    i += 1
['\n']
['(신', '세계수의', '미궁', '2에서', '뜬', '!!아앗!!)\n']
['', '\n']
['세계수의', '미궁', '시리즈에', '전통으로', '등장하는', '대사.', '2편', '제왕의', '성배부터', '등장했으며,', '훌륭한', '사망', '플래그의', '예시이다.\n']
['세계수의', '모험가들이', '탐험하는', '던전인', '수해의', '구석구석에는', '채취/벌채/채굴', '포인트가', '있으며,', '이를', '위한', '채집', '스킬에', '투자하면', '제한된', '채집', '기회에', '보다', '큰', '이득을', '챙길', '수', '있다.', '그러나', '분배할', '수', '있는', '스킬', '포인트는', '한정된', '만큼', '채집', '스킬에', '투자하는', '만큼', '전투', '스킬', '레벨은', '낮아지게', '된다.\n']
token_count = sum([len(sentence) for sentence in sentences_vocab])
print(token_count)
5689597
word2vec_model.build_vocab(sentences_vocab)
word2vec_model.train(sentences_train, total_examples = token_count, epochs=word2vec_model.iter)
(37574483, 56895970)
word2vec_model.wv['컴퓨터']
array([-4.89444733e-02,  2.12149277e-01,  3.07926774e-01, -2.36114770e-01,
        1.73265319e-02, -1.57664180e-01, -4.73214649e-02,  1.42774835e-01,
       -8.91393647e-02,  7.18534924e-03, -3.52233872e-02, -2.98546016e-01,
        4.19392347e-01, -7.64974803e-02,  1.64778501e-01,  1.34128377e-01,
       -7.67253265e-02,  2.13795349e-01,  2.36256197e-01,  1.42444149e-01,
        8.68331119e-02, -5.18982768e-01, -1.13702282e-01, -1.39919281e-01,
        3.86519670e-01,  1.22996941e-01, -1.28421724e-01, -1.01735801e-01,
        1.36627126e-02, -4.98175651e-01, -2.72755325e-01, -8.12310725e-03,
       -2.10460007e-01, -4.30127621e-01, -1.66468680e-01, -1.86461825e-02,
       -1.89480141e-01, -1.10138036e-01, -2.47299060e-01, -3.20593685e-01,
       -2.56711841e-01, -1.42238215e-01, -2.91226268e-01,  2.41235301e-01,
        4.28629994e-01,  3.21999937e-01, -1.61533847e-01,  4.15442772e-02,
        2.43607506e-01,  5.79910129e-02,  3.07140261e-01, -1.29492087e-02,
        8.81309137e-02, -1.52817547e-01, -3.81114557e-02,  4.56584170e-02,
        1.10853642e-01,  1.19951397e-01, -9.52795595e-02, -2.12374069e-02,
       -1.01117022e-01,  1.56397134e-01, -5.69580570e-02,  9.60636884e-02,
       -2.92044431e-01,  2.34986767e-02, -1.22385994e-01, -3.89746577e-01,
       -7.89434239e-02,  2.21513793e-01, -3.10118169e-01,  1.35340378e-01,
        6.44859448e-02, -3.97753149e-01, -1.63576379e-01,  2.60230839e-01,
       -5.15524268e-01,  2.99857229e-01, -3.85377780e-02, -2.99782306e-02,
        1.60701528e-01,  1.20487452e-01, -1.27783805e-01,  2.56736530e-03,
       -1.96936220e-01,  2.69296080e-01,  2.97676444e-01, -3.18073630e-01,
        1.96385399e-01, -2.97684837e-02,  3.31294686e-02, -2.23016888e-02,
        1.62911668e-01,  9.91303399e-02,  3.17770004e-01, -7.44379461e-02,
        1.75555393e-01,  3.27698737e-01, -2.64060915e-01, -4.31358963e-01,
        1.43389180e-01,  2.37381116e-01,  1.22672938e-01,  4.46838826e-01,
        2.49345303e-01, -2.57699937e-01, -2.23078370e-01, -3.79522800e-01,
        2.54011471e-02, -1.55587509e-01,  1.55087173e-01,  8.05987418e-02,
        5.38553819e-02,  6.51429221e-02,  4.12528850e-02, -1.25661166e-02,
       -1.82779655e-01,  1.36582730e-02,  1.80984199e-01,  1.44898057e-01,
        3.42630923e-01, -3.34524572e-01, -1.57649979e-01, -1.17889799e-01,
       -8.80961359e-01, -1.19090173e-02,  1.41808540e-01,  3.06444407e-01,
       -7.28462264e-02,  1.50223851e-01, -6.78099468e-02, -6.63300157e-01,
       -4.13778514e-01, -9.74495560e-02, -9.90127474e-02,  6.57032728e-01,
        1.35891810e-01,  2.75490582e-01, -3.29174519e-01,  7.61645958e-02,
       -2.35637769e-01,  2.38549590e-01, -5.13127863e-01, -1.10978857e-02,
       -3.64421159e-02, -1.15836814e-01,  4.75113392e-01,  1.46323726e-01,
       -2.05030605e-01,  3.46764326e-01,  2.40394026e-02, -1.55701756e-01,
       -5.09365618e-01,  7.78398588e-02, -2.11957380e-01, -1.89215124e-01,
        2.89770216e-01, -3.14218998e-01, -5.63240290e-01, -4.18229327e-02,
       -1.83634713e-01, -2.54698656e-02, -1.72163680e-01,  9.06114504e-02,
        1.05182022e-01,  8.90849382e-02, -1.58668026e-01, -9.72167328e-02,
        1.76415756e-01,  1.48433045e-01,  9.67289787e-03, -2.57054001e-01,
        3.27202886e-01,  2.22260103e-01, -2.55173445e-01, -1.41979620e-01,
       -2.76630241e-02,  2.36994341e-01, -2.53879845e-01, -1.45007983e-01,
       -2.39701755e-02,  6.63651526e-02,  1.88900411e-01, -1.39092982e-01,
       -1.77085012e-01,  1.26081765e-01,  3.39382797e-01,  3.43103141e-01,
       -1.13959890e-02, -2.45139897e-01,  4.78379965e-01, -7.03082755e-02,
        2.87705600e-01, -1.02873258e-01, -1.97495371e-01,  1.53617322e-01,
       -6.86099753e-02,  4.83210921e-01, -7.61319846e-02, -4.99132015e-02,
        1.80054337e-01, -3.01314816e-02,  3.50650758e-01, -5.89101076e-01,
       -9.72911179e-01,  9.88111719e-02, -2.88896877e-02,  2.59971470e-01,
       -2.63712406e-01,  1.20239727e-01,  3.09962451e-01,  2.77166069e-02,
        3.09111506e-01, -2.41481304e-01, -1.18282363e-01,  1.50902331e-01,
        3.60565335e-01,  8.88025314e-02,  5.14013112e-01, -1.47602245e-01,
        1.33635476e-01,  3.07552159e-01, -3.55134457e-01,  1.99442387e-01,
       -3.01021989e-02,  2.04161420e-01,  1.00623384e-01,  9.91701111e-02,
       -1.19120762e-01, -1.67358220e-01, -8.85520950e-02,  9.55310315e-02,
        6.84137270e-02,  1.26955718e-01,  1.01066671e-01, -1.66425020e-01,
        8.73438141e-04,  3.87228094e-02, -1.36450008e-01,  1.73422560e-01,
       -2.96802640e-01,  3.07082245e-03, -9.66350175e-03,  4.13359880e-01,
       -2.61123758e-02, -2.59313881e-01, -1.62320822e-01, -2.64905989e-01,
       -3.41820307e-02,  3.73198986e-02, -4.05382007e-01,  4.75735724e-01,
        3.79232973e-01, -1.29022658e-01, -1.18551642e-01,  4.60622162e-01,
        3.02868243e-02, -1.58158671e-02,  1.63615137e-01,  2.45047599e-01,
       -2.91406125e-01,  1.03874572e-01, -2.45708227e-02,  7.25027174e-02,
       -7.14385137e-02,  4.60685313e-01, -2.50908762e-01, -1.79602057e-01,
        6.73701763e-02, -2.61987686e-01, -1.17736302e-01, -2.14862078e-01,
       -3.96715313e-01,  1.63355872e-01,  2.94565469e-01,  2.95890003e-01,
        5.58686733e-01, -9.90497414e-03, -1.95393160e-01,  4.98686522e-01,
        2.61075497e-01,  1.52776599e-01,  2.28498921e-01,  2.60978550e-01,
        6.41064644e-02, -1.44907115e-02,  2.16054153e-02,  1.47647887e-01,
        4.96248841e-01, -2.59023011e-01,  2.15061203e-01, -1.19510461e-02,
       -1.08890802e-01,  2.59606868e-01,  3.70812640e-02,  1.28522709e-01,
        2.07727119e-01,  2.62176305e-01, -1.95170343e-01,  1.75268576e-01],
      dtype=float32)
word2vec_model.most_similar(['컴퓨터'])
[('개인용', 0.5928508043289185),
 ('공학', 0.5684698224067688),
 ('컴퓨터를', 0.5363287925720215),
 ('스마트폰', 0.5359224081039429),
 ('DAW', 0.535523533821106),
 ('태블릿', 0.5256739854812622),
 ('제조사', 0.5225208401679993),
 ('돌비', 0.5182591676712036),
 ('툴의', 0.5144219994544983),
 ('CAD', 0.5068387389183044)]
word2vec_model.most_similar(positive = ['서울', '미국'], negative=['한국'])
[('지하철', 0.41480255126953125),
 ('뉴욕', 0.3802769184112549),
 ('역번호.\n', 0.37469372153282166),
 ('3호선', 0.3733898997306824),
 ('5호선', 0.3722527027130127),
 ('경전철', 0.3663251996040344),
 ('1988', 0.36552858352661133),
 ('7호선', 0.3651158809661865),
 ('1호점을', 0.3644155263900757),
 ('5호선\n', 0.3627084791660309)]