Word2Vec for word representation

concept of this algorithm

기본적으로 컴퓨터가 어떤 단어에 대해 인지할 수 있게 하기 위해서는 수치적인 방식으로 단어를 표현할 수 있어야 한다. 그러나 앞서 말했듯이, 수치화를 통해 단어의 개념적 차이를 나타내기가 근본적으로 힘들었다. 이 한계를 극복하기 전의 NLP는 ‘one-hot encoding’ 방식을 많이 사용했다. 예를 들어, 내가 어떤 단어들이 있는지에 대한 단어 n개짜리 ‘사전’ (Dictionary)이 있다고 해보자. 이 때, 어떤 단어를 표현하기 위해서 길이 n짜리 벡터를 하나 만들고, 그 단어가 해당되는 자리에 1을 넣고 나머지 자리들에는 0을 넣는 것이다. 사전이 [감자, 딸기, 사과, 수박] 이라면 사과를 표현하는 벡터는 [0, 0, 1, 0] 이 되는 식이다.
Naive Bayes를 이용한 스팸 분류기가 이 방법을 사용하는 전형적인 예시라고 생각할 수 있겠다. 단어 자체를 벡터화한 것은 아니지만, 이 경우 이메일 전체를 보면서 어떤 단어가 있으면 1, 없으면 0으로 나타내는 식으로 이메일 하나에 대한 벡터를 만든다. 이 방식은 당시에는 나름 좋은 성능을 내었고, 지금까지도 사용하는 사람들이 있지만 컴퓨터 자체가 ‘단어가 본질적으로 다른 단어와 어떤 차이점을 가지는 지 이해할 수가 없다’ 는 아주 큰 단점이 존재한다.
이러한 단점을 존재하기 위해 연구자들은 단어 자체가 가지는 의미 자체를 다차원 공간에서 ‘벡터화’ 하는 방식을 고안하게 되었다. 단어의 의미 자체를 벡터화할 수 있게 된다면, 기본적으로 이것을 사용해서 할 수 있는 일들이 굉장히 많아진다.
그렇다면, ‘어떻게 각 단어를 벡터화해야 하는가?’ 에 대한 문제가 관건이 될 것이다. 놀랍게도 이렇게 단어를 벡터화하는 방법 자체는 정말 예전부터 이루어져왔던 연구이다. 현재 ‘CBOW’와 ‘Skip-gram’ 이라는 아키텍쳐로 다시 한번 발전하여 현재 word2vec의 모양새로 이어지게 되었다.

Word2Vec 는 기본적으로 유사한 의미를 갖는 단어는 비슷한 문맥에서 등장한다는 이론을 바탕에 두고 있다. 예를들면 <음식>을 먹는다. 형태의 문맥이 있다고 하면 “사과를 먹는다. 포도를 먹는다. 밥을 먹는다. ” 모든 문장은 먹는다와 근처에서 발생하게 된다. 이러한 특징을 바탕으로 백터를 훈련하면 유사한 의미를 갖는 단어들은 유사한 백터 분포를 갖는다라고 말한다.  Word Embedding 기법은 모든 자연어 처리 알고리즘에 있어서 가장 중요한 전처리 작업으로 최근에는 전체 도큐먼트의 발생 빈도를 고려하는 Glove나 Ngram 방법을 접목한 FastText 등이 주로 사용되고 있으며, 순수한 Word2Vector 알고리즘 자체는 잘 사용하지 않는 추세이긴 하지만 매우 중요한 개념이라는 것은 변함 없다.

APIs – Define Neural Network

import requests
import json, os

url = "{0}:{1}".format(os.environ['HOSTNAME'] , "8000")

nn_id = "w2v0014"
nn_wf_ver_id ="1"

# Seq - 1
resp = requests.post('http://' + url + '/api/v1/type/common/target/nninfo/nnid/' + nn_id + '/',
                     json={
                         "biz_cate": "MES",
                         "biz_sub_cate": "M60",
                         "nn_title" : "test",
                         "nn_desc": "test desc",
                         "use_flag" : "Y",
                         "dir": "word2vec",
                         "config": "N"
                     })
data = json.loads(resp.json())
print("1.evaluation result : {0}".format(data))

resp = requests.post('http://' + url + '/api/v1/type/common/target/nninfo/nnid/' + nn_id + '/version/',
 json={
 "nn_def_list_info_nn_id": "",
 "nn_wf_ver_info": "test version info",
 "condition": "1",
 "active_flag": "Y"
 })
data = json.loads(resp.json())
print("2.evaluation result : {0}".format(data))

네트워크를 정의하고 버전 정보를 정의하는 작업은 공통적인 작업이다.
nn_id : Neural Network ID
biz_cate : Business 대분류
biz_sub_cate : Business 소분류
nn_title : Neural Network Title
nn_desc : Neural Network Description
use_flag : 사용여부
dir : 문제유형
config : Custom 여부

APIs – Initialize Graph Flow

resp = requests.post('http://' + url + '/api/v1/type/wf/target/init/mode/simple/'+ nn_id + '/wfver/1/',
                     json={
                         "type": "word2vec"
                     })
data = json.loads(resp.json())
print("3.evaluation result : {0}".format(data))

그래프 플로우를 초기화 하고 파이프라인 구조를 생성하는 작업이다.
심플타입으로 진행하기 때문에 정해진 파이프라인이 강제로 생성되며, 사용자가 정의한 파이프 라인을 읽어오는 기능, 신규 파이프라인 생성 기능 등 기타 기능을 제공한다.

APIs – Data Upload

return_dict = {}
return_dict['test'] = open('../../data/novel_1.txt', 'rb')

