Adventure Time - Finn 3
본문 바로가기
AI/ML

Word2Vec

by hyun9_9 2026. 4. 17.

단어의 의미나 연관성을 벡터로 표현

단어간 유사도 계산이 가능해짐

 

 단어의 '의미'를 '벡터'로 표현하면,
 연관된 단어를 추출하거나, 단어와 단어의 유사도를 확인할수 있다.
 또한 의미를 선형계산할수 있어서 "왕자 - 남성 + 여성 => 공주" 와 같은 계산을 할수 있다

import codecs # 파일 입출력 시 인코딩(UTF-8, CP949 등) 문제를 해결하고 유니코드 데이터를 다룰 때 사용
from bs4 import BeautifulSoup # html 에서 추출
from konlpy.tag import Okt
from gensim.models import word2vec
import os

with codecs.open(os.path.join(base_path,'korean','BEXX0003.txt'),'r',encoding='utf-16') as f:
  soup= BeautifulSoup(f, 'html.parser')
  text =soup.select_one("body>text").getText()
print(text[:500])
"""
제1편 어둠의 발소리
서(序)
1897년의 한가위.
까치들이 울타리 안 감나무에 와서 아침 인사를 하기도 전에, 무색 옷에 댕기꼬리를 늘인 아이들은 송편을 입에 물고 마을길을 쏘다니며 기뻐서 날뛴다. 어른들은 해가 중천에서 좀 기울어질 무렵이래야, 차례를 치러야 했고 성묘를 해야 했고 이웃끼리 음식을 나누다 보면 한나절은 넘는다. 이때부터 타작마당에 사람들이 모이기 시작하고 들뜨기 시작하고 -- 남정네 노인들보다 아낙들의 채비는 아무래도 더디어지는데 그럴 수밖에 없는 것이 식구들 시중에 음식 간수를 끝내어도 제 자신의 치장이 남아 있었으니까. 이 바람에 고개가 무거운 벼이삭이 황금빛 물결을 이루는 들판에서는, 마음놓은 새떼들이 모여들어 풍성한 향연을 벌인다.
"후우이이 -- 요놈의 새떼들아!"  극성스럽게 새를 쫓던 할망구는 와삭와삭 풀발이 선 출입옷으로 갈아입고 타작마당에서 굿을 보고 있을 것이다. 추석은 마을의 남녀노유, 사람들에게뿐만 아니라 강아지나 돼지나 소나 말이나 새들에
"""
okt =Okt()
results =[]
lines = text.split('\n')

len(lines)
# 3440

for line in lines:
  # print(line)
  # print(okt.pos(line))
  #형태소 분석 (품사태깅)
  # 단어의 기본형 사용
  malist = okt.pos(line, norm= True,stem=True)

  # 어미 / 조사 / 구두점 제거
  removed =[]
  for word in malist: # word -> (단어, 품사)
    if word[1] not in ['Josa','Eomi','Punctuation']:
      removed.append(word[0])

  cleaned = (" ".join(removed)).strip()
  results.append(cleaned)

