word embedding을 해봅시다.

2 분 소요

word embedding이 뭔가요.

  • word2vec도 많이 들어 봤고, word emedding도 많이 들어봤습니다. 어떻게 ‘되는 것인지’는 모르지만, 어떻게 쓸 수 있는 줄은 알고 있습니다. 아주 간단하게 말하면, word를 벡터로 표현한다는 것이겠죠.
  • 기존에도 워드를 벡터화 하려는 몇 가지 방벙들은 있었습니다. 여기서 흔히 말하는 word2vec의 특징이라면 neural network를 사용한다는 것이겠죠(어떻게 쓰는지에 대해서는 밑에서 다시 설명하겠습니다). 특히 아래 그림에서 보는 것처럼 ‘현실에서 존재하는 semantic’이 vector를 통해 표현이 된다는 것이 아주 큰 컨트리뷰션 이라고 말할 수 있습니다.

word2vec

bag of word

  • 기존에는 개별 문서에 대해서 bag of word의 형태로 표현을 했씁니다. document(워드 문서 같은 것)를 하나의 instance로 생각하면 각각의 document에는 여러 개의 단어들이 있습니다. 개별 문서마다 단어들이 어느 정도나 있는가, ‘어떤 단어가 많이 있는가?’가 그 문서의 특징을 보여준다고 생각하는 것을 bag of word 라고 합니다.
    • 해당 벡터를 “있다 없다”의 형태로 표현할 수도 있고, “몇 개나 있느냐”로도 표현할 수도 있습니다.

TF-IDF

  • 그런데, 사람들은 비슷비슷한 단어들을 씁니다. 영어의 경우에 어떤 문서를 봐도 ‘is’, ‘the’는 정말 많을텐데, document를 count vector 로 만들어 버리면, 저런 일종의 noise 때문에 제대로 문서간의 similarity 등을 계산할 수 없을 것 같습니다.
  • 그래서 나온 것이 TF-IDF 인데, 이는 “전체 문서에서는 적게 나왔는데, 해당 문서에서만 많이 나온 경우”를 중심으로 vector화 합니다. 저는 유사공대생이기 때문에, 자세한 수식을 생략합니다 하핫. 어차피 저는 남이 만들어둔 라이브러리를 이용해서 적용만 할거에요 하핫.

제가 원하는 것은 간단합니다.

  • 저는 특정 분야의 키워드 네트워크를 만들고 있는데, 같은 의미를 가진 키워드들인데, 네트워크 상에서는 다른 의미를 가진 개별적인 노드로 인식된느 것을 해결하고 싶습니다.
  • 이를 위해서 ‘논문의 초록 데이터’를 이용하려고 합니다. 논문의 초록 데이터를 word-embedding하면 이 분야 내에서 개별 단어들을 벡터로 표현할 수 있을 것이고, 그렇다면 개별 벡터간의 비교를 통해 ‘의미적’으로 가까운 단어를 변환하면 되는게 아닐까? 생각합니다.

잘 모르겠어서, 바로 word embedding을 해보기로 합니다.

  • 일단 하라는 대로 합니다. gensim라이브러리가 필요하다고 해서, conda install gensim을 합니다. nltk는 지난 번에 다운 받아 놨습니다.
  • 실습을 한 다음에, 직접 제가 지난 번에 다운받은 논문 abstract를 이용해서 직접 학습을 해보도록 하겠습니다.
  • movie_reviews 데이터를 가져와서 실습합니다.
    • 이 데이터는 아마도 개별 문장들이 공백으로 쪼개져 있습니다. 예를 들어서, 'I am a boy' ==> ['I', 'am', 'a', 'boy;].
  • 대략 아래 메소드 들을 사용하면 될 것 같네요. 단, ‘man’과 ‘woman’의 유사도가 높게 나오는데, 어떻게 보면 비슷한게 맞고, 또 어떻게 보면 비슷하지 않죠. 그냥 단순하게 similarity를 사용해서는 안될 것 같습니다.
from nltk.corpus import movie_reviews
sentences = [list(s) for s in movie_reviews.sents()]

from gensim.models.word2vec import Word2Vec
model = Word2Vec(sentences, size=100) 
# 여기서 사이즈는 vector의 크기를 말합니다. nn의 최종 layer size라고 생각해도 됩니다. 
# 뉴럴넷의 사이즈를 좀 깊게 만들어보고 싶은데, gensim에서 자동으로 해주는지 모르겠네요. 
model.init_sims(replace=True)# 학습 완료 후, 필요없는 메모리 삭제 

print("vector of {}:".format('man'))
print(model.wv['man'])
for w1, w2 in [('actor', 'actress'), ('man', 'woman')]:
    print("similarity of {} and {}:".format(w1, w2))
    print(model.wv.similarity(w1, w2))

print()
print(model.wv.most_similar('man'))
print()
# actor + she - actress 
print(model.wv.most_similar(positive=['actor', 'she'], negative='actress', topn=1))
# actress + he - actor
print(model.wv.most_similar(positive=['actress', 'he'], negative='actor', topn=1))
vector of man:
[ 0.0961192   0.00437185  0.03467375  0.26454127  0.02940031  0.02288906
  0.02179242  0.02122602 -0.04023347  0.01882667 -0.02628091  0.03881754
 -0.06698899  0.14932805 -0.0474763   0.02154444 -0.14287125  0.21027721
 -0.02145271 -0.02302506  0.03378444  0.0153384   0.07713746  0.15382759
  0.12019698 -0.1113359  -0.0593212  -0.19330981  0.00104285 -0.08455317
  0.01631272  0.05338057 -0.05085417 -0.00311475  0.00962412  0.12170225
 -0.09533398  0.09420326 -0.03652238 -0.13428254 -0.13235193  0.12731819
  0.06866247  0.01878783  0.07961938 -0.02594641  0.1502616  -0.09824947
  0.11498301  0.03205505 -0.13049409 -0.11235102  0.18670972  0.20496006
  0.11508316 -0.08224259  0.07353425  0.05081542  0.07457628 -0.06560689
  0.06979878  0.00345675  0.15629113  0.11683072 -0.07166454 -0.08964456
  0.0704189   0.01116451 -0.07762457 -0.15145063 -0.23548466  0.17004918
 -0.08410266  0.05517555 -0.12813565  0.08467376  0.15465082 -0.01966195
 -0.126249    0.05783306 -0.10403755 -0.01165899 -0.19907828  0.07758326
 -0.05870183 -0.04015943  0.01824598 -0.01141299  0.18254025 -0.01973889
 -0.06274197 -0.03590406 -0.10662002  0.10698724  0.0145605  -0.12283614
 -0.0986573   0.08289269  0.02273848 -0.09652561]
similarity of actor and actress:
0.871707394306
similarity of man and woman:
0.907711044147

[('woman', 0.9077110886573792), ('girl', 0.8656805157661438), ('boy', 0.8102990984916687), ('child', 0.8080374598503113), ('killer', 0.8013476729393005), ('doctor', 0.7803214192390442), ('kid', 0.7172398567199707), ('secret', 0.7040114998817444), ('person', 0.7038406729698181), ('guy', 0.6979759931564331)]

[('he', 0.3257312476634979)]
[('she', 0.3937234878540039)]
  • 아주 간단하게, 거의 뇌없이 word-embedding해본 결과이고, 이를 이후에 키워드 분석에서 활용해보겠습니다.

reference

댓글남기기