cleanUrl: "/paper/word2vec-code"
๋
ผ๋ฌธ : Efficient Estimation Of Word Representations In Vector Space (Word2Vec)
์ ์ : Tomas Mikolov, Kai Chen, Greg Corrado, Jeffrey Dean
To beginCBOW ๋ชจ๋ธ ๊ตฌํCBOW ์ฝ๋ ๊ตฌํCBOW Classํ์ตtrain_cbow - ํ์ต ๊ณผ์ ํ์ต ๊ฒฐ๊ณผ๋จ์ด ๊ฐ ์ ์ฌ๋ ์ฐ์ฐSkip-gram ๋ชจ๋ธ ๊ตฌํSkip-gram Classforwardbackwardํ์ตํ์ต ๊ฒฐ๊ณผ๋จ์ด์ ๋ถ์ฐ ํํResultsMaximization of AccuracyComparison of Model ArchitecturesLarge Scale Parallel Training of ModelsMicrosoft Research Sentence Completion ChallengeExamples of the Learned RelationshipsConclusionreference
To begin
์ค๋์ ํฌ์คํธ๋ฅผ ์์ฑํ๊ธฐ์ ์์, ์ด์ ํฌ์คํธ๋ฅผ ์์ฝํ๋ฉฐ ์์ํ๊ฒ ์ต๋๋ค.
์์ธํ ๋ด์ฉ์ ์ด์ ํฌ์คํธEfficient Estimation Of Word Representations In Vector Space (Word2Vec) (1) ๋ฅผ ์ฐธ๊ณ ํด์ฃผ์ธ์!
ย
๋ณธ ๋
ผ๋ฌธ์์๋ ๋จ์ด๋ฅผ ๋ฒกํฐํํ ๋ ๋ถ์ฐ ํํ(distributed representation)์ ํตํด ๋จ์ด ๊ฐ ์๋ฏธ์ ์ ์ฌ๋๋ฅผ ํํํ ์ ์์ ๋ฟ๋ง ์๋๋ผ, multiple degrees of similarity๋ฅผ ๊ฐ์ง ์ ์๋๋ก ํ์์ต๋๋ค.
vector(โ์์ธโ) - vector(โ์๋โ) + vector(โ์ผ๋ณธโ)
์ ๊ฒฐ๊ณผ๋ก ์ป์ ๋ฒกํฐ์ ๊ฐ์ฅ ๊ฐ๊น์ด ๋จ์ด ๋ฒกํฐ๊ฐ โ๋์ฟโ๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ฐฉ์์ผ๋ก, ๋จ์ด ๋ฒกํฐ์ ์ฐ์ฐ์ด ๋จ์ด ์๋ฏธ์ ์ฐ์ฐ์ผ๋ก ๊ฐ๋ฅํ๋๋ก ์๋ก์ด ๋ชจ๋ธ ์ํคํ
์ณ๋ฅผ ๊ตฌ์ฑํ์ฌ syntactic, semantic ์์ญ์์ ๋์ ์ ํ๋๋ฅผ ๊ฐ์ง ์ ์๋๋ก ํ์์ต๋๋ค. ย
word2vec ๊ธฐ๋ฒ์ ์ ์ฉํ๋๋ฐ์ ์์ด์ ์ฒ๋ฆฌ ์ฑ๋ฅ ๋ฐ ํ์ต ์๋์ ๊ฐ์ ์ ์ํด CBOW(Continuous Bag-of-words)์ Skip-gram 2๊ฐ์ง์ architecture๋ฅผ ์ ์ํ์์ต๋๋ค.
CBOW(Continuous Bag-of-words)
: ์ฃผ๋ณ(๋งฅ๋ฝ)์ ๋จ์ด๋ค๋ก ์ค๊ฐ(์ค์ฌ)์ ๋จ์ด๋ฅผ ์์ธก
ย
- input : ์์ธก์ ์ด์ฉํ 2n๊ฐ์ ์ฃผ๋ณ๋จ์ด 1-of-V ๋ฒกํฐ
- output label : ์์ธกํ๊ณ ์ ํ๋ ์ค๊ฐ๋จ์ด์ 1-of-V ๋ฒกํฐ
- training complexity Q = N x D + D x log(V)
N : ์ด์ ๋จ์ด์ ๊ฐ์
D : vector์ ์ฐจ์
V : Vocabulary ๋ด ์ ์ฒด ๋จ์ด ์
Skip-gram
: ์ค๊ฐ์ ๋จ์ด๋ก ์ฃผ๋ณ์ ๋จ์ด๋ค์ ์์ธก
- input : ์์ธก์ ์ด์ฉํ ์ค๊ฐ๋จ์ด์ 1-of-V ๋ฒกํฐ
- output label : ์์ธกํ๊ณ ์ ํ๋ 2n๊ฐ์ ์ฃผ๋ณ๋จ์ด 1-of-V ๋ฒกํฐ
- training complexity Q = C x (D + D x log(V))
C : ๋จ์ด์ ์ต๋ ๊ฑฐ๋ฆฌ
D : vector์ ์ฐจ์
V : Vocabulary ๋ด ์ ์ฒด ๋จ์ด ์
ย
CBOW ๋ชจ๋ธ ๊ตฌํ
์๋ ๊ธ๊ณผ ์ฝ๋๋ Python ์ธ์ด์ PyTorch๋ฅผ ์ฌ์ฉํ์ฌย CBOW(Continuous Bag-Of-Word)ย ๋ชจ๋ธ์ ๊ตฌํํ๋ ๊ณผ์ ์
๋๋ค. ์ฐพ๊ณ ์ ํ๋ ๋จ์ด ์์น์ ์ฃผ๋ณ์ ๋จ์ด๋ค์ ๋ณด๊ณ ์ด๋ค ๋จ์ด๊ฐ ๊ฐ์ฅ ์ ํฉํ ์ง๋ฅผ ์์ธกํ๋ ๊ฒ, ์ฆ ์ฌ๋ฌ ๊ฐ์ Input Layer๋ฅผ ๋ฐ์๋ค์ฌ Hidden Layer๋ฅผ ๊ฑฐ์ณ ํ๋์ Output Layer๋ฅผ ์ถ๋ ฅํ๋ ๊ฒ์ด CBOW ๋ชจ๋ธ์ ๊ตฌ์กฐ์
๋๋ค. ์ฃผ๋ณ ๋จ์ด๋ค์ด ์ฃผ์ด์ก์ ๋ ์ค์ฌ ๋จ์ด๊ฐ ๋ฑ์ฅํ ์กฐ๊ฑด๋ถ ํ๋ฅ ์ ์ต๋ํํ๋ ๋ฐฉํฅ์ผ๋ก ํ์ต์ ์งํํ๋ฉฐ ๊ฐ ๋ ์ด์ด ์ฌ์ด์ ๊ฐ์ค์น๋ฅผ ์กฐ์ ํฉ๋๋ค.
CBOW ์ฝ๋ ๊ตฌํ
ํ์ต์ ์ํ Corpus ์ ์ฒ๋ฆฌ
๊ธฐ์กด์ ์ฝ๋์ ํฌํจ๋์ด์๋ ์งง์ ๋ฌธ์ฅ ๋์ , ted ๊ฐ์ฐ์ ๋ฌธ์ฅ๋ค์ ํฌํจํ๋ ์์ด Corpus๋ฅผ ๊ฐ์ ธ์ ํ์ต์ ์งํํด๋ณด์์ต๋๋ค. ํด๋น Corpus์ ๋ํด ์ ์ฒ๋ฆฌ๋ฅผ ์งํํ์์ ๋ token 4,475,758๊ฐ๋ฅผ ๋ฐ์์ฌ ์ ์์๊ณ , ์ปดํจํฐ์ ์๊ฐ๊ณผ ์ฑ๋ฅ์ ๊ณ ๋ คํ์ฌ ์ผ๋ถ ๋จ์ด๋ง์ ์ด์ฉํด ํ์ต์ ์งํํ์์ต๋๋ค.
import nltk nltk.download('punkt') import re import urllib.request import zipfile from lxml import etree from nltk.tokenize import word_tokenize, sent_tokenize urllib.request.urlretrieve("https://raw.githubusercontent.com/ukairia777/tensorflow-nlp-tutorial/main/09.%20Word%20Embedding/dataset/ted_en-20160408.xml", filename="ted_en-20160408.xml") targetXML = open('ted_en-20160408.xml', 'r', encoding='UTF8') target_text = etree.parse(targetXML) parse_text = '\n'.join(target_text.xpath('//content/text()')) context_text = re.sub(r'\([^)]*\)', '', parse_text) sent_text = sent_tokenize(context_text) result = list() normalized_text = [] for string in sent_text: tokens = re.sub(r"[^a-z0-9]+", " ", string.lower()) normalized_text.append(tokens) for sentence in normalized_text: tokenized_text = word_tokenize(sentence) for tokenized_word in tokenized_text: result.append(tokenized_word) # result์ tokenized words๊ฐ ๋ด๊ฒจ์์
CBOW ๋ชจ๋ธ ๊ตฌํ์ ์ํด torch ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ฉํ์์ต๋๋ค.
import torch from torch import nn from torch.autograd import Variable from torch.optim import SGD import torch.nn.functional as F
CBOW Class
CONTEXT_SIZE = 4 # ์ค์ฌ ๋จ์ด ์ ์์ผ๋ก 4๊ฐ์ฉ, ์ด 8๊ฐ์ ๋จ์ด๋ฅผ input์ผ๋ก ๋ฐ๋๋ค EMBEDDING_DIM = 300 # ๋จ์ด ๋ฒกํฐ๋ฅผ 300 dimension์ vector๋ก ๊ตฌ์ฑํ๋ค EPOCH = 20 # ๋จ์ด set์ ๋ํ ๋ฐ๋ณต ํ์ต ํ์ class CBOW(nn.Module): def __init__(self, vocab_size, embedding_size, context_size): super(CBOW, self).__init__() #๊ฐ์ค์น ์ด๊ธฐํ self.vocab_size = vocab_size self.embedding_size = embedding_size self.context_size = context_size self.embeddings = nn.Embedding(self.vocab_size, self.embedding_size) # ๊ณ์ธต ์์ฑ # input layer -> proj layer(lin1) self.lin1 = nn.Linear(self.context_size * 2 * self.embedding_size, 512) # proj layer -> output layer(lin2) self.lin2 = nn.Linear(512, self.vocab_size) def forward(self, inp): out = self.embeddings(inp).view(1, -1) out = self.lin1(out) # proj layer์ ํ์ฑํ ํจ์๋ก reLU๋ฅผ ์ฌ์ฉ out = F.relu(out) out = self.lin2(out) # output layer์ ํ์ฑํ ํจ์๋ก log_softmax๋ฅผ ์ฌ์ฉ out = F.log_softmax(out, dim=1) return out def get_word_vector(self, word_idx): word = Variable(torch.LongTensor([word_idx])) return self.embeddings(word).view(1, -1)
- __init__ : CBOW ์ ์ธ ๋ฐ ์ด๊ธฐํ
vocab_size
: ์ดํ ์embedding_size
: ๋จ์ด ๋ฒกํฐ์ ์ฐจ์ ์context_size
: input layer๋ก ๋ฐ์๋ค์ผ ๋จ์ด์ ๊ฐ์ (ํ์ฌ ์์ฑํ ์ฝ๋์์๋ ์ค์ฌ ๋จ์ด ๊ธฐ์ค ์ ์์ผ๋ก 2 x context_size ๊ฐ์ ๋จ์ด๋ฅผ ์ฌ์ฉํฉ๋๋ค)
- forward : ํ์ต ๋ฐฉ๋ฒ ์ ์
inp
: ์ฃผ๋ณ ๋จ์ด ๋ฆฌ์คํธ (์ค์ฌ ๋จ์ด ์ฃผ๋ณ ๋จ์ด์ word vector list๋ฅผ ๊ฐ์ ธ์ต๋๋ค)
- get_word_vector : ๋จ์ด์ ๋ฒกํฐ ๋ฐํ
word_idx
: ์ฐพ๊ณ ์ ํ๋ ๋จ์ด์ ์ธ๋ฑ์ค
ย
ํ์ต
CORPUS_SIZE = 10000 # Corpus size ์กฐ์ ์ผ๋ก ํ์ต ๋ฐ์ดํฐ ์ฌ์ด์ฆ ๊ฒฐ์ def main(): corpus_text = result[0:CORPUS_SIZE] # Corpus Data ๊ฐ๊ณต data = list() for i in range(CONTEXT_SIZE, CORPUS_SIZE - CONTEXT_SIZE): data_context = list() for j in range(CONTEXT_SIZE): data_context.append(corpus_text[i - CONTEXT_SIZE + j]) for j in range(1, CONTEXT_SIZE + 1): data_context.append(corpus_text[i + j]) data_target = corpus_text[i] data.append((data_context, data_target)) global unique_vocab unique_vocab = list(set(corpus_text)) # mapping to index global word_to_idx word_to_idx = {w: i for i, w in enumerate(unique_vocab)} # CBOW ๋ชจ๋ธ ํ์ต (์ ์๋ ์๋์) global cbow cbow = train_cbow(data, unique_vocab, word_to_idx) if __name__ == "__main__": main()
CORPUS_SIZE
๋ ํ์ต์ํค๊ณ ์ ํ๋ ๋ง๋ญ์น์ ํฌ๊ธฐ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค. ์๊ฐ๊ณผ ์ปดํจํฐ์ ์ฑ๋ฅ ๋ฑ์ ๊ณ ๋ คํ์ฌ ๋ชจ๋ธ ํ์ต ๋ฐ ํ
์คํธ๋ฅผ ์งํํ ์ ์๋๋ก ์ฝ์
ํ์์ต๋๋ค.ted ๊ฐ์ฐ์ ๋ฐ์ดํฐ์์ ํ ํฐํ ์ฒ๋ฆฌํ ๋ฐ์ดํฐ์ธ
result
๋ฅผ ๊ฐ๊ณตํ์ฌ, ํ์ต์ ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ง๋ค์ด์ค๋๋ค. ์ค์ฌ ๋จ์ด(data_target
)๋ฅผ ๊ธฐ์ค์ผ๋ก ์ผ์ชฝ 4๋จ์ด, ์ค๋ฅธ์ชฝ 4๋จ์ด๋ฅผ data_context
์ ์ฝ์
ํ๊ณ , ๋ ๊ฐ๋ค์ ํํ๋ก์จ data
๋ฆฌ์คํธ์ ์ถ๊ฐํฉ๋๋ค.[์์] ์ฃผ์ด์ง ๋จ์ด ๋์ด : here are two reasons "companies" fail they only do ์ค์ฌ ๋จ์ด : companies ์ฃผ๋ณ ๋จ์ด : here are two reasons fail they only do -> (['here','are','two','reasons','fail','they','only','do'],'companies') ([์ฃผ๋ณ 8๊ฐ ๋จ์ด] + ์ค์ฌ ๋จ์ด) ํ ๋ฌถ์์ผ๋ก data์ append ๋๋ค.
์ด๋ ๊ฒ ์์ฑ๋
data
๋ฆฌ์คํธ์ ์์๋ ๊ฐ๊ฐ 8๊ฐ์ input word + ๋ชฉํ word 1๊ฐ๋ก ๊ตฌ์ฑ๋ ํํ์ด๋ฉฐ, ํ์ต๊ณผ์ ์์ 8๊ฐ์ ๋จ์ด์ ๋ชฉํ ๋จ์ด ๊ฐ์ ๊ด๊ณ(๊ฐ์ค์น)๋ฅผ ์ฐพ๋๋ฐ์ ์ฌ์ฉ๋ฉ๋๋ค.ย
unique_vocab
์ corpus์ ๋ฑ์ฅํ ๋จ์ด๋ฅผ ์ค๋ณต๋์ง ์๊ฒ ๋ชจ์๋ ๋จ์ด์ list ์
๋๋ค. word_to_idx
๋ unique_vocab
์ ๋จ์ด๋ฅผ key๋ก ์ฌ์ฉํ๊ณ , index ๋ฒํธ๋ฅผ value๋ก ์ฌ์ฉํ๋ dictionary ์
๋๋ค. data
๋ฆฌ์คํธ์ ๋จ์ด๋ฅผ dictionary์์ ์ฐพ์ index ๋ฒํธ๋ฅผ ๋ฐ๊ณ , ์ด๋ฅผ ์ด์ฉํด ย
train_cbow - ํ์ต ๊ณผ์
CBOW ๋ชจ๋ธ์ ํ์ต ๊ณผ์ ์ ๋ํ ์ ์๋ ์๋์ ๊ฐ์ต๋๋ค.
def train_cbow(data, unique_vocab, word_to_idx): # CBOW ๋ชจ๋ธ ์ ์ธ cbow = CBOW(len(unique_vocab), EMBEDDING_DIM, CONTEXT_SIZE) # Loss function, Optimizer nll_loss = nn.NLLLoss() optimizer = SGD(cbow.parameters(), lr=0.01) # EPOCH : ํ์ฌ ๋ฐ์ดํฐ์ ์ ๋ํ ํ์ต ํ์ for epoch in range(EPOCH): for context, target in data: inp_var = Variable(torch.LongTensor([word_to_idx[word] for word in context])) target_var = Variable(torch.LongTensor([word_to_idx[target]])) cbow.zero_grad() log_prob = cbow(inp_var) loss = nll_loss(log_prob, target_var) loss.backward() optimizer.step() return cbow
์ฐ์ , CBOW ๋ชจ๋ธ๊ณผ ์์คํจ์, ์ต์ ํ๋ฐฉ์์ ์๋์ ๊ฐ์ต๋๋ค.
- loss function - Negative Log Likelihood Loss. NLL Loss์์๋ ๋ชจ๋ธ์ด ์์ธกํ ํ๋ฅ ๊ฐ์ ์ง์ ๋ฐ์ํ์ฌ ์์ค์ ํ๊ฐํฉ๋๋ค. ํ๋ฅ ๊ฐ์ ์์ ๋ก๊ทธ ํจ์๋ก ๋ณํ์์ผ ์ด์ฉํ๋ฉด, ์ ๋ต์ ๊ฐ๊น์ธ ํ๋ฅ ์ด ๋ฎ์์๋ก ๋ ๋ง์ ํจ๋ํฐ๋ฅผ ๋ถ์ฌํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ๋ชจ๋ธ์ ๋ํ ๋ ์ ๊ตํ ํ๊ฐ๊ฐ ๊ฐ๋ฅํฉ๋๋ค. (์ด์ฌํ ๊ณต๋ถํ์ฌ ์ ๋ต์ ๋ง์ถ ํ๋ฅ ์ด 99%์ธ ํ์๊ณผ ์ฐ์ด์ ๋ง์ถ ํ๋ฅ ์ด 20%์ธ ํ์์ด ์๋ค๊ณ ํ๋ฉด, ๋ ๋ค ๋์ผํ ์ ๋ต์ ๋ด๋ฆฌ๋๋ผ๋, ๋ง์ถ ํ๋ฅ ์ ๊ธฐ์ค์ผ๋ก ํ๊ฐ๋ฅผ ์งํํ์ฌ ํ์ ๊ฐ์ ์ ๊ตํ ํ๊ฐ๊ฐ ๊ฐ๋ฅํฉ๋๋ค. )
- Optimizer - Stochastic Gradient Descent ์ต์ ํ๋ฅผ ์ํด ๊ณ์ฐํ๋ ๋ฐ์ดํฐ ๋จ์์ธ batch์ ํฌ๊ธฐ๋ฅผ 1๋ก ๊ณ์ฐํ๋ ๊ฒฝ์ฌํ๊ฐ๋ฒ์ผ๋ก, ์ฐ์ฐํ ๋ฐ์ดํฐ์ ์ ๊ท๋ชจ๊ฐ ํฐ ๊ฒฝ์ฐ์ ๋น๊ต์ ๋น ๋ฅด๊ฒ ์ต์ ๊ฐ์ ์ฐพ๊ธฐ์ํด ์ฌ์ฉํ๋ ์ต์ ํ ๋ฐฉ์์ ๋๋ค. Gradient Descent ๋ฑ์ ๋ค๋ฅธ optimizer ๋ณด๋ค ๋ ธ์ด์ฆ๊ฐ ํฌ๊ฒ ๋ฐ์ํ์ง๋ง, ๊ณ์ฐ๋์ ์ค์ฌ ๋น ๋ฅด๊ฒ ์ต์ ํ๋ ๊ธฐ์ธ๊ธฐ๋ฅผ ์ฐพ์ ์ ์๋ค๋ ์ฅ์ ์ด ์์ต๋๋ค.
์๋ ๋์ด๋ ์ผ๋ จ์ ์์๋ก CBOW ๋ชจ๋ธ์ด ํ์ต์ ์ค์ํฉ๋๋ค.
inp_var = Variable(torch.LongTensor([word_to_idx[word] for word in context])) target_var = Variable(torch.LongTensor([word_to_idx[target]])) cbow.zero_grad() log_prob = cbow(inp_var) loss = nll_loss(log_prob, target_var) loss.backward() optimizer.step()
data
๋ฆฌ์คํธ์์ ํํ(8๊ฐ์ ์ฃผ๋ณ ๋จ์ด์ 1๊ฐ์ ๋ชฉํ ๋จ์ด๋ก ๊ตฌ์ฑ)์ ๊ฐ์ ธ์inp_var
,target_var
์ ์ด๊ธฐํ
- ํ์ฌ ๋ชจ๋ธ์ ๋ณํ๋๋ฅผ 0์ผ๋ก ์ด๊ธฐํ
- ๋ชจ๋ธ์ input layer๋ก 8๊ฐ์ ์ฃผ๋ณ ๋จ์ด๋ฅผ ์ ๋ฌ
- ๋ชจ๋ธ์ด ๋ชฉํ ๋จ์ด๋ฅผ ๋ง์ถ ํ๋ฅ ์ ๊ณ์ฐํ๊ณ , ์์คํจ์๊ฐ ํ๊ฐ๋ฅผ ๋ด๋ฆผ
- ์ญ์ ํ๋ฅผ ์ํ (Autograd๊ฐ attribution์ ๋ณํ๋๋ฅผ ๊ณ์ฐํ๊ณ ์ ์ฅํจ)
- ์ ์ฅ๋ ๋ณํ๋์ ๋ฐ๋ผ Optimizer๊ฐ ๋งค๊ฐ๋ณ์๋ฅผ ์กฐ์ ํจ
data
๋ฆฌ์คํธ์ ๋ชจ๋ ํํ์ ๋ํด 1~6์ ๋ฐ๋ณต
EPOCH
์ ํฌ๊ธฐ๋งํผ 1~7์ ๋ฐ๋ณต
ย
์ฃผ์ด์ง EPOCH ๋งํผ ํ์ต์ ๋ฐ๋ณตํ๋ ๋์, ๊ฐ EPOCH ๋จ๊ณ์ ๋ํ ์์คํจ์์ ํ๊ท ๊ฐ์ ๊ณ์ฐํด๋ณธ ๊ฒฐ๊ณผ, ํ์ต์ ํตํด ๋จ์ด๋ฒกํฐ๋ค์ด ์ ์ ํ ์์น์ ๋ฐฐ์น๋๋ฉด์, ํ์ต์ด ์งํ๋ ์๋ก ํ๊ท ์์ค์ด ์ค์ด๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
์ค๋ฅธ์ชฝ ์ฌ์ง์ CBOW ๋ชจ๋ธ์ ํ์ต ํ์์ ํ๊ท ์์ค๋ฅ ์ ์ถ๋ ฅํ ๊ฒ์
๋๋ค.
ํ์ต ๊ฒฐ๊ณผ
ํ์ต์ด ์๋ฃ๋๋ฉด, ์๋ ์์์ ๊ฐ์ด corpus์ ์ํ ๋จ์ด๋ค์ ๊ฐ์ค์น๋ฅผ ๊ฐ๊ฒ๋๊ณ , ์ด๊ฒ์ด ํน์ ํ ๋จ์ด์ ์๋ฏธ๋ฅผ ๋ํ๋ด๊ฒ ๋ฉ๋๋ค.
dimension์ 300์ผ๋ก ์ฃผ์์ผ๋ฏ๋ก, ๊ฐ๊ฐ์ ๋จ์ด ๋ฒกํฐ๋ 300๊ฐ์ ๊ฐ์ค์น์ ์ํด ๊ทธ ์๋ฏธ๊ฐ ๊ฒฐ์ ๋ฉ๋๋ค. between [-0.4627, 0.5517, 0.9427, -1.2970, 0.4817, -0.5149, -2.0008, -1.6774, -0.1271, -0.1935, -0.7941, 0.6387, 0.7139, 1.1319, 1.1475, 0.9229, ... ์ค๋ต (300๊ฐ์ ๊ฐ์ค์น) ... 0.1773, -0.2089, 1.7897, -1.3952, 0.8338, -0.9995, 0.5707, 0.3273, 1.4372, 0.7663, 0.2333, 0.1943]
๋จ์ด ๊ฐ ์ ์ฌ๋ ์ฐ์ฐ
ํ์ต ๊ฒฐ๊ณผ ํ
์คํธ๋ฅผ ์ํด ๋ ๊ฐ์ง ๊ธฐ๋ฅ์ ์ ์ํ์์ต๋๋ค.
(1) get_similarity : ์
๋ ฅํ ๋ ๋จ์ด๊ฐ์ ์ ์ฌ๋ ์ถ๋ ฅ
(2) get_most_similar_word : ํ์ฌ corpus์์ ์
๋ ฅํ ๋จ์ด์ ๊ฐ์ฅ ์ ์ฌํ ๋จ์ด ์ถ๋ ฅ
ํด๋น ๊ธฐ๋ฅ ๊ตฌํ ์์ค์ฝ๋
def similarity_between_words(word_1_vec, word_2_vec): # ๋ ๋ฒกํฐ๊ฐ์ ์ ์ฌ๋๋ฅผ ๊ณ์ฐํ๊ธฐ ์ํด, ์ฝ์ฌ์ธ์ ์ด์ฉํจ # ๋ ๋ฒกํฐ์ ์ฌ์ด๊ฐ์ ์์์๋ก (์ ์ฌํ ์๋ก) cosine ๊ฐ์ด 1์ ๊ฐ๊น์์ง์ ์ด์ฉ result = (torch.dot(word_1_vec, word_2_vec) / (torch.norm(word_1_vec) * torch.norm(word_2_vec))) # ์์ ๊ฐ ๋ฐํ์ ์ํด ๊ฐ ๋ณด์ if(result < 0): result *= -1 return result def get_similarity(cbow, word1, word2, unique_vocab, word_to_idx): if not((word1 in unique_vocab) and (word2 in unique_vocab)): print("word is not in the vocabulary") return # (1) ๋ ๋จ์ด word1, word2 ์ฌ์ด์ ์ ์ฌ๋๋ฅผ ํ์ธ word_1 = unique_vocab[unique_vocab.index(word1)] word_2 = unique_vocab[unique_vocab.index(word2)] word_1_vec = cbow.get_word_vector(word_to_idx[word_1]) word_2_vec = cbow.get_word_vector(word_to_idx[word_2]) word_1_vec = torch.flatten(word_1_vec) word_2_vec = torch.flatten(word_2_vec) word_similarity = similarity_between_words(word_1_vec, word_2_vec) if(word_similarity < 0): word_similarity *= -1 print("Similarity between '{}' & '{}' : {:0.4f}".format(word_1, word_2, word_similarity)) def get_most_similar_word(cbow, word, unique_vocab, word_to_idx): word_1 = unique_vocab[unique_vocab.index(word)] word_1_vec = cbow.get_word_vector(word_to_idx[word_1]) word_1_vec = torch.flatten(word_1_vec) most_similar_word = 0 most_similarity = 0.0 print(len(unique_vocab)) for i in range(0, len(unique_vocab)): if(i == unique_vocab.index(word1)): continue word_3_vec = torch.flatten(cbow.get_word_vector(word_to_idx[unique_vocab[i]])) word_similarity = similarity_between_words(word_1_vec, word_3_vec) # print(unique_vocab[i], '{:.4f}'.format(word_similarity)) if(most_similarity < word_similarity): most_similar_word = i most_similarity = word_similarity print("most similar word between '{}' is '{}' with {:.4f} of similarity".format(word_1, unique_vocab[most_similar_word], most_similarity))
ย
๋ ๋จ์ด ๋ฒกํฐ๊ฐ์ ์ ์ฌ๋๋ฅผ ๊ณ์ฐํ์ฌ ์ถ๋ ฅํ๊ณ , ๋จ์ด์ ๊ฐ์ฅ ์ ์ฌํ ๋จ์ด๋ฅผ ์ถ๋ ฅํ๋ ๊ธฐ๋ฅ์ด ์ ๋๋ก ์๋ํจ์ ํ์ธํ ์ ์์ต๋๋ค.
ย
Corpus์ ์ฌ์ด์ฆ๋ฅผ ๋ ํฌ๊ฒ ํค์ ํ์ตํ์์ ๋, ๋จ์ด๊ฐ์ ์๋ฏธ ๊ด๊ณ๊ฐ ๋์ฑ ์ ์ ํด์ง๋๋ค. ์ ๋ชจ๋ธ๋ณด๋ค 10๋ฐฐ ๋ ๋ง์ ๋จ์ด๋ฅผ ์ด์ฉํด ๋ชจ๋ธ์ ํ์ตํ ๊ฒฝ์ฐ, ์ ์ฌํ๋ค๊ณ ํ๋จ๋ ๋จ์ด๊ฐ ๋์ฑ ์ ์๋ฏธํ๋ค๊ณ ํ๋จ๋ฉ๋๋ค.
ย
๋ ์ข์ ์ฑ๋ฅ์ ํ์ต๋จธ์ ๊ณผ, ๋ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ์ด์ฉํด ๋ชจ๋ธ์ ํ์ต์ํจ๋ค๋ฉด ๋์ฑ ์ ์๋ฏธํ ๋จ์ด๊ฐ์ ๊ด๊ณ๋ฅผ ๋ฝ์๋ผ ์ ์์ ๊ฒ์ด๋ผ ์๊ฐ๋ฉ๋๋ค.
ย
Skip-gram ๋ชจ๋ธ ๊ตฌํ
Skip-gram ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํํ๋ ๊ณผ์ ์
๋๋ค.ย kaggle์ text8.txt ๋ฐ์ดํฐ์ ์ผ๋ถ(1000๊ฐ์ ๋จ์ด)๋ก ํ์ตํ์ต๋๋ค. ์ค์ฌ๋จ์ด๋ฅผ ์
๋ ฅํ์ ๋, ๊ทธ ์ฃผ๋ณ๋จ์ด๊ฐ ๋์ถ๋ ํ๋ฅ ์ ๋์ด๋๋ก ํ์ตํด์ผํฉ๋๋ค.
ย
Skip-gram์ ํ๋์ input layers๊ฐ ์๊ณ hidden layer๋ฅผ ๊ฑฐ์ณ ์ฃผ๋ณ๋จ์ด ๊ฐ์๋งํผ output layer๋ก ์ถ๋ ฅํ๋ ๊ตฌ์กฐ์
๋๋ค. ๋จ์ด์ถํ ํจํด์ ํ์ตํด ๋จ์ด์ ๋ถ์ฐํํ์ ๋์ถํฉ๋๋ค. ๋ค์ค ํด๋์ค ๋ถ๋ฅ์ด๊ธฐ ๋๋ฌธ์ ์ํํธ๋งฅ์ค์ ๊ต์ฐจ ์ํธ๋กํผ ์ค์ฐจ๋ง ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค. ์ํํธ๋งฅ์ค ํจ์๋ฅผ ์ด์ฉํด ์ ์๋ฅผ ํ๋ฅ ๋ก ๋ณํํ๊ณ , ๊ทธ ํ๋ฅ ๊ณผ ์ ๋ต ๋ ์ด๋ธ๋ก๋ถํฐ ๊ต์ฐจ ์ํธ๋กํผ ์ค์ฐจ๋ก ๊ตฌํ ์์ค์ ์ฌ์ฉํด ํ์ตํฉ๋๋ค.
ย
Skip-gram Class
class SimpleSkipGram: def __init__(self, vocab_size, hidden_size): V, H = vocab_size, hidden_size # ๊ฐ์ค์น ์ด๊ธฐํ W_in = 0.01 * np.random.randn(V, H).astype('f') W_out = 0.01 * np.random.randn(H, V).astype('f') # ๊ณ์ธต ์์ฑ self.in_layer = MatMul(W_in) # ์ ๋ ฅ์ธต self.out_layer = MatMul(W_out) # ์ถ๋ ฅ์ธต self.loss_layer1 = SoftmaxWithLoss() # Softmax ๊ณ์ธต self.loss_layer2 = SoftmaxWithLoss() # Softmax ๊ณ์ธต # ๋ชจ๋ ๊ฐ์ค์น์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๋ฆฌ์คํธ์ ๋ชจ์๋ค. layers = [self.in_layer, self.out_layer] self.params, self.grads = [], [] for layer in layers: self.params += layer.params self.grads += layer.grads # ์ธ์คํด์ค ๋ณ์์ ๋จ์ด์ ๋ถ์ฐ ํํ์ ์ ์ฅํ๋ค. self.word_vecs = W_in
- SimpleSkipGram ํด๋์ค์ ์ธ์
vocab_size
: ์ดํ ์hidden_size
: hidden layer์ ๋ด๋ฐ ์
- W_in , W_out ๋๊ฐ์ ๊ฐ์ค์น
- ๊ฐ๊ฐ ์์ ๋ฌด์์ ๊ฐ์ผ๋ก ์ด๊ธฐํ ๋ฉ๋๋ค.
- ๊ณ์ธต ์์ฑ
- ์ ๋ ฅ์ธต์ Matmul ๊ณ์ธต 1๊ฐ, ์ถ๋ ฅ์ธต์ Matmul ๊ณ์ธต 1๊ฐ
- Softmax with Loss ๊ณ์ธต ์ฃผ๋ณ๋จ์ด ์(=์๋์ฐ ํฌ๊ธฐ) ๋งํผ (์ฌ๊ธฐ์๋ 2๊ฐ) ๊ณ์ธต์ ์์ฑํฉ๋๋ค. ( Softmax์ Cross entropy error๋ฅผ Softmax with loss๋ก ํฉ์นจ )
word_vec
์ ๋ถ์ฐํํ ์ ์ฅ
ย
forward
def forward(self, contexts, target): h = self.in_layer.forward(target) s = self.out_layer.forward(h) l1 = self.loss_layer1.forward(s, contexts[:, 0]) l2 = self.loss_layer2.forward(s, contexts[:, 1]) loss = l1 + l2 return loss
ย
backward
def backward(self, dout=1): dl1 = self.loss_layer1.backward(dout) dl2 = self.loss_layer2.backward(dout) ds = dl1 + dl2 dh = self.out_layer.backward(ds) self.in_layer.backward(dh) return None
ย
ํ์ต
## ํ์ต๋ฐ์ดํฐ ์ค๋น๊ณผ์ window_size = 1 hidden_size = 5 # ์๋์ธต์ ๋ด๋ฐ์ batch_size = 3 max_epoch = 1000 text = x # ๋ฐ์ดํฐ corpus, word_to_id, id_to_word = preprocess(text) # corpus๋ฅผ ๋จ์ด id๋ก ๋ฐํ vocab_size = len(word_to_id) # ์ดํ ์ contexts, target = create_contexts_target(corpus, window_size) # ์ค์ฌ, ์ฃผ๋ณ๋จ์ด ๋ฐํ # one-hot encoding target = convert_one_hot(target, vocab_size) contexts = convert_one_hot(contexts, vocab_size)
## ๋ชจ๋ธํ์ต model_2 = SimpleSkipGram(vocab_size, hidden_size) optimizer = Adam() trainer_2 = Trainer(model_2, optimizer) trainer_2.fit(contexts, target, max_epoch, batch_size)
preprocess()
: corpus๋ฅผ ๋จ์ด id๋ก ๋ฐํ
create_contexts_target()
: ์ค์ฌ ๋จ์ด, ์ฃผ๋ณ ๋จ์ด๋ฅผ ๋ง๋ค๊ธฐtarget
์ ์ค์ฌ๋จ์ด ๋ฆฌ์คํธ,contexts
๋ target์ ๊ธฐ์ค์ผ๋ก window size ๋งํผ ์ ์ ์ฃผ๋ณ๋จ์ด ๋ฆฌ์คํธ
- ๊ฐ๊ฐ์ one-hot encoding์ ํด ํ์ต๋ฐ์ดํฐ๋ฅผ ์ค๋น
์ฌ๊ธฐ์ ๋งค๊ฐ๋ณ์ ๊ฐฑ์ ๋ฐฉ๋ฒ์ SGD, AdaGrad ๋ฑ ์ค Adam์ ์ฌ์ฉํ์ต๋๋ค.
ย
ย
๊ฐ๋ก์ถ์ ํ์ต ํ์, ์ธ๋ก์ถ์ ์์ค์ธ ๊ทธ๋ํ์
๋๋ค. ํ์ต๊ฒฝ๊ณผ๋ฅผ ๊ทธ๋ํ๋ก ๋ํ๋ด๋ฉด ํ์ต์ ํ ์๋ก ์์ค์ด ๊ฐ์ํ๊ณ ์๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
ย
ํ์ต ๊ฒฐ๊ณผ
๋จ์ด์ ๋ถ์ฐ ํํ
๊ฐ ๋จ์ด์ ๋ถ์ฐ ํํ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. Skip-gram์ ์ฌ์ฉํ์ฌ ์ด๋ ๊ฒ ๋จ์ด๋ฅผ ๋ฒกํฐํ์์ผ, ๋ถ์ฐํํ์ผ๋ก ๋จ์ด์ ์๋ฏธ๋ฅผ ๋ํ๋ผ ์ ์์ต๋๋ค.
# (์ค๋ต) ghosts [ -1.554753 -14.199934 5.4088864 -8.995648 -4.0544376] mind [ 10.231861 -12.334701 2.9066288 2.9563556 5.0717473] saying [ 0.6028301 -16.115307 0.48380145 -6.917041 2.6495762 ] reality [ 14.173826 -0.3625413 -10.682704 4.753849 8.219211 ] advocated [13.001251 3.5767713 -6.613554 9.323543 7.023613 ]
ย
Results
word vector์ quality๋ฅผ ์ธก์ ํ๊ธฐ ์ํ์ฌ, 5๊ฐ type์ ์๋ฏธ์ ์ธ ์ง์์ 9๊ฐ type์ ๋ฌธ๋ฒ์ ์ธ ์ง์๋ก ๊ตฌ์ฑ๋ comprehensive test๋ฅผ ์ ์ํ์์ต๋๋ค. ์ด 8869๊ฐ์ ์๋ฏธ์ ์ธ ์ง์์ 10675๊ฐ์ ๋ฌธ๋ฒ์ ์ธ ์ง์๋ก ์ด๋ฃจ์ด์ ธ์์ต๋๋ค.
๊ฐ ์นดํ
๊ณ ๋ฆฌ์ ์ง์๋ ๋ ๋จ๊ณ๋ก ์ด๋ฃจ์ด์ ธ ์๋๋ฐ,
1. ์ ์ฌ ๋จ์ด์์ ์๋์ผ๋ก ๋ง๋ญ๋๋ค.
2. ๋ ๋จ์ด์์ ์ฐ๊ฒฐํ์ฌ ์ง์ list๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด 68๊ฐ์ ๋ฏธ๊ตญ ๋๋์์ ๊ทธ ๋์์ ์ํ ์ฃผ๋ฅผ ์ฐ๊ฒฐํฉ๋๋ค. ๊ทธ ๋ค์ ๋๋ค์ผ๋ก 2๊ฐ์ ๋จ์ด์์ ์ ํํ์ฌ ์ฝ 2.5K๊ฐ์ ์ง์๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
ํด๋น ๋
ผ๋ฌธ์์ ์ ์๋ ํ
์คํธ ์
์์๋ New York ๊ณผ ๊ฐ์ multi-word๋ ์ฌ์ฉํ์ง ์์๊ณ , ๋จ์ผ ์ธ์ด set์ผ๋ก๋ง ๊ตฌ์ฑํ์์ต๋๋ค.
ย
๋ณธ ๋
ผ๋ฌธ์์๋ ๋ชจ๋ ํ์
์ ์ง์๋ฅผ ์ด์ฉํ์ฌ ์ ํ๋๋ฅผ ์ธก์ ํ์๊ณ , ์ง์๋ ๋ฒกํฐ์ ๋์์ ์ฐ์ฐ์ ๊ฒฐ๊ณผ๋ก ๋์จ closest word๊ฐ correct word์ ์ ํํ๊ฒ ์ผ์นํ ๋๋ง ์ ๋ต์ด๋ผ๊ณ ํ๊ฐํ์์ต๋๋ค. ๋์์ด๋ ์ค๋ต์ผ๋ก ์ธก์ ๋์๊ธฐ ๋๋ฌธ์, ์ ํ๋๊ฐ 100%์ ๋๋ฌํ๋ ๊ฒ์ ๊ฑฐ์ ๋ถ๊ฐ๋ฅํ๋ค๊ณ ๋ณผ ์ ์์ต๋๋ค.
ย
Maximization of Accuracy
์ฝ 60์ต๊ฐ์ ํ ํฐ์ผ๋ก ๊ตฌ์ฑ๋ Google News Corpus๋ฅผ training์ ์ฌ์ฉํ์๊ณ , vocabulary size(๋จ์ด์ ์)๋ 10๋ง๊ฐ๋ก ์ ํํ์์ต๋๋ค. ์ต์ ํ ๋ฌธ์ ์ ๋ํด ์๊ฐ์ ์ ์ฝ์ ์ง๋ฉดํ๊ฒ ๋๋๋ฐ, ์ด๋ ๋ ๋ง์ ๋ฐ์ดํฐ์ ๋ ๊ณ ์ฐจ์์ ์๋๋ฒกํฐ๋ฅผ ์ฌ์ฉํ๋ฉด ์ ํ๋์ ํฅ์์ ๊ธฐ๋ํ ์ ์๋ค๋ ๊ฒ์
๋๋ค. ๊ฐ๋ฅํ ๊ฐ์ฅ ์ข์ ๋ชจ๋ธ์ ๋น ๋ฅด๊ฒ ์ ํํ๊ธฐ ์ํด์ ๊ฐ์ฅ ๋ง์ด ์ฐ์ด๋ 3๋ง๊ฐ์ ๋ฐ์ดํฐ๋ก subset์ ๊ตฌ์ฑํ์ฌ ํ๋ จ์ ์งํํ์์ต๋๋ค.
๋จผ์ CBOW ๊ตฌ์กฐ์ ๋ํ์ฌ ์๋ก ๋ค๋ฅธ ์ฐจ์๊ณผ ํ๋ จ dataset์ word ๊ฐ์์ ๋ฐ๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ฃผ๋๋ฐ, ์ฐจ์๊ณผ training data์ ์์ ํจ๊ป ์ฆ๊ฐ์์ผ์ผ ์ ํ๋๊ฐ ํฅ์๋๋ค๊ณ ํ ์ ์์ต๋๋ค.
ย
์ค์ ์คํ์์๋ 3 epoch ๊ณผ 0.025์ learning rate๋ฅผ hyper-parameter๋ก ํ์ฌ stochastic gradient descent์ ์ญ์ ํ๋ฅผ ์ด์ฉํ์ฌ ํ๋ จํ์์ต๋๋ค.
ย
Comparison of Model Architectures
๋จผ์ , ์๋ก ๋ค๋ฅธ ๋ชจ๋ธ ๊ตฌ์กฐ๋ฅผ ๋น๊ตํ๊ธฐ ์ํด ๋์ผํ training data์ ๋ํ์ฌ word vector ์ฐจ์์ 640์ผ๋ก ๋์ผํ๊ฒ ๋ง์ถฐ ์คํํ์์ต๋๋ค. ์ถํ์ ์คํ์์๋ 3๋ง๊ฐ์ ๋จ์ด ์ ํ์ ๋์ง ์๊ณ ๋ชจ๋ semantic-syntatic word relationship test๋ฅผ ์ฌ์ฉํ์์ต๋๋ค.
RNN์ word vector๋ syntatic ์ง์์์ ๋ ์ข์ ์ฑ๋ฅ์ ๋ณด์ด๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
NNLM์ word vector๋ RNN๋ณด๋ค ํจ์ฌ ๋ ์ข์ ์ฑ๋ฅ์ ๋ณด์ด๊ณ ์๋๋ฐ, RNNLM์ word vector๋ ๋ฐ๋ก ๋น์ ํ์ hidden layer๋ก ์ฐ๊ฒฐ๋๊ธฐ ๋๋ฌธ์
๋๋ค.
CBOW์ ๊ฒฝ์ฐ syntatic ์ง์์์๋ NNLM๋ณด๋ค ์ข์ ์ฑ๋ฅ์ ๋ด๊ณ ์๊ณ , semantic ์ง์์์๋ ๋น์ทํ ๋ชจ์ต์ ๋ณด์
๋๋ค.
Skip-gram๋ syntatic ์ง์์์๋ CBOW๋ณด๋ค ๋ค์ ์ข์ง ์์ ์ฑ๋ฅ์ ๋ณด์์ง๋ง, semantic ์ง์์์๋ ์ด๋ ํ ๋ชจ๋ธ๋ณด๋ค ํจ์ฌ ๋ ์ข์ ์ฑ๋ฅ์ ๋ณด์์ต๋๋ค.
ย
๋ค์์ผ๋ก๋ ์ค์ง ํ๋์ CPU๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ธ์ ํ์ตํ์๊ณ ๊ณต์ ์ผ๋ก ์ฌ์ฉ๊ฐ๋ฅํ word vector๊ณผ ๋น๊ตํ์ฌ ํ๊ฐํ์์ต๋๋ค.
CBOW ๋ชจ๋ธ์ Google News Data์ subset์ผ๋ก ์ฝ ํ๋ฃจ๋์ trainingํ์๊ณ , Skip-gram ๋ชจ๋ธ์ ์ฝ 3์ผ๋์ training ํ์์ต๋๋ค.
ย
์ถํ์ ์คํ์์๋ 1 epoch๋ง์ ์ฌ์ฉํ์๊ณ , learning rate๋ฅผ ์ค์ฌ๊ฐ๋ฉด์ ํ๋ จ์ด ๋๋ ์์๋ learning rate๊ฐ 0์ด ๋๊ฒ ํ์์ต๋๋ค.
1 epoch์ ๋ํ์ฌ 2๋ฐฐ ๋ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ 3 epoch์ ๋ํ์ฌ ๋์ผํ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๋์ผํ๊ฑฐ๋ ๋ ๋์ ์ฑ๋ฅ์ ๋ณด์์ต๋๋ค.
ย
Large Scale Parallel Training of Models
๋ณธ ๋
ผ๋ฌธ์ ์คํ์์๋ ๋ถ์ฐ ์ฐ์ฐ ํ๋ ์์ํฌ์ธ DistBelief๋ฅผ ์ ์ฉํ์์ต๋๋ค.
Google News 60์ต๊ฐ์ ๋ฐ์ดํฐ์
์ ๋ํ์ฌ mini-batch ๋น๋๊ธฐํ gradient descent ์ Ada-grad๋ฅผ ์ด์ฉํ์ฌ ํ๋ จํ์๋๋ฐ, 50~100๊ฐ์ ๋ณต์ ๋ณธ์ ์ด์ฉํ์ฌ CPU ๊ฐ์์ ๋ฐ๋ผ training ๊ฒฐ๊ณผ๋ฅผ ์ ๋ฆฌํ ๊ฒ์
๋๋ค. (1000์ฐจ์์ ๋ฒกํฐ๋ฅผ NNLM์ผ๋ก ํ๋ จ์ํค๋ ๊ฒ์ ๋ง๋ฌด๋ฆฌํ๊ธฐ์ ๋๋ฌด ๊ธด ์๊ฐ์ด ์์๋์์ต๋๋ค.)
- Ada-grad : ์ง๊ธ๊น์ง ๋ง์ด ๋ณํํ ๊ฐ์ ์ ๊ฒ ๋ณํํ๋๋ก, ์ ๊ฒ ๋ณํํ ๊ฐ์ ๋ง์ด ๋ณํํ๋๋ก learning rate๋ฅผ ์กฐ์
- DistBelief : ๊ฐ์ ๋ชจ๋ธ์ ๋ํ์ฌ ๋ณต์ ๋ณธ์ ๋ง๋ค์ด ๋ณ๋ ฌ์ ์ผ๋ก ์คํ๋๋๋ฐ, ๊ฐ๊ฐ์ ๋ณต์ ๋ณธ์ ์ค์์ server๋ฅผ ํตํ์ฌ ๊ธฐ์ธ๊ธฐ update ๋๊ธฐํ
ย
Microsoft Research Sentence Completion Challenge
: Langauge Modeling๊ณผ ๋ค๋ฅธ NLP ๊ธฐ์ ์ ๋ํ์ฌ ์ต๊ทผ์ ์๊ฐ๋ task
1040๊ฐ์ ๋ฌธ์ฅ์ผ๋ก ๋์ด ์์ผ๋ฉฐ, ๊ฐ ๋ฌธ์ฅ์๋ ํ ๋จ์ด๊ฐ ๋น์ด์๋๋ฐ 5๊ฐ์ ์ ํ์ง ์ค ๊ฐ์ฅ ์ผ๊ด์ฑ์๋ ๋จ์ด๋ฅผ ์ ํํ๋ ๊ฒ์ด ๋ชฉํ์
๋๋ค. N-gram, LSA-based model, log-bilinear, combination of recurrent neural network์ ๊ฒฐ๊ณผ๋ 55.4%์ ์ ํ๋๋ก ์ด๋ฏธ ๋ณด๊ณ ๋์ด ์์ต๋๋ค.
๋ณธ ๋
ผ๋ฌธ์์๋ Skip-gram ๊ตฌ์กฐ์ ์ฑ๋ฅ์ ํ๊ตฌํ๊ธฐ ์ํ์ฌ 5000๋ง๊ฐ์ ๋จ์ด๋ก 640์ฐจ์์ ๋ชจ๋ธ์ ํ๋ จ์ํค๊ณ test set์ ๊ฐ ๋ฌธ์ฅ์ ๋ํ์ฌ ์ฑ๋ฅ์ ํ์ธํ ํ ๊ฐ prediction์ ํฉ์ฐํ์ฌ ์ต์ข
์ ์๋ฅผ ์ธก์ ํ์์ต๋๋ค.
Skip-gram ๋จ์ผ ๋ชจ๋ธ์ LSA ๊ธฐ๋ฐ๋ณด๋ค ์ข์ ์ฑ๋ฅ์ ๋ณด์ด์ง ๋ชปํ์ง๋ง, ์ด์ ๊น์ง ๊ฐ์ฅ ์ข์ ์ฑ๋ฅ์ ๋ณด์๋ RNNLMs์ weight๋ฅผ ๊ฒฐํฉํ์์ ๋๋ 58.9%์ ์ ํ๋๋ฅผ ๋ณด์์ต๋๋ค.
ย
Examples of the Learned Relationships
ํ๋จ์ ํ๋ ๋ค์ํ relationship์ ๋ณด์ฌ์ค๋๋ค. relationship์ ๋ word vector์ ๋บ์
์ผ๋ก ์ ์ํ์๊ณ , result๋ ๋ค๋ฅธ ๋จ์ด๊ฐ ๋ํด์ง ๊ฒฐ๊ณผ๊ฐ ๋์์์ต๋๋ค.
e.g. Paris - France + Italy = Rome
์์ง ์ฑ๋ฅ์ ๊ฐ์ ํ์์ฑ์ ๋ณด์ด์ง๋ง ํ์ฌ์ ์ฑ๋ฅ๋ ๋์์ง ์๊ณ , ๋ ๋ง์ ๋ฐ์ดํฐ์
์ ๋ํ์ฌ ๋ ๊ณ ์ฐจ์์ ๋ฒกํฐ๋ก train ๋๋ค๋ฉด ํจ์ฌ ๋ ์ข์ ์ฑ๋ฅ์ ๋ณด์ผ ๊ฒ์ด๋ผ ์์ํ๊ณ ์๊ณ , ์๋ก์ด ํ์ ์ ์ธ ์์ฉ ๋ํ ๊ฐ๋ฅํ ๊ฒ์ผ๋ก ๋ณด์
๋๋ค.
ย
Conclusion
- ์นด์ดํธ ๊ธฐ๋ฐ์ representation(LSA, HAL ๋ฑ)๊ณผ ๋ค๋ฅด๊ฒ ๋จ์ด์ ์๋ฏธ๋ฅผ ๋ณด์กดํ๊ณ , ๋ฒกํฐ์ ์ฐ์ฐ ๋ํ ๊ฐ๋ฅํจ์ ํ์ธํ ์ ์์์ต๋๋ค.
- ๋น์์ ๋ค๋ฅธ ๋ชจ๋ธ๋ค์ ๋นํด ๋ฎ์ ๊ณ์ฐ๋ณต์ก๋ ๋๋ถ์, ํจ์ฌ ๋ ํฐ ๋ฐ์ดํฐ์ ์ผ๋ก๋ถํฐ ๋งค์ฐ ์ ํํ ๊ณ ์ฐจ์ word vector๋ฅผ ๊ณ์ฐํ ์ ์์ต๋๋ค.
- Word2vec์ NNLM(Neural Network Language Model)์ ๊ณ์นํ๋ฉด์๋ ์ง๊ด์ ์ด๋ฉฐ ๊ฐ๋จํ ๋ชจ๋ธ๋ก ์ฐ์ํ ์ฑ๊ณผ๋ฅผ ๋ด ๋ค์ํ NLP task์ ๋์ค์ ์ผ๋ก ํ์ฉ๋๋ ๋ฐฉ๋ฒ๋ก ์ ๋๋ค.
ย
Word2Vec์ด ๊ฐ๋ ์์
- ์์ฐ์ด๊ฐ ๊ฐ์ง๊ณ ์๋ ๋์ผํ ์๋ฏธ์ ๋ํ ๋ค์ํ ํํ ๋ฐฉ๋ฒ(์์ฐ์ด์ Flexibility)์ ๊ธฐ๊ณ๊ฐ ์ดํดํ๊ณ ํ์ฉํ ์ ์๊ฒ ํด์ค๋๋ค.
- ๊ณ์ ์๋ก์ด ๋จ์ด๊ฐ ์๊ฒจ๋๊ณ ๊ธฐ์กด ๋จ์ด๊ฐ ์์ด์ง๋ฉด์ ๋ฐ์ ํ๋ ์์ฐ์ด์ ๋ค๋ฅด๊ฒ, ์ปดํจํฐ ์ธ์ด๋ ๊ณ ์ ๋ ๋ฌธ๋ฒ์ ๋ฐ๋ผ์ผ ํ๋ ์ ์ ์ธ ์ธ์ด์ ๋๋ค. ๊ทธ๋ฌ๋, Word2Vec ๊ธฐ๋ฒ์ ํตํด ๋ณํํ๋ ๋จ์ด์ ์๋ฏธ์ ์๋ก ๋ฑ์ฅํ๋ ํํ์ ๋ํด์๋ ์ปดํจํฐ๊ฐ ํ์ตํ๊ณ ์ดํด(evolution)ํ๋ ๊ฒ์ด ๊ฐ๋ฅํ๊ฒ ๋์์ต๋๋ค.
- ๋จ์ด๋ฅผ ๋ฒกํฐํํ๋ ๊ฒ์ ๊ทธ์น์ง ์๊ณ , Item2vec(์ถ์ฒ์์คํ ), live2vec(์ํ๋ฆฌ์นดTV Live ๋ฐฉ์ก), song2vec(Sportify ํ๋ ์ด๋ฆฌ์คํธ), lda2vec(LDA์ word2vec์ ๊ฒฐํฉ), ์ง๋ณ๊ณผ ์ ์ ์ ๊ฐ์ ์ฐ๊ด์ฑ ์ฐ๊ตฌ ๋ฑ ๋ค์ํ ๋ถ์ผ์์ ๋ณธ ๋ ผ๋ฌธ์์ ์ ์ํ ๋ฒกํฐํ ๊ธฐ๋ฒ์ ํ์ฉํ๊ณ ์์ต๋๋ค.
ย
reference
Word2Vecย ย โEfficient Estimation Of Word Representations In Vector Spaceโ
ย
๋ฐ๋ฐ๋ฅ๋ถํฐ ์์ํ๋ ๋ฅ๋ฌ๋2 (์ฌ์ดํ ๊ณ ํค)
ย