resp = requests.post('http://' + url + '/api/v1/type/wf/state/textdata/src/local/form/raw/prg/source/nnid/'+nn_id+'/ver/1/node/data_node/',
                     files = return_dict)

data = json.loads(resp.json())

훈련하고자 하는 데이터를 로컬에서 업로드한다.

APIs – Data Configuration

resp = requests.put('http://' + url + '/api/v1/type/wf/state/textdata/src/local/form/raw/prg/source/nnid/'+ nn_id + '/ver/1/node/data_node/',
                     json={
                         "source_server": "local",
                         "source_sql": "all",
                         "max_sentence_len" : 10,
                         "preprocess":  "None",
                     })
data = json.loads(resp.json())
print("5.evaluation result : {0}".format(data))

데이터 소스에 대한 정의로 로컬 파일을 사용하는 경우 별다른 설정은 사실상 필요하지 않다. 타입만 로컬만 넣어 주면 된다. 실제 소스 서버를 명시하는 경우 접속정보 등을 바탕으로 해당 서버에서 데이터를 ETL 작업을 수행한 후 후속 프로세스를 수행하지만사전에 데이터를 업로드해 놓은 상태이기 때문에 실제 ETL  작업은 Skip 된다.

APIs – Word2Vector configuration

resp = requests.put('http://' + url + '/api/v1/type/wf/state/netconf/detail/w2v/nnid/' + nn_id + '/ver/' + nn_wf_ver_id + '/node/netconf_node/',
                     json={
                        "window_size" : 5,
                        "vector_size" : 100,
                        "batch_size" : 100,
                        "iter" : 5,
                        "min_count" : 1,
                        "preprocess" : "None"
                     })
data = json.loads(resp.json())
print("9.evaluation result : {0}".format(data))

Word2Vector 알고 리즘을 수행하기 위한 하이퍼 파라메터를 정의한다.
– WindowSize : 문장내에서 기준단어에서 어느정도 범위까지 탐색할 것인지
– min_count : Dict 에 등록하기 위한 최소 발생 빈도
– preprocess : mecab 등 lexical Analysis 를 수행 후 훈련 할 수 있다

APIs – Execute train

resp = requests.post('http://' + url + '/api/v1/type/runmanager/state/train/nnid/'+nn_id+'/ver/'+nn_wf_ver_id+'/')
data = json.loads(resp.json())
print("14.evaluation result : {0}".format(data))

위와 같이 정의된 프로세스에 따라 훈련을 실행한다.

APIs – Inference Test

resp = requests.post('http://' + url + '/api/v1/type/service/state/predict/type/w2v/nnid/' + nn_id + '/ver/active/',
                     json={
                         "type": "vector",
                         "val_1":["관심"],
                         "val_2":[]
                        }
                     )
data = json.loads(resp.json())
print("evaluation result : {0}".format(data))

아래 예와 같이 단순히 해당 단어에 대한 백터를 출력할 수도 있고, 해당 단어와 백터간의 유사도가 높은 단어를 찾거나 해당 단어의 인덱스를 찾는 등 다양한 기능을 type 을 바꿔서 실행 할 수 있다.  아래는 “관심”이라는 단어에 대한 백터 출력 결과

evaluation result : [[-0.020525163039565086, 0.04692612960934639, 0.05030370131134987, -0.012286012060940266, -0.0037592644803225994, -0.030842192471027374, 0.01674736849963665, -0.054970309138298035, -0.08577895909547806, 0.1255255788564682, -0.02777358889579773, 0.03695392981171608, 0.044458433985710144, -0.007728930562734604, 0.08414790034294128, 0.058133892714977264, 0.04944032430648804, 0.01613127626478672, -0.040425531566143036, 0.004654400981962681, -0.03939636051654816, -0.0019560905639082193, -0.009940450079739094, -0.06451232731342316, 0.0569504015147686, -0.014093209989368916, 0.09073378145694733, 0.09947685152292252, 0.006592847406864166, -0.008854197338223457, 0.12631729245185852, 0.04848669841885567, 0.06378431618213654, -0.04620460793375969, 0.008887161500751972, -0.030518099665641785, -0.01516534760594368, 0.044853076338768005, -0.05782085284590721, -0.08027826994657516, 0.014025202952325344, 0.044981539249420166, 0.004896924365311861, -0.028371311724185944, -0.05109790712594986, -0.07373176515102386, -0.10512163490056992, 0.08453123271465302, -0.013461959548294544, 0.021848665550351143, -0.008970526047050953, -0.04527459293603897, -0.017793165519833565, 0.01753085106611252, 0.02533436194062233, 0.035888779908418655, 0.026869671419262886, 0.07286906987428665, -0.09840452671051025, 0.08030493557453156, 0.020363574847579002, 0.05747954919934273, -0.04360934719443321, -0.007815506309270859, 0.05689325928688049, 0.05190270394086838, -0.018432151526212692, 0.009586657397449017, -0.08955849707126617, -0.015274081379175186, 0.06507446616888046, -0.04223490506410599, -0.047457266598939896, -0.05493870750069618, 0.03036578930914402, -0.012590847909450531, 0.10204384475946426, -0.07904526591300964, -0.0001657690154388547, -0.09601821005344391, 0.018075214698910713, 0.05400990694761276, 0.0034184586256742477, 0.002286079805344343, 0.02704218029975891, -0.044543638825416565, 0.07505488395690918, 0.04921184480190277, -0.05573805049061775, 0.0022162178065627813, 0.03275308758020401, -0.11974544078111649, 0.0004437191819306463, -0.01948268711566925, 0.03747180849313736, 0.006018102169036865, -0.02106001414358616, -0.0002090744092129171, -0.01121156569570303, 0.012898841872811317]]

 

Categories: Word2Vec

Leave a Reply

Your email address will not be published. Required fields are marked *