Introdução e objetivo

A base de dados utilizada para o programa está dísponível por meio do link: https://www.kaggle.com/c/digit-recognizer/leaderboard. Os arquivos de dados train.csv e test.csv contêm uma série de números desenhados, sendo eles de 1 à 9. Cada imagem tem uma certa quantidade de pixel, e o código em questão deverá analisar percorrer linhas e colunas de pixels de uma imagem preenchida por números com a finalidade de mostrar quais números em questão estão presentes.

O código

#Loading Libraries
library(tidyverse)
## -- Attaching packages ------------------------------------- tidyverse 1.2.1 --
## v ggplot2 3.2.1     v purrr   0.3.3
## v tibble  2.1.3     v dplyr   0.8.3
## v tidyr   1.0.0     v stringr 1.4.0
## v readr   1.3.1     v forcats 0.4.0
## -- Conflicts ---------------------------------------- tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(keras)
library("magick")
## Linking to ImageMagick 6.9.9.14
## Enabled features: cairo, freetype, fftw, ghostscript, lcms, pango, rsvg, webp
## Disabled features: fontconfig, x11

Na primeira parte, observamos que estão sendo carregados os pacotes necessários para o funcionamento do programa.

 img <- image_read("D:/Users/Usuario/Downloads/RedesNeuraisDigit.jpg")
 img

 img28x28 <- img %>% image_scale(geometry = 28)
 img28x28

 img_dados <- image_data(img28x28, channels = "gray")

 img_num <- img_dados %>% as.numeric()
 img_num2 <- img_num[,,1]

 image(img_num2)

 imgD2 <- image_read("D:/Users/Usuario/Downloads/RedesNeuraisDigit.jpg") %>%
   image_scale(geometry = "28x28") %>%
   image_data(channels = "gray") %>%
   .[1,,] %>%
   as.numeric()

 imgD2 %>% matrix(nrow = 28, byrow = TRUE) %>%
   image()
 imgD2neg <- 1-imgD2


 imgD2 <- image_read("D:/Users/Usuario/Downloads/RedesNeuraisDigit.jpg") %>%
   image_scale(geometry = "28x28") %>%
   image_data(channels = "gray") %>%
   .[1,,] %>%
   as.numeric()



 imgD2 %>% matrix(nrow = 28, byrow = TRUE) %>%
   image()

 imgD2neg <- (255-imgD2)/255


 imgD6n <- (255-imgD2)/255
 imgD0n2 <- ifelse(imgD2neg < .4, 0, 1)
 imgD6n2 <- ifelse(imgD2neg < .4, 0, 1)
 imgD0n2 %>% matrix(nrow = 28, byrow = TRUE) %>%
   image(col = grey.colors(255))

 imgD2neg %>% matrix(nrow = 28, byrow = TRUE) %>%
   apply(2,rev) %>%
   t() %>%
   image()

O código acima serve para gerar os caracteres em qual vão ser baseadas as leituras. Os caracteres vão ser enumerados de 0 à 9 e todos têm a mesma quantidade de pixels e estão apresentados em uma escala de cor cinza para que o programa reconheça melhor a forma e seja mais fácil compreendido na hora de determinar quais os números correspondentes na imagem que irá ser adicionada.

test <- read_rds("teste.rds")
label <- read_rds("label_test.rds")
train <- read_rds("train.rds")

# Constants
img_rows <- 28
img_cols <- 28
n_classes <- 10

O número de classes da variável resposta e as dimensões da matriz são fixadas.

# Creating a function

# Start Function
Label <- function(digits, base, nrows = 28, ncols = 28){
  stopifnot(digits %in% 1:nrow(base))
  if ("label" %in% colnames(base))
  {
    cat("\nRemoving label column...")
    base <- base %>% select(-label)
  }
  if ("Flag" %in% colnames(base))
  {
    cat("\nRemoving Flag column...")
    base <- base %>% select(-Flag)
  }
  # Check graphical parameters
  val <- par(no.readonly=TRUE)
  n <- ceiling(sqrt(length(digits)))
  par(mfrow = c(ceiling(length(digits)/n),n), mar = c(0.1, 0.1, 0.1, 0.1))
  for (i in digits){
    m <- base %>%
      filter(row_number() == i) %>%
      unlist() %>%
      matrix(nrow = nrows, ncol = ncols, byrow = TRUE) %>%
      apply(2, rev) %>%
      t() %>%
      image(col = grey.colors(255), axes = FALSE)
  }
  # reset the original graphics parameters
  par(val)
}

# Call Function
Label(101:109, train)


x_train <- train %>%
  select(-label, -Flag) %>%
  mutate_all(function(x) x/255) %>%
  as.matrix()

x_test <- train %>%
  filter(Flag == 1) %>%
  select(-label, -Flag) %>%
  mutate_all(function(x) x/255) %>%
  as.matrix()

y_train <- train %>%
  select(label) %>%
  as.matrix() %>%
  to_categorical(num_classes = 10)



# Evaluate# Defining the RNN Model
rnn_model <- keras_model_sequential()
rnn_model %>%
  layer_dense(units = 64, activation = 'relu', input_shape = c(img_cols*img_rows)) %>%
  layer_dropout(rate = 0.4) %>%
  layer_dense(units = 32, activation = 'relu') %>%
  layer_dropout(rate = 0.2) %>%
  layer_dense(units = 16, activation = 'relu') %>%
  layer_dropout(rate = 0.1) %>%
  layer_dense(units = n_classes, activation = 'softmax')

summary(rnn_model)



##
predict_classes(rnn_model, t(imgD2neg))
t(predict(rnn_model, t(imgD2neg))) %>% round(2)
#



rnn_model %>% compile(
  loss = 'categorical_crossentropy', #categorical_accuracy
  optimizer = optimizer_rmsprop(),
  metrics = c('accuracy')
)

# Training and Evaluation
history <- rnn_model %>% fit(
  x_train, y_train,
  epochs = 30, batch_size = 128,
  validation_split = 0.2,
  callbacks = list(
    callback_early_stopping(monitor = "val_acc", min_delta = 0.001,
                            patience = 10,
                            verbose = 1,
                            mode = "auto",
                            restore_best_weights = TRUE))
)

plot(history)
rnn_model %>% evaluate(test,label)

#imager
predict_classes(rnn_model, t(test[1,]))

O processo de leitura da imagem vai avançando à medida em que vai percorrendo cada pixel da mesma sendo comparada com os números presente na base de dados. Logo depois é possível observar o processo no gráfico, onde nos é mostrado os valores da função de perda e de acurácia. Por fim o programa gera a probabilidade de cada número da base de dados que correspondem ao número da imagem escolhida e de qual número a imagem se trata.