Word2vec 모델을 학습시키고 사용해보는 것이 목표

  • 나무위키 덤프 활용 - 정제 - 텍스트로 된 순수 문장 얻기
  • 형태소 분석 - 형태소 분류
  • 말뭉치(Corpus) 데이터 준비
  • 말뭉치를 활용해서 Word2vec 모델 학습
  • Word2vec 모델 활용

In [1]:
import ijson
import gensim
import re

In [2]:
input_filename = "/Users/byeon/Downloads/namuwiki180326/namuwiki_20180326.json"
output_filename = "/Users/byeon/Downloads/namuwiki180326/namuwiki_20180326_mini.txt"

In [3]:
input_file = open(input_filename, 'r', encoding='utf-8')
texts = ijson.items(input_filename, 'item.text')

In [22]:
for some in zip(range(3), texts):
    print(some)


(0, '#redirect 느낌표\n')
(1, '[[파일:3444050440.jpg]]\n([[신 세계수의 미궁 2]]에서 뜬 !!아앗!!)\n{{{+1 !!ああっと!! }}}\n\n[[세계수의 미궁 시리즈]]에 전통으로 등장하는 대사. [[세계수의 미궁 2 제왕의 성배|2편 제왕의 성배]]부터 등장했으며, 훌륭한 [[사망 플래그]]의 예시이다.\n\n세계수의 모험가들이 탐험하는 던전인 수해의 구석구석에는 채취/벌채/채굴 포인트가 있으며, 이를 위한 채집 스킬에 투자하면 제한된 채집 기회에 보다 큰 이득을 챙길 수 있다. 그러나 분배할 수 있는 스킬 포인트는 한정된 만큼 채집 스킬에 투자하는 만큼 전투 스킬 레벨은 낮아지게 된다.\n\n 1. 채집용 캐릭터들로 이루어진 약한 파티(ex: [[레인저(세계수의 미궁 2)|레인저]] 5명)가 수해에 입장한다.\n 1. 필드 전투를 회피하면서 채집 포인트에 도착해 열심히 아이템을 캐는 중에...\n 1. \'\'\'!!아앗!!\'\'\' ~~라플레시아가 나타났다!~~\n \'\'\'이때 등장하는 것은 [[FOE(세계수의 미궁 시리즈)|FOE]]는 아닌 일단 필드 졸개지만, 훨씬 위 층에 등장하는 강력한 졸개이며 선 턴을 빼앗긴다!\'\'\'\n 1. \'\'\'[[으앙 죽음|떡잎]]\'\'\'(hage)\n\n작품마다 !!아앗!!의 세세한 모습은 다르다. 그 악랄함은 첫 등장한 작품이자 시리즈 중에서도 불친절하기로 정평이 난 2편이 절정이었는데, 그야말로 위의 !!아앗!! 시퀀스 그대로, 묻지도 따지지도 않고 채집할 때마다 일정 확률로 \'\'\'강제로\'\'\' 전투에 돌입해야 했다. 게다가 이럴 때 쓰라고 있는 레인저의 스킬 \'위험감지(중간 확률로 적의 선제공격을 무효화)\'는 작동하지 않았다!\n[[세계수의 미궁 3 성해의 내방자|3편]], [[세계수의 미궁 4 전승의 거신|4편]]에는 숨통이 트이게도 채집 중 낮은 확률로 "좋은 아이템을 얻을 수 있을 것 같지만... 주변에서 몬스터들의 기척이 느껴진다."는 메시지가 뜨고 이때 운이 좋으면 레어 아이템을 얻을 수 있지만 반대의 경우 적과 싸우게 되는 것으로 조정되었다. 단 4편은 움직이지 않고 채집할 때도 턴이 경과하도록 조정되었기 때문에 주변에 있는 FOE를 잊고 채집에 몰두하다가 FOE와 부딪히면 FOE 버전 !!아앗!!이 뜬다. 그리고 난이도 CASUAL로 플레이시 FOE로 인한 !!아앗!!을 제외하면 절대로 발생하지 않는다.\n[[신 세계수의 미궁 밀레니엄의 소녀|신 세계수의]] [[신 세계수의 미궁 2 파프니르기사|미궁 시리즈]], 그 이후에 나온 최신작 [[세계수의 미궁 5 오랜 신화의 끝|5편]]에서는 채집 방식이 한 턴으로 끝나는 구조[* 채집으로 한번 아이템을 획득하면 "다시, (채집스킬)에 의해..."가 뜨면서 한꺼번에 획득되는 구조.]로 바뀐 덕분인지 강제 조우로 다시 회귀해버렸다(...). 그나마 위험감지 먹통과 같은 버그성 난점들은 수정되었다.\n\n세계수 시스템을 기반으로 한 [[페르소나 시리즈]]와의 콜라보 작품 [[페르소나 Q 섀도우 오브 더 래버린스]]에도 물론 등장. 3, 4편과 같이 파워 스팟에서 채집 도중 메시지가 뜨고, 실패하면 파티에 참가하고 있는 멤버중 한명의 [[http://nico.ms/sm25683358|아앗! 하는 음성]]~~또는 [[고로마루|개소리]]~~과 함께 그 던전의 \'강적\'인 거대 섀도우가 나타난다. 그러나 내비 전용 스킬인 뱀 눈 노려보기(위험감지와 같은 효과), 채집 보조 스킬은 파티의 전투력에 전혀 지장을 주지 않고, \'대안심\'을 달면 거의 볼 일이 없어져서 초중반 이후 존재감이 급격히 줄어든다.\n\n여담으로, 2편에서 채집 도중 !!아앗!!이 뜰 확률은 [[http://www.atlusnet.jp/topic/detail/910|고작 1%였다고 한다.]] 낮아보이는 확률이어도 플레이 중 한번이라도 일어나는 것을 경험하는 체감 확률을 고려해서 확률을 설정한다고.\n\n그 기원은 1인칭 던전 크롤러의 원조 [[위저드리]]에서 함정을 건드렸을 때 나오는 대사 Oops!(おおっと!)라고 한다.\n\n[[분류:세계수의 미궁 시리즈]]')
(2, ' * 상위 문서: [[개그 콘서트/종영 코너]]\n[include(틀:다른 뜻1, other1=말줄임표 등으로 사용하는 용어, rd1=(...))]\n\n||<tablebordercolor=#878787><tablealign=right> \'\'\'코너명\'\'\' || “……” ||\n|| \'\'\'시작\'\'\' || [[2013년]] [[5월 26일]] ||\n|| \'\'\'종료\'\'\' || 2013년 [[10월 13일]] ||\n|| \'\'\'출연진\'\'\' || [[유민상#s-1|유민상]], [[김희원]], [[송필근]], [[남궁경호]] ||\n|| \'\'\'유행어\'\'\' || XX는 더 이상합니다[* 어색한 상황을 수습해보려는 변명이 더 안 좋은 결과를 낼 때 나오는 말.] ||\n\n[목차]\n\n== 소개 ==\n--[[나는 킬러다|2년 뒤에는 사위가 장인을 죽이려 한다]].--\n\n\'\'\'진짜로 코너 [[이름]]이 ([[말풍선]])“……”[* 큰 따옴표도 포함된다.]이다\'\'\'. 언론에서는 이 코너를 언급할 때 \'점점점\' 또는 \'점점점점점점\'이라는 표현을 사용했다. 코너명의 유래는 흔히 쓰이는 [[...|말줄임표]]. 2013년 5월 26일부터 방송되었고 [[김희원]], 남궁경호, [[유민상#s-1|유민상]], [[송필근]]이 출연했다.\n\n남자친구(남궁경호)와 여자친구(김희원)의 아버지(유민상) 간의 어색함을 다룬 코미디. 코너 초창기에는 남자친구 역인 남궁경호의 비중이 높았고 송필근은 배달부나 이웃주민 등 조연 역할이었으나, 송필근이 남궁경호의 아버지 역할(즉 유민상과 사돈관계) 컨셉으로 고정되면서 남궁경호의 비중이 줄어들고, 심지어 아예 등장하지 않는 회차도 간간히 있다. 사실상 유민상과 송필근의 투톱 체제로 나간다. 따라서 그 이후로는 주로 사돈 간의 어색함을 다루고 있다. 3인(혹은 4인)이 있다가 여자친구(혹은 경호-희원 커플)가 자리를 비우면 남은 두 사람은 어색해 하면서 아무 말 없이 중간중간 몇 마디 말만 던지고 다시 조용한 분위기가 되는 것이 주된 패턴이다. 자리마다 항상 큰 괘종시계가 있어서 아무 말 없을 때마다 째깍째깍 소리가 나는 것이 웃음 포인트. 유민상이 사돈어른(송필근)이 찾아오기 전에 집안에 있는 괘종시계를 미리 치워버린 에피소드도 있었는데, 사돈어른이 선물로 벽시계를 사오면서 어색한 상황에서 째깍째깍 소리가 나게 되었다.\n\n중간에 제 3자(송필근)가 끼어들며 남자친구가 자리를 비우면 제 3자와 아버지 간에도 사이가 어색해진다. 6화(2013년 6월 30일 방송분)부터 송필근은 주로 유민상의 사돈어른 役을 맡고 있다. 그 외에도 간혹 김희원의 오빠 역할 등 다른 역할을 한다. 대화가 없는 상황을 보여주기도 하고, 어떤 사람은 대화가 별로 없는 현대 사회를 보여주기도 한다고 해석한다.\n\n김희원은 유일하게 어색해하지 않게 붙임성있게 말 잘 하지만, 대신 [[눈새|눈치가 없다]]. 그리고 그녀의 눈치 없는 말로 주변은 더 어색해진다.\n\n== 상세 ==\n7화(2013년 7월 14일 방송분)에서는 사돈어른이 [[2PM]] 춤 추다가 입원해서 놀림당했는데 건너편에 [[미라]]처럼 깁스를 하고 있던 유인석이 한 손을 뻗어 심장박동을 시전했다. ~~캔 유 필 마 핫빗?~~ 그리고 아빠와 딸이 모두 [[박카스|박X스]]를 한 \'\'\'[[박스]]\'\'\'씩 사왔는데, 병실 장롱에 \'\'\'[[박카스|박X스]]가 한가득\'\'\' 들어있었다. 유민상이 병문안 때는 [[박카스|박X스]]를 사가는 것이 좋다고 생각했는데, 알고보니 전에 병문안 왔던 사람들도 같은 생각을 했던 것.\n\n9화(2013년 7월 28일 방송분)에서는 송필근이 김희원의 오빠 역할로 나온다. 경호-희원 커플이 유민상 몰래 괌에 갔다온 것이 들통나면서 남궁경호가 [[괌]]을 "\'\'\'[[대전광역시|대전]] [[구암역(대전)|구]][[유성구#s-4.1.2|암]]\'\'\'(Guam)"이라고 말하니까 유민상의 드립이"난 \'\'\'[[몽둥이]] 괌~\'\'\'"\n\n회가 거듭하면 거듭할수록 커플의 진도가 쭉쭉 잘 나가서 김희원이 \'\'\'[[배꼽티]]\'\'\'도 자랑했고, 11화(2013년 8월 25일 방송분)에서는 김희원이 웨딩드레스를 맞췄다.\n\n14화(2013년 9월 15일 방송분)에서는 송필근이 사돈 유민상의 아버지 희수연을 기념하고자 화환을 보냈는데, 문제는 유민상 아버지의 본명이 유[[죽빵|죽방]]이라 본인이 그 이름을 매우 싫어했다. (그래서 현수막은 "유 할아버지" 라고 걸려있었다.) ~~이 정도면 [[개명]]을...~~ 하지만 송필근은 그 사실을 몰랐기 때문에 예식장에 이름이 크게 적힌 화환이 배달되었으며 뒤늦게 상황을 수습한다는 게 \'\'\'[[유방(신체)|가운데 글자를 가리는 바람에]]\'\'\'...\n\n15화(2013년 9월 22일 방송분)에서는 [[정태호]]가 [[나훈아|너훈아]] 역할로 출연했다.\n\n마지막화인 17화(2013년 10월 13일 방송분)에서는 [[박은영(개그우먼)|박은영]]이 유민상과 송필근이 [[건강검진]]을 받으러 간 [[병원]]의 [[간호사]] 역할로 나왔다.[* 이날 방송분에는 직접적으로 마지막회라고 언급했더니 방청객들이 아쉬워하자 유민상이 모든 사람들에게 다 까라고 그런다.]\n\n극중에서 부자관계로 나오는 27기 남궁경호와 송필근은 동갑이자 성남예고, [[인덕대학]] 동기로 둘 다 91년생이다.\n\n[[분류:개그 콘서트 코너]]')

