HyeM

6부_2장 Word2Vec로 문장을 백터로 변환하기 본문

Study/AI&DeepLearning

6부_2장 Word2Vec로 문장을 백터로 변환하기

Hailey_HyeM207 2020. 7. 17. 23:51

Word2Vec 

: 문장 내부의 단어를 벡터로 변환하는 도구

단어의 연결을 기반으로 단어의 연관성을 벡터로 만들어준다. 

단어의 의미 파악할 수 있음

+ 의미를 선형으로 계산 가능 ( "아빠-남자+여자" = "엄마")


01. Gensim 설치

Word2Vec을 구현하는 도구는 많은데, 그 중 실행속도 빠르고 파이썬으로 실행 가능한 Gensim 라이브러리 사용할 것이다.

Gensim라이브러리의 Word2Vec : 단어를 더하고 빼는 처리를 하기 위해선, 말뭉치(Corpus) 라는 단어사전을 만들려면, 데이터를 준비하고 학습시켜야 한다.

설치

 

 

02_1. Gensim의 Word2Vec으로 "토지"를 읽어보기 (단계1) 

 

단계1.  분석할 파일 다운로드 하기

따로 파일을 다운로드 하지않고, 6부 1장에서 활용한 "토지1" 파일을 재사용하여 실습하겠다.

 

단계2. 소스코드 

import codecs
from bs4 import BeautifulSoup
from konlpy.tag import Okt
from gensim.models import word2vec

#utf-16인코딩으로 파일을 열고 글자를 출력하기 (#1)
fp= codecs.open("BEXX0003.txt","r", encoding="utf-16")
soup=BeautifulSoup(fp, "html.parser")
body=soup.select_one("body > text")
text=body.getText()


#텍스트를 한 줄씩 처리하기 (#2)
okt=Okt()
results=[]
lines=text.split("\n")
for line in lines:
    #형태소 분석하기(#3)
    #단어의 기본형 사용
    malist= okt.pos(line,norm=True, stem=True)  #형태소 분석 (줄별로)
    r=[]
    for word in malist:  # 단어 단위로 
        #조사/어미/구두점 등은 대상에서 제외
        if not word[1] in ["Josa","Eomi", "Punctuation"]:
            r.append(word[0]) # 형태소를 r에 추가한다.
        rl = (" ".join(r)).strip()   #r리스트에 공백을 추가하고,  문자열 양 끝의 공백과 \n를 제거한다.
        results.append(rl) # result에 이를 추가하여, 출력한다. 
        print(rl)


#파일로 출력하기(#4)
gubun_file= 'toji.gubun'
with open(gubun_file, 'w', encoding='utf-8') as fp : #toji.gubun이름의 파일에 공백을 추가하여 result 리스트의 내용을 입력한다. 
    fp.write("\n".join(results))


#Word2Vec 모델만들기 (#5)
data=word2vec.LineSentence(gubun_file)
model=word2vec.Word2Vec(data,
                        size=200, window=10, hs=1, min_count=2, sg=1)
model.save("toji.model")
print("ok")

#1. 파일을 읽어오기  -> #2.  줄단위로 나누고, 형태소 분석한다. -> 

#3. 형태소 분석한 것을 바탕으로, 하나씩 읽어서 리스트에 추가& 출력 _ ( 이때, 조사/어미/구두점은 대상에서 제외 )  ->

#4. 위의 결과를 togi.gubun 이름의 파일로 저장한다. ->

#5. word2vec 모델(백터모델)을 만든다.

 

* 파일객체 = open(파일이름, 파일열기모드) : open함수로 쓰기 모드(w)로 열면, 이미 존재할 경우엔 원래 내용사라지고 해당 파일이 존재하지 않으면 새로운 파일이 생성된다.     

* strip() : 문자열 양 끝에 존재하는 공백과 \n를 제거해주는 함수. 단 중간에 있는 공백은 제거하지 않는다.

* with open(파일이름, '동작', '인코딩' ) as 파일객체 :  

                파일객체.write( )                                         

  : with문 사용하여 close 하지 않아도, 자동으로 close하게 한다.   + write함수는 해당 내용을 파일에 입력함.

 

* word2vec.LineSentence(파일이름) 텍스트를 읽어들임

* word2vec.Word2Vec( ) 벡터 모델을 만든다. 

* model.save(파일이름) : 파일 저장  

 

 

단계3. 실행화면

(시간이 꽤 아니,, 많이 걸린다..)

이런식으로 출력된다.  (중간 출력 내용은 생략)

 

 

 

 

02_2.  "토지" 모델 살펴보기 (단계2) 

Jupyter Notebook을 사용해서 모델을 살펴본다. 

+ Jupyter Notebook:  Jupyter Notebook은 오픈 소스 웹 애플리케이션으로 라이브 코드, 등식, 시각화와 설명을 위한 텍스트 등을 포함한 문서를 만들고 공유하도록 할 수 있습니다. (출처 : https://cyan91.tistory.com/7)

 

단계1. 코드 실행

아래 코드는 파이썬 대화환경에서 실행한 코드이다. 

>>> from gensim.models import word2vec
>>> model = word2vec.Word2Vec.load("toji.model")
>>> model.most_similar(positive=["땅"])

* word2vec.Word2vec.load(파일의 경로) :  모델을 불러옴.

* model.most_similar() : 유사한 단어를 찾을 때 사용하는 함수 , positive와 negative 인수를 이용해서 관계 찾을 수 있다.

위의 예제에서는 positive=["땅"]이라고 했으니, 땅과 유사한 항목들을 출력해줄 것이다. 

 

 

단계2. 실행 결과

positive=["땅"]

"토지"라는 책에서 "땅" 가장 가까운 단어로 '전래', '초목' 등등이 나왔다. 

positive=["집"]

이번엔 "집"과 가장 가까운 단어 검색 결과, '따끈하다',' 얼얼하다' 등이 나왔다.

 

이 실습은 토지의 1권정도어서, 데이터가 매우 적기 때문에 원하는 결과가 나오기 힘들다.

 

 


 

 

03. 위키피디아 한국어 버전을 사전으로 사용해보기 (단계1) 

더 많은 데이터를 가진 위키피디아를 이용해 실습해본다. 

 

단계1.  분석할 파일 다운로드 하기

위의 "토지"를 이용한 실습은, 데이터가 부족하였다. 이번엔 데이터가 많은 위키피디아를 사용해 실습을 해본다.

다운로드 받는 시간은 대략 10시간 정도 걸린다.  ( 시간이 부족하여 하지 못했다. ) 

https://dumps.wikimedia.org/kowiki/latest

 

단계 2. 소스코드

wiki-wakati.py   _ 형태소 구분하여 저장

import codecs
from bs4 import BeatifulSoup
from konlpy.tag import Okt
from gensim.models import word2vec

#파일 열기(#1)
readFp=codecs.open("wiki.txt", "r", encoding="utf-8")
gubun_file ="wiki.gubun"
writeFp=open(gubun_file, "w", encoding="utf-8")   #파일 'w'모드로 open

okt=Okt()
i=0

#텍스트를 한줄씩 처리하기(#2)
while True:
    line=readFp.readline()  # 한줄씩 처리한다. 
    if not line : break  # 라인이 없으면(더 이상 읽을 줄이 없으면) break
    if i %20000 ==0 :
        print("current -" + str(i))
    i+=1
    malist = okt.pos(line, norm=True, stem=True) # 형태소 분석(#3)
    r=[]
    for word in malist :# 단어(형태소) 단위로 처리
        # 조사/ 어미/ 구두점 등은 대상에서 제외
        if not word[1] in ["Josa", "Eomi", "Punctuation"]:
            writeFp.write(word[0] +" ")  # 파일에 [0]인 형태소를 쓴다.
writeFp.close() #파일 입력종료(#4)

#1. 파일을 읽어오기  -> #2.  줄단위로 나눈다. -> 

#3. 형태소 분석하고, 하나씩 리스트에 추가& 출력 _ ( 이때, 조사/어미/구두점은 대상에서 제외 ) - >

#4. 위의 결과를 wiki.gubun 이름의 파일이 생성된다. 

 

( 소스코드는 위의 실습 "토지"와 비슷하여 자세한 설명은 생략한다. )

( 위의 코드 역시 돌리면 오랜시간 기다려야 한다. )

 

 

wiki-mkdic.py  _ 벡터모델로 생성

from gensim.models import word2vec
data=word2vec.Text8Corpus("wiki.gubun")
model=word2vec.Word2Vec(data, size=100)
model.save("wiki.model")
print("ok")

* word2vec.Text8Corpus() :  텍스트 파일에서 문장 가져오기

* word2vec.Word2Vec() : 벡터 모델 만들기  #이때, 백터만들때 size를 100으로 지정하여, 100차원 벡터 데이터로 표현된다. 

최종적으로는 wiki.model이라는 파일이 생성된다. 

 

 

단계3. 실행화면

( 시간이 많이 걸린다. 아직 다운로드가 덜 되어 사진첨부는 못하였다. 

다운로드하고, 소스코드 짜고 실행했다는 가정하에 결과를 쓰겠습니다. )

 

  ○    코드 실행  _ 모델 불러오기

>>> from gensim.models import word2vec
>>> model=word2vec.Word2Vec.load('wiki.model')

위의 코드로 벡터모델을 불러온다. 

 

 

○      유사어 검색

 

>>> model.most_similar(positice=["Python", "파이썬"])
    [('Perl', 0.9213457107543945), ('Java', 0.90691133533783), ...(생략)
    
>>> model.most_similar(positive=["아빠", "여성"], negative=["남성"])[0]  #처음 한개만 출력
   #아빠-남성+여성 계산과 같음
   ( '엄마', 0.851773988296631)
  

이 외에도 positive=["서울", "맛집"])[0:5] 를 하게 되면 강남, 인사동, 서울특별시, 등등 총 5개의 결과가 나오는 것을 볼 수 있다.

 

 

 

 

 

 

 

 

위 글은 [(파이썬을 이용한)머신러닝, 딥러닝 실전 개발 입문] 을 읽고 정리한 글입니다.

Comments