print(lines[20:30])
print(results[20:30])
"""
['"용왕님네 심사도 풀어주어야 안 하겄나? 그래야 개기도 풍년이 들제."', '"젯상에도 못 오르는 민물개기가 어디 개기가! 당산에 가자! 당산에!"', '누군가가 팔팔하게 반대하고 나서면 너희들이야 그러거나 말거나 두만아비는 느릿느릿 징을 칠 것이다. 봉기는 헤죽헤죽 웃으며, 구경하는 아낙들보고 부끄러워하며 고깔을 흔들 것이다. 이들은 한창 일할 나이, 살림의 기틀을 잡고 있는 삼십대 중간쯤의 장정들이었고 나이 좀 처지는 축으로는 장구 멘, 하얀 베수건 어깨에 걸고 싱긋이 웃으며 큰 키를 점잖게 가누어 맴을 도는 이용(李龍)이다. 그는 누구니 누구니 해도 마을에선 제일 풍신 좋고 인물 잘난 사나이, 마음의 응어리를 웃음으로 풀며 장단을 치고, 칠성이 북을 더덩 덩! 뚜드리면 무같이 미쭉한 영팔이는 욱욱 헛힘을 주어 춤을 추고 있을 것이다. 아낙들은 노인들 아이들 틈새에서 제 남편 노는 꼴을 반쯤은 부끄럽고 반쯤은 자랑스러워 콧물을 홀짝일 것이다. 타작마당에서 한마당 벌이고 나면 시장기가 든 농부들은 강가도 당산도 아닌 마을길을 누비다가 삽짝 큰 집에 밀고 들어 한바탕 지신(地神)을 밟고 그러고 나면 갈고리 같은 손으로 땀을 닦으며 술과 밥을 먹게 될 것이다.', '팔월 한가위는 투명하고 삽삽한 한산 세모시 같은 비애는 아닐는지. 태고적부터 이미 죽음의 그림자요, 어둠의 강을 건너는 달에 연유된 축제가 과연 풍요의 상징이라 할 수 있을는지. 서늘한 달이 산마루에 걸리면 자잔한 나뭇가지들이 얼기설기한 그림자를 드리우고 소복 단장한 청상의 과부는 밤길을 홀로 가는데 -- 팔월 한가위는 한산 세모시 같은 처량한 삶의 막바지, 체념을 묵시(?示)하는 축제나 아닐는지. 우주 만물 그중에서도 가난한 영혼들에게는.', '가을의 대지에는 열매를 맺어놓고 쓰러진 잔해가 굴러 있다. 여기저기 얼마든지 굴러 있다. 쓸쓸하고 안쓰럽고 엄숙한 잔해 위를 검시(檢屍)하듯 맴돌던 찬바람은 어느 서슬엔가 사람들 마음에 부딪쳐와서 서러운 추억의 현(絃)을 건드려주기도 한다. 사람들은 하고많은 이별을 생각해보는 것이다. 흉년에 초근목피를 감당 못하고 죽어간 늙은 부모를, 돌림병에 약 한 첩을 써보지 못하고 죽인 자식을 거적에 말아서 묻은 동산을, 민란 때 관가에 끌려가서 원통하게 맞아죽은 남편을, 지금은 흙 속에서 잠이 들어버린 그 숱한 이웃들을, 바람은 서러운 추억의 현을 가만가만 흔들어준다.', '"저승에나 가서 잘사는가."', '사람들은 익어가는 들판의 곡식에서 위안을 얻기도 한다. 그러나 들판의 익어가는 곡식은 쓰라린 마음에 못을 박기도 한다. 가난하게 굶주리며 살다 간 사람들 때문에……', '"이만하믄 묵을 긴데……"', '풍요하고 떠들썩하면서도 쓸쓸하고 가슴 아픈 축제, 한산 세모시 같은 한가위가 지나고 나면 산기슭에서 먼, 먼 지평선까지 텅 비어버린 들판은 놀을 받고 허무하게 누워 있을 것이다. 마을 뒷산 잡목 숲과 오도마니 홀로 솟은 묏등이 누릿누릿 시들 것이다. 이러고저러고 해서 세운 송덕비며 이끼가 낀 열녀비며 또는 장승 옆에 한두 그루씩 서 있는 백일홍나무에는 물기 잃은 바람이 지나갈 것이다. 그러고 나면 겨울의 긴 밤이 다가오는 소리를 들을 수 있다.', '해가 서산에 떨어지고부터 더욱 흐느끼는 듯 꽹과리 소리는 여전히 마을 먼 곳에서 들려오고 있었다. 밤을 지샐 모양이다. 하기는 마을 처녀들의 놀이는 이제부터, 달 뜨기를 기다려 강가 모래밭에서 호작거리는 물 소리를 들으며 시작될 것이다.']
['용왕 님 심사 풀다 안 하겄 그 래야 개다 풍년 들다 제', '젯상 못 오르다 민물 개다 어디 개다 당산 가다 당산', '누군가 팔팔하다 반대 나서다 너희 들 그렇다 말다 두 만 아비 느릿느릿 징 칠 것 봉기 헤죽헤죽 웃다 구경 하다 아낙 들 보고 부끄럽다 고깔 흔들다 것 이 들 한창 일 하다 나이 살림 기틀 잡고 있다 삼십 대 중간 쯤 장정 들이다 나이 좀 처지다 축 장구 메다 하얗다 베 수건 어깨 걸다 싱긋이 웃다 크다 키 점잖다 가누다 맴 도 이용 李龍 그 누구 누구 해도 마을 제일 풍 신 좋다 인물 잘나다 사나이 마음 응어리 웃음 풀다 장단 칠성 북 더덩 덩 뚜 드리다 무 밉다 쭉 영 팔이 욱욱 헛힘 주어 춤 추다 있다 것 아낙 들 노 아이 들 틈새 제 남편 노 꼴 반 쯤 부끄럽다 반 쯤 자랑스럽다 콧물 홀짝 일 것 타 작 마당 한 마당 벌이 나다 시 장기 들다 농부 들 강가 당산 아니다 마을 길 누비 다가 삽짝 크다 집 밀고 들다 한바탕 지신 地神 밟다 그렇다 나다 갈고리 같다 손 땀 닦다 술 밥 먹다 되다 것', '팔월 한가위 투명하다 삽삽 한산 세 모시 같다 비애 아니다 태고 적 이미 죽음 그림자 어둠 강 건너다 달 연유 되다 축제 과연 풍요 상징 하다 수 있다 서늘하다 달이 산마루 걸리다 자 잔한 나뭇가지 들 얼기설기하다 그림자 드리우다 소복 단장 청상 과부 밤길 홀로 가다 팔월 한가위 한산 세 모시 같다 처량하다 삶 막바지 체념 묵시 示 하다 축제 아니다 우주 만물 그 중 가난하다 영혼 들', '가을 대지 열매 맺다 쓰러지다 잔해 구르다 있다 여기저기 얼마 구르다 있다 쓸쓸하다 안쓰럽다 엄숙하다 잔해 위 검시 檢屍 맴돌다 찬 바람 어느 서슬 가다 사람 들 마음 부딪치다 서다 서럽다 추억 현 絃 건드리다 주기도 하다 사람 들 하고많다 이별 생각 해보다 것 흉년 초 근 목피 감당 못 죽 어간 늙다 부모 돌림병 약 하다 첩 써다 보지 못 죽이다 자식 거적 말다 묻다 동산 민란 때 관가 끌리다 원통 하다 맞다 죽다 남편 지금 흙 속 잠 들다 버리다 그 숱 이웃 들 바람 서럽다 추억 현 가만가만 흔들다 주다', '저승 가다 잘살다', '사람 들 익다 들판 곡식 위안 얻다 하다 그러나 들판 익다 곡식 쓰라리다 마음 못 박다 하다 가난하다 굶주리다 살다 간 사람 들 때문', '이만 하므다 묵 기다', '풍요 떠들썩하다 쓸쓸하다 가슴 아프다 축제 한산 세 모시 같다 한가위 지나다 나다 산기슭 멀다 멀다 지평선 텅 비어 버리다 들판 놀 받다 허무하다 눕다 있다 것 마을 뒷산 잡목 숲 오도마니 홀로 솟다 묏등 누릿누릿 시들다 것 이르다 저러다 하다 세운 송덕비 이끼 끼다 열녀 비 또는 장승 옆 한두 그루 씩 서다 있다 백일홍나무 물기 잃다 바람 지나가다 것 그렇다 나다 겨울 기다 밤 다가오다 소리 들다 수 있다', '해 서산 떨어지다 더욱 흐 느끼다 듯 꽹과리 소리 여전하다 마을 멀다 곳 들려오다 있다 밤 지다 새다 모양 하기는 마을 처녀 들 놀이 이제 달 뜨다 기르다 기다리다 강가 모래밭 호 작 거리 물 소리 들다 시작 되다 것']
"""

 

 

모델 생성

wakati_file ='tojo.wakati'
with open(wakati_file,'w',encoding='utf-8') as fp:
  fp.write("\n".join(results))

data = word2vec.LineSentence(wakati_file)  # Word2Vec 모델 입력으로 사용할  LineSentence 객체
model = word2vec.Word2Vec(data, vector_size=200, window=10,hs=1,min_count=2,sg=1)
    # vector_size : 문장의 벡터의 차원
    # window: 한 문장 내에서의 최대 거리값.
    # hs=1 : hierarchical softmax 학습
    # min_count : 발생빈도가 이보다 낮으면 무시
    # sg : 학습 알고리즘 선택 1 이면 -> skip-gram 사용

# 유사도 검색을 위한 학습 모델

# 학습모델 저장
model.save('tojo.model')

# 모델 불러오기
model = word2vec.Word2Vec.load('tojo.model')

model.corpus_count # 학습된 말뭉치 개수 # 3376
model.corpus_total_words # 말뭉치 내 전체 단어개수
model.wv.most_similar(positive=['땅'])
"""
[('조상', 0.8887168765068054),
 ('못지않다', 0.8615437150001526),
 ('꾼', 0.8614882230758667),
 ('장차', 0.8505263328552246),
 ('보름', 0.8448419570922852),
 ('수능', 0.843887209892273),
 ('경신', 0.8434568643569946),
 ('벼슬길', 0.8411835432052612),
 ('몹쓸', 0.8410126566886902),
 ('봇짐', 0.8401477932929993)]
 """

 

Wiki 모델 다루기

# 위키피디아 (한국어판) 데이터

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

model = word2vec.Word2Vec.load(os.path.join(base_path,'wiki','wiki.model'))
model.wv.most_similar(positive=['Python','파이썬'])
"""
[('Perl', 0.9213457107543945),
 ('Java', 0.9069113731384277),
 ('Tcl', 0.9054787755012512),
 ('MATLAB', 0.8736515641212463),
 ('Lisp', 0.869271457195282),
 ('자바스크립트', 0.8669256567955017),
 ('하스켈', 0.8633923530578613),
 ('JSP', 0.8586523532867432),
 ('IDL', 0.8562408089637756),
 ('CLI', 0.8507612943649292)]
"""

# 아빠 -  남성 + 여성 => ?
model.wv.most_similar(positive=['아빠','여성'],negative=['남성'])
"""
[('엄마', 0.8517740368843079),
 ('아저씨', 0.682062029838562),
 ('어디가', 0.6796489953994751),
 ('친구', 0.6589521169662476),
 ('신혼', 0.6444262266159058),
 ('괴짜', 0.6426041722297668),
 ('할머니', 0.6371489763259888),
 ('아줌마', 0.6364408135414124),
 ('룸메이트', 0.6234321594238281),
 ('아내', 0.619864821434021)]
"""

'AI > ML' 카테고리의 다른 글

Attention Mechanism  (0) 2026.04.19
인코더 디코더 Seq2Seq  (0) 2026.04.18
자연어 처리 (NLP)  (0) 2026.04.16
LSTM(2)  (1) 2026.04.15
LSTM(1)  (1) 2026.04.14