In [6]:
chinese = re.compile(u'[⺀-⺙⺛-⻳⼀-⿕々〇〡-〩〸-〺〻㐀-䶵一-鿃豈-鶴侮-頻並-龎]', re.UNICODE)
japanese = re.compile(u'[\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u4e00-\u9faf\u3400-\u4dbf]', re.UNICODE)

# hangul = re.compile('[^ ㄱ-ㅣ가-힣]+') # 한글과 띄어쓰기를 제외한 모든 글자
# hangul = re.compile('[^ \u3131-\u3163\uac00-\ud7a3]+')  # 위와 동일
# result = hangul.sub('', s) # 한글과 띄어쓰기를 제외한 모든 부분을 제거


def strip_wiki_literal(text):               
    text = re.sub(r"\{\{\{#\!html[^\}]*\}\}\}", '', text, flags=re.IGNORECASE|re.MULTILINE|re.DOTALL) # remove html
    text = re.sub(r"#redirect .*", '', text, flags=re.IGNORECASE) # remove redirect
    text = re.sub(r"\[\[분류:.*", '', text) # remove 분류
    text = re.sub(r"\[\[파일:.*", '', text) # remove 파일
    text = re.sub(r"\* 상위 문서 ?:.*", '', text) # remove 상위문서        
    text = re.sub(r"\[youtube\(\w+\)\]", '', text, flags=re.IGNORECASE) # remove youtube
    text = re.sub(r"\[include\(([^\]|]*)(\|[^]]*)?\]", r'\1', text, flags=re.IGNORECASE) # remove include
    text = re.sub(r"\[\[(?:[^\]|]*\|)?([^\]|]+)\]\]", r'\1', text) # remove link
    text = re.sub(r"\[\*([^\]]*)\]", '', text) # remove 각주
    text = re.sub(r"\{\{\{([^\ }|]*) ([^\}|]*)\}\}\}", r'\2', text) # remove text color/size
    text = re.sub(r"'''([^']*)'''", r'\1', text) # remove text bold
    text = re.sub(r"(~~|--)([^']*)(~~|--)", '', text) # remove strike-through
    text = re.sub(r"\|\|(.*)\|\|", '', text) # remove table
    text = re.sub(r"\n\s*\n*", '\n', text) # remove empty line                       
    text = chinese.sub('', text) # remove chinese
    text = japanese.sub('', text) # remove japanese
    return text

