one-hot encoding은 텍스트를 부호화(encoding) 하기위해 많이 사용함.
one-hot encoding은 텍스트를 일명 토큰이라 부르는 중복없는 단어표(일종의 암호표)를 만들고, 인덱스를 붙인 후 부호화하고자 하는 텍스트의 위치에 해당하는 비트만 1로 만들고 나머지는 모두 0으로 채우는 것을 말함.
예를 들어 두개의 문장이 있다고 가정하자.
문장1: The cat sat on the mat.
문장2: The dog ate my homework.
이 문장을 R에서 리스트로 읽어 들인다.
samples <- c("The cat sat on the mat.", "The dog ate my homework.")
samples[[1]]
## [1] "The cat sat on the mat."
samples[[2]]
## [1] "The dog ate my homework."
이 두 문장을 부호화하는 방법은
- 토큰화(tokenization): 일종의 중복없는 단어표를 만드는 과정이다.
- 벡터화(vectorization): 텍스트의 위치에만 1을 넣고 나머지는 0을 채운다.
먼저 토큰화를 보자
아래의 코드는 중복된 단어를 제거하고 위 문장의 모든 단어의 인덱스를 만든다.
token_index <- list()
for (sample in samples) #
# Tokenizes the samples via the strsplit function. In real life, you'd also
# strip punctuation and special characters from the samples.
for (word in strsplit(sample, " ")[[1]])
if (!word %in% names(token_index))
# Assigns a unique index to each unique word. Note that you don't
# attribute index 1 to anything.
token_index[[word]] <- length(token_index) + 2
만들어진 단어의 인덱스를 보자
str(token_index)
## List of 10
## $ The : num 2
## $ cat : num 3
## $ sat : num 4
## $ on : num 5
## $ the : num 6
## $ mat. : num 7
## $ dog : num 8
## $ ate : num 9
## $ my : num 10
## $ homework.: num 11
‘The’ 단어는 index 2로 되어 있고, cat 이라는 단어는 3으로 index 되어 있다. 나머지도 마찬가지다.
총 단어가 몇 개인지 살펴보자.
length(token_index)
## [1] 10
단어의 총 개수만큼 행을 만들고, 단어의 최대 인덱스 만큼 열을 만들어 모두 0으로 채운다.
max_length <- length(token_index)
results <- array(0, dim = c(length(samples),
max_length,
max(as.integer(token_index))))
이제 단어의 위치에 해당하는 비트만 1로 채운다.
for (i in 1:length(samples)) {
sample <- samples[[i]]
words <- head(strsplit(sample, " ")[[1]], n = max_length)
for (j in 1:length(words)) {
index <- token_index[[words[[j]]]]
results[[i, j, index]] <- 1
}
}
자, 이제 어떻게 부호화가 되었는지 보자.
dim(results)
## [1] 2 10 11
2개의 문장, 10개의 행, 11개의 단어 인덱스로 이루어진 3D array 이다.
앞에서 보았듯이 첫번째 문장의 각 단어의 인덱스는 2,3,4,5,6,7 이고,
두번째 문장은 각 단어의 인덱스는 2 8 9 10 11 이다.
이 인덱스가 어떻게 벡터화가 되었는지 보자. 각 단어의 인덱스 위치에 1로 코딩되어 있는 것을 볼 수 있다.
results[1,,]
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
## [1,] 0 1 0 0 0 0 0 0 0 0 0
## [2,] 0 0 1 0 0 0 0 0 0 0 0
## [3,] 0 0 0 1 0 0 0 0 0 0 0
## [4,] 0 0 0 0 1 0 0 0 0 0 0
## [5,] 0 0 0 0 0 1 0 0 0 0 0
## [6,] 0 0 0 0 0 0 1 0 0 0 0
## [7,] 0 0 0 0 0 0 0 0 0 0 0
## [8,] 0 0 0 0 0 0 0 0 0 0 0
## [9,] 0 0 0 0 0 0 0 0 0 0 0
## [10,] 0 0 0 0 0 0 0 0 0 0 0
results[2,,]
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
## [1,] 0 1 0 0 0 0 0 0 0 0 0
## [2,] 0 0 0 0 0 0 0 1 0 0 0
## [3,] 0 0 0 0 0 0 0 0 1 0 0
## [4,] 0 0 0 0 0 0 0 0 0 1 0
## [5,] 0 0 0 0 0 0 0 0 0 0 1
## [6,] 0 0 0 0 0 0 0 0 0 0 0
## [7,] 0 0 0 0 0 0 0 0 0 0 0
## [8,] 0 0 0 0 0 0 0 0 0 0 0
## [9,] 0 0 0 0 0 0 0 0 0 0 0
## [10,] 0 0 0 0 0 0 0 0 0 0 0
아래 코드는 위에서 나온 코드를 하나로 모은 것이다.
samples <- c("The cat sat on the mat.", "The dog ate my homework.")
token_index <- list()
for (sample in samples) #
for (word in strsplit(sample, " ")[[1]])
if (!word %in% names(token_index))
token_index[[word]] <- length(token_index) + 2
max_length <- 10
results <- array(0, dim = c(length(samples),
max_length,
max(as.integer(token_index))))
for (i in 1:length(samples)) {
sample <- samples[[i]]
words <- head(strsplit(sample, " ")[[1]], n = max_length)
for (j in 1:length(words)) {
index <- token_index[[words[[j]]]]
results[[i, j, index]] <- 1
}
}