1 패션 MNIST 데이터

캐글 패션 MNIST를 다운로드 받아도 되고, RStudio Keras를 설치하게 되면 포함된 데이터를 사용해도 된다.

1.1 데이터 가져오기 1

fashion-mnist 데이터는 10개 범주로 구분된 70,000개 흑백이미지 데이터로 구성되고, 각 이미지 크기는 \(28 \times 28\) 크기를 갖고 keras 팩키지 dataset_fashion_mnist() 함수를 사용해서 데이터를 받아낼 수 있다.

keras 팩키지 사용

> library(keras)
> fashion_mnist <- dataset_fashion_mnist()
> 
> c(train_images, train_labels) %<-% fashion_mnist$train
> c(test_images, test_labels) %<-% fashion_mnist$test
> 
> class_names = c('T-shirt/top',
+                 'Trouser',
+                 'Pullover',
+                 'Dress',
+                 'Coat', 
+                 'Sandal',
+                 'Shirt',
+                 'Sneaker',
+                 'Bag',
+                 'Ankle boot')

원본 데이터 활용 2

> load_mnist <- function() {
+   load_image_file <- function(filename) {
+     ret = list()
+     f = file(filename,'rb')
+     readBin(f,'integer',n=1,size=4,endian='big')
+     ret$n = readBin(f,'integer',n=1,size=4,endian='big')
+     nrow = readBin(f,'integer',n=1,size=4,endian='big')
+     ncol = readBin(f,'integer',n=1,size=4,endian='big')
+     x = readBin(f,'integer',n=ret$n*nrow*ncol,size=1,signed=F)
+     ret$x = matrix(x, ncol=nrow*ncol, byrow=T)
+     close(f)
+     ret
+   }
+   load_label_file <- function(filename) {
+     f = file(filename,'rb')
+     readBin(f,'integer',n=1,size=4,endian='big')
+     n = readBin(f,'integer',n=1,size=4,endian='big')
+     y = readBin(f,'integer',n=n,size=1,signed=F)
+     close(f)
+     y
+   }
+   train <<- load_image_file('mnist/train-images-idx3-ubyte')
+   test <<- load_image_file('mnist/t10k-images-idx3-ubyte')
+   
+   train$y <<- load_label_file('mnist/train-labels-idx1-ubyte')
+   test$y <<- load_label_file('mnist/t10k-labels-idx1-ubyte')  
+ }
> 
> 
> show_digit <- function(arr784, col=gray(12:1/12), ...) {
+   image(matrix(arr784, nrow=28)[,28:1], col=col, ...)
+ }

2 탐색적 데이터 분석

훈련과 시험 데이터로 이미지를 나누고, 훈련데이터 수는 70,000개 중에서 60,000개, 시험데이터는 10,000개로 구성된다. table(train_labels) 함수로 10개 범주에 각 6,000개씩 훈련범주로 구성된 것이 확인된다.

2.1 이미지 하나 시각화

그중에서 이미지 하나를 뽑아내서 ggplot으로 시각화한다.

> library(tidyverse)
> 
> table(train_labels)
train_labels
   0    1    2    3    4    5    6    7    8    9 
6000 6000 6000 6000 6000 6000 6000 6000 6000 6000 
> image_1 <- as.data.frame(train_images[1, , ])
> colnames(image_1) <- seq_len(ncol(image_1))
> image_1$y <- seq_len(nrow(image_1))
> image_1 <- gather(image_1, "x", "value", -y)
> image_1$x <- as.integer(image_1$x)
> 
> ggplot(image_1, aes(x = x, y = y, fill = value)) +
+   geom_tile() +
+   scale_fill_gradient(low = "white", high = "black", na.value = NA) +
+   scale_y_reverse() +
+   theme_minimal() +
+   theme(panel.grid = element_blank())   +
+   theme(aspect.ratio = 1) +
+   xlab("") +
+   ylab("")

2.2 이미지 다수 시각화

그중에서 이미지 다수 뽑아내서 ggplot으로 시각화한다. 먼저 이미지를 255로 나눠 0-1 사이 값을 갖도록 변환하고 해당되는 이미지를 \(5 \times 5\) 총 25개 이미지를 한장의 이미지에 담는다.

> train_images <- train_images / 255
> test_images <- test_images / 255
> 
> par(mfcol=c(5,5))
> par(mar=c(0, 0, 1.5, 0), xaxs='i', yaxs='i')
> for (i in 1:25) { 
+   img <- train_images[i, , ]
+   img <- t(apply(img, 2, rev))
+   image(1:28, 1:28, img, col = gray((0:255)/255), xaxt = 'n', yaxt = 'n',
+         main = paste(class_names[train_labels[i] + 1]))
+ }

3 딥러닝 예측모형

3.1 계층 설정(Setup the layer)

첫번째 계층은 입력값(\(25 \times 25 = 784 \text{픽셀}\))을 받도록 layer_flatten()을 지정하고, 두 dense 계층을 쌓는데 노드크기가 128, 10개로 활성화 함수를 relu, softmax로 지정한다.

> model <- keras_model_sequential()
> model %>%
+   layer_flatten(input_shape = c(28, 28)) %>%
+   # layer_conv_2d(filter = 32, kernel_size = c(3,3), input_shape = c(28, 28, 1), padding = "same", activation = 'relu') %>% 
+   # layer_max_pooling_2d(pool_size = c(2, 2)) %>% 
+   layer_dense(units = 128, activation = 'relu') %>%
+   layer_dropout(rate = 0.7) %>%
+   layer_dense(units = 64, activation = 'relu') %>%
+   layer_dropout(rate = 0.7) %>%
+   layer_dense(units = 64, activation = 'relu') %>%
+   layer_dropout(rate = 0.7) %>%
+   layer_dense(units = 128, activation = 'relu') %>%
+   layer_dropout(rate = 0.7) %>%
+   layer_dense(units = 10, activation = 'softmax')

3.2 모형 컴파일(compile-the-model)

다음으로 손실함수(loss function), 최적화(optimizer)도구, 측도(metrics)를 지정하여 컴파일 한다.

> model %>% compile(
+   optimizer = 'adam', 
+   loss = 'sparse_categorical_crossentropy',
+   metrics = c('accuracy')
+ )

3.3 모형 훈련(train-the-model)

fit 함수에 훈련 이미지를 넣고, 훈련라벨을 지정하여 이폭을 10회ㅣ 저정하여 학습을 시킨다.

> model %>% fit(train_images, train_labels, epochs = 5)

3.4 모형 평가(evaluate-the-model)

evaluate() 함수를 통해서 훈련에 사용된 적이 없는 시험 데이터를 활용해서 패션 MNIST 옷범주 예측 성능을 평가한다.

> score <- model %>% evaluate(test_images, test_labels)
> 
> cat('Test loss:', score$loss, "\n")
Test loss: 1.146743 
> cat('Test accuracy:', score$acc, "\n")
Test accuracy: 0.5077 

3.5 예측

evaluate() 함수를 통해서 훈련에 사용된 적이 없는 시험 데이터를 활용해서 패션 MNIST 옷범주 예측 성능을 평가한다.

> predictions <- model %>% predict(test_images)
> predictions[1,]
 [1] 1.512148e-22 2.153349e-14 1.860881e-31 5.056279e-23 6.735633e-31
 [6] 5.098696e-01 1.017952e-25 1.294642e-01 3.923463e-02 3.214315e-01
> which.max(predictions[1, ])
[1] 6
> class_pred <- model %>% predict_classes(test_images)
> class_pred[1:20]
 [1] 5 2 1 1 2 3 2 2 5 7 2 8 8 3 2 3 2 2 8 2

3.6 예측결과 시각화

예측결과 맞으면… 녹색, 틀리면 붉은색으로 이미지 분류예측한 결과를 시각화하여 확인한다.

> par(mfcol=c(5,5))
> par(mar=c(0, 0, 1.5, 0), xaxs='i', yaxs='i')
> for (i in 1:25) { 
+   img <- test_images[i, , ]
+   img <- t(apply(img, 2, rev)) 
+   # subtract 1 as labels go from 0 to 9
+   predicted_label <- which.max(predictions[i, ]) - 1
+   true_label <- test_labels[i]
+   if (predicted_label == true_label) {
+     color <- '#008800' 
+   } else {
+     color <- '#bb0000'
+   }
+   image(1:28, 1:28, img, col = gray((0:255)/255), xaxt = 'n', yaxt = 'n',
+         main = paste0(class_names[predicted_label + 1], " (",
+                       class_names[true_label + 1], ")"),
+         col.main = color)
+ }

직접 이미지를 넣어 예측할 수도 있다.

> smpl_img <- test_images[1, , , drop = FALSE]
> dim(smpl_img)
[1]  1 28 28
> smpl_predictions <- model %>% predict(smpl_img)
> smpl_predictions
             [,1]         [,2]         [,3]         [,4]        [,5]
[1,] 1.512153e-22 2.153364e-14 1.860908e-31 5.056391e-23 6.73568e-31
          [,6]        [,7]      [,8]       [,9]     [,10]
[1,] 0.5098692 1.01796e-25 0.1294645 0.03923471 0.3214316
> class_pred <- model %>% predict_classes(smpl_img)
> class_pred
[1] 5