In [26]:
strip_wiki_literal(" XX는 더 이상합니다[* 어색한 상황을 수습해보려는 변명이 더 안 좋은 결과를 낼 때 나오는 말.] ||\n\n[목차]\n\n== 소개 ==\n--[[나는 킬러다|2년 뒤에는 사위가 장인을 죽이려 한다]].-")


Out[26]:
' XX는 더 이상합니다 ||\n[목차]\n== 소개 ==\n--2년 뒤에는 사위가 장인을 죽이려 한다.-'

In [28]:
for index, text in zip(range(3), texts):
    print(strip_wiki_literal(text))


틀:링크시 주의, 링크=[[\\\\#FairyJoke])]
[목차]
== 개요 ==
사운드 볼텍스 시리즈에 수록된 동방 프로젝트 어레인지 곡이며, 리믹서는 uno(IOSYS). \#Fairy_dancing_in_lake의 후속곡이기도 하다. 원곡은 동방홍마향 2면 필드곡인 '르네이트 엘프()'이며, 쥬크 하우스의 영향을 받아 리믹스했다고 리믹서 본인이 밝힌 바 있다.
동 작곡가가 DJ Laugh 명의로 그루브 코스터에 제공한 Stardust Vox와 전개, 음색이 많이 닮았다.
제 11회 하쿠레이 신사 예대제에서 발매된 IOSYS의 앨범 Prank Masters!에 수록되었다.
== 사운드 볼텍스에 수록 ==
* 곡 목록으로 돌아가기
* SKILL ANALYZER 수록
* EXHAUST : Skill Level 10(2014.7.4 ~ 2014.11.20), Skill Level 10 C코스(2014.11.20 ~ 2014.12.26)
자켓은 하쿠레이 신사 예대제 11회에 발매된 Prank Masters!의 표지를 그대로 썼다. 자켓의 캐릭터는 대요정과 치르노.
=== 채보 상세 ===
[youtube(HJM9vrD8Ngw, width=420, height=600)]
EXH 패턴 PERFECT 영상
좌우 노브 분리 영상
이미 2014년 5월 동방 예대제에서 \#Fairy_dancing_in_lake의 후속곡이 수록될 것이라는 정보가 밝혀졌었고, 그보다 훨씬 악랄한 패턴을 보여주겠다는 예고가 떴다. 그리고 수록된 것은 대다수가 예상한 Hirayasu Matsudo 제작의 고난이도 노브곡. Hirayasu Matsudo가 처음으로 단독 제작한 레벨 15.
페어리 댄싱의 물수제비를 꼬아 놓은데다가 중간중간 보이는 HYENA의 고속 직각노브, GAMBOL(dfk SLC rmx) INF의 꽈배기 노브 등등 기존의 노브곡들의 대표 패턴들이 한데 섞여 나온다. 그리고 기습적으로 섞여나오는 BT, FX 트릴 때문에 여타 다른 Hirayasu Matsudo의 노브곡에 비해 니어나 에러를 낼 위험이 크다.
개인차가 매우 강한 노브곡이기에 클리어 난이도와 스코어링 난이도 모두 개인차 폭이 매우 넓다. 노브에 약하다면 17레벨 클리어가 쌓여 가면서도 이 곡에서 어려움을 겪을 수도 있지만, 노브에 강한 6~7단 정도의 유저가 상당히 일찍 클리어하는 경우도 존재한다. 상기한 틱 카운트 보정덕에 일반적인 클리어 난이도는 17 중에선 높지 않은 편이다. 스코어링의 경우는 노브에 강하다면 패턴의 대다수가 노브이므로 무난하게 고득점을 뽑아내겠지만, 반대로 이런 패턴에 약하다면 제 아무리 틱 카운트 보정이 걸려있다한들 탈선이 자주 일어나다보니 점수가 곤두박질 칠 수 밖에 없다.
클리어만이 목적이라면 반대쪽 지속노브를 놓치더라도 직각노브만큼은 놓치지 않는다는 생각으로 플레이하는게 좋다. 지속노브는 보정이 걸려있기때문에 게이지 증감량이 적은 편이므로, 곡선+지속노브와 직각노브가 함께나오는 구간에서 처리하기가 힘들다면 둘다 놓치느니 직각노브는 어떻게든 처리한다는 마인드로 플레이하면 게이지 보전에 도움이 된다.
사운드 볼텍스 IV 헤븐리 헤이븐에서는 17레벨을 배정받았다. 지속적인 난이도 인플레로 인해 이 곡들보다 더 한 곡들이 등장함으로서 체감 난이도가 크게 낮아졌고 아예 물렙이라는 의견도 종종 나온다. 하지만 노브곡 특성상 개인차의 폭이 넓기 때문에 적정레벨로 느끼는 사람도 다수 있다.
니코니코 동화에서 이 곡의 노브 흐름에 맞춰  3명이 고개를 돌려본 영상이 나오기도 했다.  또한 한쪽 팔로만 클리어하는 동영상도 올라와 있다.
[youtube(DGce2EOcpd4, width=360, height=640)]
NOV 패턴은 패턴에 노브와 FX 롱노트 밖에 없기 때문에  Profession NOV처럼 UC가 곧 퍼펙트가 된다.



틀:링크시 주의, 링크=[[\\\\#Fairy_dancing_in_lake])]
[목차]
== 개요 ==
사운드 볼텍스의 수록곡. 원곡은 동방홍마향 2면 테마인 르네이트 엘프()이며, 리믹서는 uno(IOSYS). 덤으로 자켓 담당은 리믹서의 여동생이라고 한다. 자켓에 그려진 캐릭터는 대요정.
트랩 장르에 가깝게 리믹스되었다. SOUND VOLTEX ULTIMATE TRACKS 동방홍마향 리믹스 디스크 2에 #Full_length 버전이 수록되었다.
그리고 2014년 5월 하쿠레이 신사 예대제 11회의 시연회에서 이 곡의 후속곡인 \#FairyJoke가 공개되었다.
== 사운드 볼텍스 ==
사운드 볼텍스 플로어 '동방홍마향 리믹스곡 컨테스트'의  부문 당선곡이다.
* 곡 목록으로 돌아가기
* SKILL ANAYZER 수록
* ADVANCED : Skill Level 04(2014.4.4 ~ 2014.6.5, 2014.7.4 ~ 2014.8.1), The 4th KAC 엔조이♪고릴라 코스 D
* EXHAUST : Skill Level 08(2014.5.1 ~ 2014.7.4), Skill Level 08 B코스(2014.11.20 ~ 2014.12.26), The 4th KAC 챌린지★고릴라 코스 D(2015.1.12 ~ 2015.1.19)
||<bgcolor=#E9ECEF>
GUMI 오리지널, SDVXII제작 기념 리믹스 대회에 이어 4번째세요! 시드 비셔스!  uno(IOSYS)이라고 합니다.
동방홍마향 리믹스 컨테스트에서의 채용, 기쁩니다. 감사합니다!
악곡 모집 시기로 추측컨대 이 곡은 여름에 공개될 것이다!
그렇게 생각해 화제의 지팡구에 초점을 두고 호수에서 춤추는 대요정을 이미지화했습니다.
상쾌하고 물 속을 떠다니는 같은 편곡이 되었다고 생각하지만 이대로 가면 이 곡이 나올 때에는 이미 여름이 끝나있겠군요! 젠장-! 지쳤어! 
-당선자 uno(IOSYS) 코멘트-
||
||<bgcolor=#E9ECEF>
※이 작품은 자켓도 함께 채용되었습니다
일러스트레이터명
냥꼬로모찌라고 합니다└('ω')//
채용해 주셔서 정말 황송합니다! 하와와ㅋ!
자켓 제작에 익숙하지 않아서 고생했었지만, uno씨는 물론 RoughSketch님에게 조언을 받거나, DJ.Laugh씨에게 작품의 체크를 받거나, 가끔 러프스케씨에게  푸념을 늘어놓으면서,  촌스럽고 스타일리쉬하고 지팡구스러운 재킷이 완성되었습니다!
부드러운 대요정쨩이 마음에 드네요. 그리고 수초.
그래서 "#페어리 댄싱 인 레이크".
"어떤 보면이 될까-"라는 망상이 끊이지 않은 좋은 곡입니다.
플레이할 때는 해시태그를 했으면 좋겠어요!
-당선자  코멘트-
||
팬게임이 있다. 해보기


In [4]:
input_file = open(input_filename, 'r', encoding='utf-8')
texts = ijson.items(input_file, 'item.text')

In [7]:
%%time

item_limit = 10000
minimum_length = 500

with open(output_filename, 'w', encoding='utf-8') as output_file:
    for index, text in zip(range(item_limit), texts):
        if (len(text) > minimum_length):
            try:
                a_line = strip_wiki_literal(text)
                output_file.write(a_line + '\n')
            except UnicodeEncodeError as e:
                print("UnicodeEncodeError ({0}) : {1}".format(e, text))


CPU times: user 54.1 s, sys: 13 s, total: 1min 7s
Wall time: 1min 9s

In [8]:
import konlpy

In [9]:
from konlpy.tag import Twitter

In [10]:
result = Twitter().pos("나무위키 말뭉치를 만들어보자")
for pos in result:
    print(pos[0]+ ' ' + pos[1])


나무 Noun
위키 Noun
말뭉치 Noun
를 Josa
만들어 Verb
보자 Verb

In [11]:
tagger = Twitter()

In [12]:
def flat(content):
    return ["{}/{}".format(word, tag) for word, tag in tagger.pos(content)]

In [13]:
tagged = flat("나무위키 말뭉치를 만들어보자")

In [14]:
input_filename = "/Users/byeon/Downloads/namuwiki180326/namuwiki_20180326_mini.txt"
output_filename = "/Users/byeon/Downloads/namuwiki180326/namuwiki_20180326_mini_pos_tagged_corpus.txt"

In [15]:
%%time
with open(output_filename, 'w', encoding='utf-8') as output_file:
    for line in open(input_filename, 'r', encoding='utf-8'):
        for sentence in line.split('.'):
            tagged = flat(sentence)
            if len(tagged) > 1:
                a_line = ' '.join(tagged)
                output_file.write(a_line + '\n')


CPU times: user 8min 7s, sys: 7.09 s, total: 8min 14s
Wall time: 8min 19s

In [16]:
from gensim import corpora, similarities
from gensim.models import Word2Vec

import os
import multiprocessing

input_filename = '/Users/byeon/Downloads/namuwiki180326/namuwiki_20180326_mini_pos_tagged_corpus.txt'
model_path = './model'

In [17]:
%%time
class SentenceReader(object):
    def __init__(self, input_filename):
        self.input_filename = input_filename
 
    def __iter__(self):
        for line in open(input_filename):
            yield line.split(' ')

sentences_vocab = SentenceReader(input_filename) # a memory-friendly iterator
sentences_train = SentenceReader(input_filename) # a memory-friendly iterator

config = {
    'min_count': 10,  # 등장 횟수가 10 이하인 단어는 무시
    'size': 300,  # 300차원짜리 벡터스페이스에 embedding
    'sg': 1,  # 0이면 CBOW, 1이면 skip-gram을 사용한다
    'batch_words': 10000,  # 사전을 구축할때 한번에 읽을 단어 수
    'iter': 10,  # 보통 딥러닝에서 말하는 epoch과 비슷한, 반복 횟수
    'workers': multiprocessing.cpu_count(),
}
word2vec_model = Word2Vec(**config)


CPU times: user 107 µs, sys: 6 µs, total: 113 µs
Wall time: 118 µs

In [18]:
%%time
token_count = sum([len(sentence) for sentence in sentences_vocab])
print(token_count)

word2vec_model.build_vocab(sentences_vocab)
word2vec_model.train(sentences_train, total_examples = token_count, epochs=word2vec_model.iter)


10103580
/usr/local/lib/python3.6/site-packages/ipykernel_launcher.py:5: DeprecationWarning: Call to deprecated `iter` (Attribute will be removed in 4.0.0, use self.epochs instead).
  """
CPU times: user 24min 51s, sys: 15.8 s, total: 25min 7s
Wall time: 3min 57s

In [25]:
word2vec_model.wv.most_similar(["서울/Noun"])


Out[25]:
[('부산/Noun', 0.5920711159706116),
 ('장충/Noun', 0.575017511844635),
 ('여의도/Noun', 0.5566101670265198),
 ('영등포구/Noun', 0.5554679036140442),
 ('종로/Noun', 0.5489655137062073),
 ('영등포/Noun', 0.547404408454895),
 ('압구정/Noun', 0.5453184843063354),
 ('인천/Noun', 0.5452240705490112),
 ('상암동/Noun', 0.5448856353759766),
 ('고법/Noun', 0.5424453616142273)]

In [26]:
word2vec_model.wv.most_similar(positive = ['서울/Noun', '미국/Noun'], negative=['한국/Noun'])


Out[26]:
[('제네바/Noun', 0.4128422439098358),
 ('뮌헨/Noun', 0.3984510600566864),
 ('컬럼비아/Noun', 0.39666545391082764),
 ('지방법원/Noun', 0.3959895670413971),
 ('건설/Noun\n', 0.3912340998649597),
 ('국회의사당/Noun', 0.3874393701553345),
 ('영등포/Noun', 0.3866955041885376),
 ('상트페테르부르크/Noun', 0.38594767451286316),
 ('영등포구/Noun', 0.3842099905014038),
 ('장충/Noun', 0.38419654965400696)]

In [28]:
word2vec_model.save(model_path)

In [ ]: