앞서 배운 word2vec을 실제로 구현해봐야 내가 제대로 알 거 같다는 생각이 들었담,,

우선 영어 버전의 word2vec의 경우, gensimmodels.word2vec에 미리 학습된 word2vec model이 존재한다.

아래와 같이 로드해서 사용하면 된다.


from gensim.test.utils import common_texts
from gensim.models import Word2Vec
model = Word2Vec(sentences=common_texts, vector_size=100, window=5, min_count=1, workers=4)

# model.save("word2vec.model")
# model = Word2Vec.load("word2vec.model")

model.train([["hello", "world"]], total_examples=1, epochs=1)

이를 바탕으로, 의미가 비슷한 단어를 찾아낼 수도 있다.

vector = model.wv['computer']  # get numpy vector of a word
sims = model.wv.most_similar('computer', topn=10)  # get other similar words


물론 한국어의 경우에도, github에 다른 분들이 올려주신 pre-trained wore2vec model이 있다.

https://github.com/Kyubyong/wordvectors 에서 다운받고 설치하면 되지롱 ! 눌러서 다운로드

ko_model = gensim.models.Word2Vec.load('./model/ko/ko.bin')
a = ko_model.wv.most_similar("강아지")
print(a) # 강아지와 유사도가 비슷한 단어 & 그 유사도 set


그런데 더 나아가서, 직접 원리를 눈으로 확인해보고 싶어졌다! [다른 분들의 블로그]https://sdc-james.gitbook.io/onebook/5./6.1./6.1.3.-word2vec)를 보고 공부해봤다.

사용된 데이터는 https://github.com/e9t/nsmc.git 에서 다운받을 수 있다.

ratings.txt = ratings_train.txt + ratings_test.txt 이다.

# open file
import csv

f = open('nsmc/ratings_train.txt', 'r', encoding='utf-8')
rdr = csv.reader(f, delimiter='\t')
rdw = list(rdr)

f.close()

ratings.txt, ratings_train.txt, ratings_test.txt의 각 파일에 있는 Column 은 <영화 아이디, 영화 평, 영화 평점> 이고,

r을 출력해보면 아래와 같다.

print(rdw[:5])

#[['id', 'document', 'label'],
# ['9976970', '아 더빙.. 진짜 짜증나네요 목소리', '0'],
# ['3819312', '흠...포스터보고 초딩영화줄....오버연기조차 가볍지 않구나', '1'],
# ['10265843', '너무재밓었다그래서보는것을추천한다', '0'],
# ['9045019', '교도소 이야기구먼 ..솔직히 재미는 없다..평점 조정', '0']]


우선 형태소 분석기를 통해 Josa, Eomi, Punctuation 는 제외한 단어들의 목록을 리스트에 저장한당.

result = []
for line in rdw: # ['6684036', '나중이라도 꼭 한번 보고싶습니다!!', '1']

    #형태소 분석하기, 단어 기본형 사용
    malist = twitter.pos( line[1], norm=True, stem=True) # [('나중', 'Noun'), ('이라도', 'Josa'),('꼭', 'Noun'), ('한번', 'Noun'), ('보다', 'Verb'), ('!!', 'Punctuation')]
    r = []
    for word in malist:
        #Josa”, “Eomi”, “'Punctuation” 는 제외하고 처리
        if not word[1] in ["Josa","Eomi","Punctuation"]:
            r.append(word[0])
     #형태소 사이에 공백 " "  을 넣습니다. 그리고 양쪽 공백을 지웁니다.
    rl = (" ".join(r)).strip() # '나중 꼭 한번 보다'
    result.append(rl)

이후 아래와같이 word2vec을 학습 시켜 model을 만들어 사용한다.

#형태소들을 별도의 파일로 저장 합니다.
 with open("NaverMovie.nlp",'w', encoding='utf-8') as fp:
     fp.write("\n".join(result))

#Word2Vec 모델 만들기
wData = word2vec.LineSentence("NaverMovie.nlp")
wModel =word2vec.Word2Vec(wData, size=200, window=10, hs=1, min_count=2, sg=1)
#wModel.save("NaverMovie.model")
#print("Word2Vec Modeling finished")

#wModel = word2vec.Word2Vec.load("NaverMovie.model")
print(model.most_similar(positive=["재미"]))
#[('ㅠㅡㅜ', 0.5964617729187012), ('없슴', 0.596453070640564), ('나용', 0.5938360095024109), ('푸시', 0.5832706689834595), ('사고사', 0.5669316053390503), ('이상하', 0.5638896822929382), ('섹씬', 0.5629161596298218), ('유익', 0.5620923042297363), ('재미없다', 0.5620167255401611), ('지렁이', 0.558078408241272)]

print(model.most_similar(positive=["최고"]))
#[('꼽을', 0.7225841283798218), ('꼽는', 0.6934826970100403), ('최고다', 0.6918784976005554), ('단연', 0.6749929785728455), ('ER', 0.6678911447525024), ('하이스쿨', 0.6403142809867859), ('손꼽다', 0.6399452686309814), ('으뜸', 0.6315333843231201), ('손에꼽는', 0.6309640407562256), ('투윅스', 0.6254955530166626)]


그런데 이것도 마찬가지로 구현된 word2vec을 사용한 거라,,,

진짜 pytorch로 word2vec 구현하신 분의 코드 http://cedartrees.co.kr/index.php/2020/12/30/word2vec-pytorch/ 도 공부했다.

-> colab으로 정리해둠 !!


Reference

  • https://radimrehurek.com/gensim/models/word2vec.html

  • https://omicro03.medium.com/%EC%9E%90%EC%97%B0%EC%96%B4%EC%B2%98%EB%A6%AC-nlp-14%EC%9D%BC%EC%B0%A8-word2vec-%EC%8B%A4%EC%8A%B52-8e518a358b6c