캐글 패션 MNIST를 다운로드 받아도 되고, RStudio Keras를 설치하게 되면 포함된 데이터를 사용해도 된다.
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, ...)
+ }
훈련과 시험 데이터로 이미지를 나누고, 훈련데이터 수는 70,000개 중에서 60,000개, 시험데이터는 10,000개로 구성된다. table(train_labels)
함수로 10개 범주에 각 6,000개씩 훈련범주로 구성된 것이 확인된다.
그중에서 이미지 하나를 뽑아내서 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("")
그중에서 이미지 다수 뽑아내서 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]))
+ }
첫번째 계층은 입력값(\(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')
다음으로 손실함수(loss function), 최적화(optimizer)도구, 측도(metrics)를 지정하여 컴파일 한다.
> model %>% compile(
+ optimizer = 'adam',
+ loss = 'sparse_categorical_crossentropy',
+ metrics = c('accuracy')
+ )
fit
함수에 훈련 이미지를 넣고, 훈련라벨을 지정하여 이폭을 10회ㅣ 저정하여 학습을 시킨다.
> model %>% fit(train_images, train_labels, epochs = 5)
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
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
예측결과 맞으면… 녹색, 틀리면 붉은색으로 이미지 분류예측한 결과를 시각화하여 확인한다.
> 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