King
- Man
+ Woman
= ?
먼저 워드 임베딩(Word Embedding)의 가장 유명한 예제를 구현해보자. 어떻게 해서 300차원 워드 임베딩 모형을 갖게 되면 다음 연산이 가능하다.
library(tidyverse)
library(textdata)
glove6b <- embedding_glove6b(dimensions = 100)
king <- glove6b %>%
filter(token == "king") %>%
unlist() %>%
as.numeric()
man <- glove6b %>%
filter(token == "man") %>%
unlist() %>%
as.numeric()
woman <- glove6b %>%
filter(token == "woman") %>%
unlist() %>%
as.numeric()
what_vector <- king - man + woman
what_matrix <- as.matrix(what_vector[2:101], nrow=1)
glove_mat <- glove6b %>%
data.matrix()
glove_mat <- glove_mat[, 2:101]
result_vec <- glove_mat %*% what_matrix %>%
as.vector(.)
what_df <- tibble(token = glove6b$token, similarity = result_vec)
what_df %>%
arrange(desc(similarity)) %>%
top_n(10, wt=similarity) %>%
slice(2) %>%
pull(token)
[1] "queen"
상기 결과를 일반화할 수 있는 즉, King
- Man
+ Woman
관계를 단어를 치환해서 계산하는 함수를 작성해서 살펴보자. 관련된 다양한 관계에 대한 내용은 다음 블로그를 참조한다.
get_analogy <- function(king, man, woman) {
king <- glove6b %>% filter(token == king) %>% unlist() %>% as.numeric()
man <- glove6b %>% filter(token == man) %>% unlist() %>% as.numeric()
woman <- glove6b %>% filter(token == woman) %>% unlist() %>% as.numeric()
question_vec <- king - man + woman
question_mat <- as.matrix(question_vec[2:101], nrow=1)
glove_mat <- glove6b %>%
data.matrix() %>%
.[, 2:101]
answer_vec <- glove_mat %*% question_mat %>%
as.vector(.)
answer_df <- tibble(token = glove6b$token, similarity = answer_vec)
answer_df %>%
arrange(desc(similarity)) %>%
top_n(6, wt=similarity)
}
get_analogy("king", "man", "woman")
# A tibble: 6 x 2
token similarity
<chr> <dbl>
1 king 33.2
2 queen 29.9
3 emperor 27.3
4 daughter 26.5
5 throne 25.8
6 princess 25.4
# A tibble: 6 x 2
token similarity
<chr> <dbl>
1 small 37.7
2 large 35.3
3 big 32.0
4 a 31.5
5 an 31.1
6 - 31.0
# A tibble: 6 x 2
token similarity
<chr> <dbl>
1 daughter 28.0
2 wife 26.7
3 mother 26.5
4 married 24.8
5 father 24.4
6 son 23.6
2075.9 MB
크기를 갖는 GloVe 워드 임베딩 모델을 다운로드 받아 압축을 풀면 4095 MB 크기가 된다. embedding_glove840b()
함수를 통해 dir="data"
디렉토리에 저장한다. 1.6백만 단어가 있는 데이터프레임으로 결과가 반환된다.
glove840b <- embedding_glove840b(dir="data")
dim(glove840b)
# [1] 1669210 301
get_analogy <- function(king, man, woman) {
king <- glove840b %>% filter(token == king) %>% unlist() %>% as.numeric()
man <- glove840b %>% filter(token == man) %>% unlist() %>% as.numeric()
woman <- glove840b %>% filter(token == woman) %>% unlist() %>% as.numeric()
question_vec <- king - man + woman
question_mat <- as.matrix(question_vec[2:301], nrow=1)
glove_mat <- glove840b %>%
data.matrix() %>%
.[, 2:301]
answer_vec <- glove_mat %*% question_mat %>%
as.vector(.)
answer_df <- tibble(token = glove840b$token, similarity = answer_vec)
answer_df %>%
arrange(desc(similarity)) %>%
top_n(6, wt=similarity)
}
get_analogy("king", "man", "woman")
get_analogy("big", "bigger", "small")
get_analogy("uncle", "man", "woman")
데이터 과학자 이광춘 저작
kwangchun.lee.7@gmail.com