[자연어처리] word2vec 로 워드임베딩 하기

2020. 5. 18. 15:56노트/Python : 프로그래밍

https://excelsior-cjh.tistory.com/156

* 원핫인코더 vs 워드임베딩

원핫인코더 

    -> 멀캠 => [0,1,,0,0,0,0,0,] 1000차원  

워드임베딩 

    -> 멀캠 => [0.3,-1.5]  100차원  

 

* word2vec 알고리즘이 구현된 사이트

https://word2vec.kr/search/ 

 

Korean Word2Vec

ABOUT 이곳은 단어의 효율적인 의미 추정 기법(Word2Vec 알고리즘)을 우리말에 적용해 본 실험 공간입니다. Word2Vec 알고리즘은 인공 신경망을 생성해 각각의 한국어 형태소를 1,000차원의 벡터 스페이

word2vec.kr

* Word2vec 

  • Skip-gram : 중간 단어들로 부터 주변 단어를 예측 

  • CBOW  : 주변 단어들로 부터 중간 단어를 예측 

 

모델 생성 코드

 

<ted 데이터 파싱>

import re 
from lxml import etree  # 파서 
from nltk.tokenize import word_tokenize, sent_tokenize

path = "C:\\Users\\student\\Desktop\\DY\\★ 데이터\\402. word2vec\\"
targetText=etree.parse(open(path+"ted_en-20160408.xml","r", encoding="UTF-8"))

parseText="\n".join(targetText.xpath("//content/text()"))
#content 태그 내부의 내용을 추출 

parseText

 

 

데이터 전처리 

contentText = re.sub('\([^)]*\)', '', parseText)
# (배경음) 제거

sentText = sent_tokenize(contentText)
# 문장 단위 토큰화 

# 대문자 => 소문자, 구두점 제거 (영문, 숫자 제외)
normalizedText = [] 
for sent in sentText: 
    tokens = re.sub("[^a-z0-9]+"," ",sent.lower())
    normalizedText.append(tokens)
result = [ word_tokenize(s) for s in normalizedText ] 

 

워드 투 벡터 생성

from gensim.models import Word2Vec

model = Word2Vec(sentences=result , size = 100 , window = 5, min_count=5 , workers = 4 , sg = 0)
# 임베딩 벡터 차원 
# window : 윈도우 크기 
#mincont : 최소 5번 이상 등장한 단어 
# sg = 0 : CBOW 
# sg = 1 : skip - grows

model.wv.most_similar("boy")
>>>
[('girl', 0.9331763982772827),
 ('kid', 0.8508039712905884),
 ('woman', 0.8028853535652161),
 ('lady', 0.7984563708305359),
 ('man', 0.7496694922447205),
 ('baby', 0.7485554218292236),
 ('mary', 0.7290230989456177),
 ('brother', 0.7253110408782959),
 ('sister', 0.7207695245742798),
 ('guy', 0.7084351778030396)]
 
 model.wv.most_similar(positive=["computer"], topn=20)
 >>> 
 [('machine', 0.7435390949249268),
 ('software', 0.7116355895996094),
 ('device', 0.7114464044570923),
 ('robot', 0.6957539319992065),
 ('printer', 0.6745666861534119),
 ('3d', 0.6687895655632019),
 ('camera', 0.6669822931289673),
 ('video', 0.6506317853927612),
 ('chip', 0.6502120494842529),
 ('interface', 0.648311972618103),
 ('program', 0.6476713418960571),
 ('game', 0.6365739703178406),
 ('mechanical', 0.631850004196167),
 ('simulation', 0.6288244128227234),
 ('laser', 0.6235957741737366),
 ('circuit', 0.6218003034591675),
 ('satellite', 0.6084750890731812),
 ('keyboard', 0.6066275238990784),
 ('film', 0.6054130792617798),
 ('mri', 0.6019344925880432)]

 

< 영화 댓글 >

import pandas as pd 

trainData=pd.read_table(path+"ratings.txt")
trainData

# 결측값 제거 
# 데이터가 많고 null값 있는 행은 적기 때문에 null 값이 있는 행 전체 제거 
trainData=trainData.dropna()

# 한글 아닌 단어 제거 
trainData['document'] = trainData['document'].str.replace("[^가-힣ㄱ-하-ㅣ ]","")
trainData[:20]

# 불용어 
stopwords = ["하다","한","에","와","자","과","걍","잘","좀","는","의","가","이","은","들"]

# 단어 토큰화 
from konlpy.tag import Okt 
import matplotlib.pyplot as plt 

okt = Okt()
tokenizedData = []

for sent in trainData['document']:
    t = okt.morphs(sent, stem=True) 
    # stem: 어근 추출
    # norm(표준화): 그래욬ㅋㅋ => 그래요
    [w for w in t if w not in stopwords] # for문부터 해석 => if문 => 조건문에 해당하는 w 순서로 해석
    tokenizedData.append(t)
    

# tokenizedData에 저장된 리뷰에 대해 
# 리뷰 최대 길이 
# 리뷰 평균 길이 

print(max(len(l) for l in tokenizedData))
#stem: 어근 , norm: 그래욬ㅋㅋ => 그래요 
print(sum(map(len, tokenizedData)) / len(tokenizedData))
plt.hist([len(s) for s in tokenizedData])
plt.show()

 

모델 생성 

model = Word2Vec(sentences=tokenizedData, 
        size=100,
        window=5,
        min_count=5,
        workers=4,
        sg=0)
        
model.wv.most_similar("송강호")

>>>

[('설경구', 0.8824548721313477),
 ('엄정화', 0.8616570234298706),
 ('한석규', 0.8591156005859375),
 ('김혜수', 0.8546769618988037),
 ('박중훈', 0.8499290347099304),
 ('차승원', 0.8398219347000122),
 ('최민수', 0.8362987637519836),
 ('임창정', 0.8344924449920654),
 ('러셀', 0.8276678323745728),
 ('안성기', 0.823891282081604)]

 

<구글 word2vec 모델>

# 구글 word2vec모델 : 3백만개 단어벡터 
from gensim.models import Word2Vec 
Word2Vec.load(path+"ko.bin")

model.wv.most_similar("아저씨")
model.wv.most_similar("모델")
model.wv.most_similar("고객")
model.wv.most_similar("구매")
model.wv.most_similar("추천")

>>>
[('강추', 0.7383513450622559),
 ('후회', 0.6111788749694824),
 ('꼭', 0.5963805317878723),
 ('권하다', 0.5816684365272522),
 ('즐기다', 0.5469875335693359),
 ('적극', 0.5408307313919067),
 ('비추다', 0.5373992919921875),
 ('감상', 0.5136994123458862),
 ('께', 0.5081770420074463),
 ('강', 0.5050325393676758)]