EMNIST
데이터셋은 EMNIST Dataset에서 다운로드 받아 설치가 가능하다.
EMNIST: An extension of mnist to handwritten letters
논문에 EMNIST
데이터셋에 대한 자세한 사항이 포함되어 있다. tabularizer
팩키지를 통해 논문의 주요 내용을 담고 있는 표를 추출하고 원본 데이터에 대한 주요 내용을 살펴보자.
library(tabulizer)
library(tidyverse)
library(here)
pdf_tab <- extract_tables("data/1702.05373v1.pdf", pages = 2,
output = "data.frame")
original_dat <- pdf_tab[[1]] %>%
janitor::clean_names()
original_df <- original_dat %>%
select(x_3:total) %>%
filter(!is.na(no_classes)) %>%
rename(dataset = x_3) %>%
mutate_at(c("training", "testing", "total"), parse_number) %>%
mutate(pcnt = training / total)
original_df %>%
DT::datatable() %>%
DT::formatRound(c("training", "testing", "total"), digits = 0) %>%
DT::formatPercentage("pcnt", digits = 1)
EMNIST
원데이터를 정제한 Matlab 형태 데이터로 바로 딥러닝 학습에 동원할 수 있는 원본 데이터를 살펴보자.
emnist_tab <- extract_tables("data/1702.05373v1.pdf", pages = 4,
output = "data.frame")
emnist_dat <- emnist_tab[[1]] %>%
janitor::clean_names()
emnist_df <- emnist_dat %>%
select(name:total) %>%
filter(!is.na(classes)) %>%
rename(training = no_training, testing = no_testing) %>%
mutate_at(c("training", "testing", "total"), parse_number) %>%
mutate(pcnt = training / total)
emnist_df %>%
DT::datatable() %>%
DT::formatRound(c("training", "testing", "total"), digits = 0) %>%
DT::formatPercentage("pcnt", digits = 1)
EMNIST
데이터셋을 가지고 “선형 분류기”와 “OPIUM 분류기” 성능을 각각 살펴본다. 즉, 신형 분류기를 개발할 때 논문에 적시된 내용이 성능의 벤치마킹 하한으로 간주하고 더 우수한 성능의 분류기를 개발한다.
eval_dat <- tribble(
~"dataset", ~"Linear Classifier", ~"OPIUM Classifier",
"Balanced", "50.93%", "78.02%",
"By Merge", "50.51%", "72.57%",
"By Class", "51.80%", "69.71%",
"Letters", "55.78%", "85.15%",
"EMNIST MNIST", "85.11%", "96.22%",
"Digits", "84.70%", "95.90%")
eval_df <- eval_dat %>%
janitor::clean_names() %>%
mutate_at(c("linear_classifier", "opium_classifier"), parse_number) %>%
mutate(linear_classifier = linear_classifier / 100,
opium_classifier = opium_classifier / 100)
eval_df %>%
DT::datatable() %>%
DT::formatPercentage(c("linear_classifier", "opium_classifier"), digits = 1)
Matlab format dataset 파일을 다운로드 받아 필기체 인식기를 개발할 경우 R.matlab
팩키지가 필요하다. 매트랩을 활용하여 작업을 하게 되면 데이터프레임이 아닌 배열(array
)이라 다소 흔하게 다루는 자료구조가 아니라서 당혹스러울 수도 있다.
훈련 데이터는 크기가 커서 10,000 시험 필기체 데이터부터 작업을 수행해 보자. 각 필기체 이미지는 \(28 \times 28\) = 784을 갖는 행렬로 구성되어 있고, labels
에 필기체 인식 정답이 담겨져 있다.
library(R.matlab)
library(magick)
mnist_df <- readMat("data/matlab/emnist-mnist.mat")
## 데이터 가져오기 ----------
mnist_train <- mnist_df$dataset[1, ,]$train
mnist_test <- mnist_df$dataset[2, ,]$test
## Feature/Label 데이터셋 ----------
test_img <- mnist_test[,,1]$images
test_img_labels <- mnist_test[,,1]$labels
dim(test_img)
[1] 10000 784
[1] 10000 1
손글씨 문자가 \(1 \times 784\) 행렬로 되어 있어 이를 시각화하기 위해서 array()
함수로 자료구조를 변화시킨다. 그리고 magick
팩키지 image_read()
함수로 불러 읽어들여 척도를 조정하고, 정답과 손글씨 원본 이미지를 시각화해 본다.
visualize_character <- function(index) {
img_arr <- array(test_img[index,], c(28, 28, 1))
img_magick <- magick::image_read(img_arr / 255) %>%
magick::image_scale("500x500") %>%
image_annotate(test_img_labels[index], location = geometry_point(10, 10), size = 137, color = "red")
return(img_magick)
}
visualize_character(10)
image_read() %>% image_join() %>% image_animate()
작업흐름을 통해서 10,000개 손글씨 이미지에서 임으로 100개를 추출하여 정답(label
)과 손글씨 이미지를 Gif 파일로 시각화한다. trelliscope
으로 시각화한 사례는 딥러닝: 캡챠(captcha) 깨기를 참조한다.
각각 처리한 이미지를 10개를 뽑아, image_join()
함수로 붙이고 나서, image_append()
하나로 쭉 이어 붙인다.
trelliscope
작은 창먼저 MATLAB
객체를 R 배열(Array) 객체로 변환시키고 이를 Magick
객체로 변환시킨 후에 PNG
파일로 저장시킨다.
save_image <- function(index) {
img_arr <- array(test_img[index,], c(28, 28, 1))
img_magick <- magick::image_read(img_arr / 255) %>%
magick::image_scale("500x500") %>%
image_annotate(test_img_labels[index], location = geometry_point(10, 10), size = 137, color = "red")
image_write(img_magick, glue::glue("data/mnist/image_{index}.png"))
}
save_random_img <- sample(1:10000, 10, replace = FALSE) # 9683 4879 6692 5490 3315 5476 3003 2444 5421 7476
map(save_random_img, save_image)
[1] "image_2444.png" "image_3003.png" "image_3315.png" "image_4879.png"
[5] "image_5421.png" "image_5476.png" "image_5490.png" "image_6692.png"
[9] "image_7476.png" "image_9683.png"
다음으로 이를 trellisocpe
으로 불러 읽어들여 시각화한다. 이를 위해서 먼저 데이터프레임을 준비한다.
library(glue)
file_names <- list.files("data/mnist/")
mnist_df <- tibble(random = c(9683L, 4879L, 6692L, 5490L, 3315L, 5476L, 3003L, 2444L, 5421L, 7476L),
label = test_img_labels[c(9683L, 4879L, 6692L, 5490L, 3315L, 5476L, 3003L, 2444L, 5421L, 7476L)],
image = glue("data/mnist/image_{random}.png"))
mnist_df
# A tibble: 10 x 3
random label image
<int> <dbl> <glue>
1 9683 5 data/mnist/image_9683.png
2 4879 5 data/mnist/image_4879.png
3 6692 6 data/mnist/image_6692.png
4 5490 2 data/mnist/image_5490.png
5 3315 0 data/mnist/image_3315.png
6 5476 9 data/mnist/image_5476.png
7 3003 8 data/mnist/image_3003.png
8 2444 4 data/mnist/image_2444.png
9 5421 7 data/mnist/image_5421.png
10 7476 8 data/mnist/image_7476.png
이제 시각화를 해보자.
library(trelliscopejs)
mnist_df <- mnist_df %>%
mutate(panel = img_panel_local(image))
trelliscope(mnist_df, name = "mnist",
nrow = 2, ncol=5,
state = list(labels = c("label")),
path="mnist")
1. Cohen G, Afshar S, Tapson J, Schaik A van. EMNIST: An extension of mnist to handwritten letters. arXiv preprint arXiv:170205373. 2017.