Introdução

A CNN(“Convolucional Neural Networking”) é um modelo de rede neural comumente utilizado em reconhecimento de imagens e processamento de vídeo. O principal objetivo dessa classe de modelo é de diminuir o máximo possível o nível de pré-processamento do modelo utilizando filtros, ou seja, essa rede consegue aprender os filtros que em um só algoritmo. Como visto anteriormente as redes Neurais recebem uma entrada (um único vetor) e a transformam em uma série de camadas ocultas , porém, essas rede neurais regulares não são bem dimensionadas para imagens completas, como por exemplo em imagens com largura, altura e profundidade(canais de cores), visto que para esse tipo de dados, quando se trata de imagens com dimensões maiores, a estrutura totalmente conectada dos neurônios da rede neural regular termina produzindo neurônios com incontáveis pesos, trazendo um desperdício e o grande número de parâmetros levaria rapidamente ao sobreajuste.

Objetivos

O objetivo principal deste relatório é de propor um modelo de rede neural convolucional (CNN) tal que consiga classificar de forma mais eficaz o dígito. A ideia por trás dos algoritmos apresentados é de manipular a base de dados tal que consiga melhorar a capacidade de entendimento da rede neural, como por exemplo, utilizando bootstrap. Outro ponto a ser discutido, é na escolha no número de camadas de cada rede neural, afim de estudar na relação do aumento de número de camadas com o aumento da acurácia. Nesse relatório, será utilizado filtros de convolução

Base de dados

A base de daods em questão se trata da mesma basede dígitos utilizada anteriormente. Ela é dividida em teste, treinamento e label.

library(keras)
library(tidyverse)
# Constantes utilzada no modelo
img_rows <- 28
img_cols <- 28
n_classes <- 10

Os arquivos foram fornecidos, em formato rds.

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

Rede Neural 1

Nesta seção, será aplicado a CNN comum, sem aumentar a base de dados.

Formalizando a base de treino, utilizando os códigos abaixo, é obtido os dados principais denominados de x_train e y_train. No qual x_train é representado pelos pixels dos dígitos e y_train é uma matriz representando que dígito aquela observação representa.

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

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

Refindindo as dimensões da base de treino e teste, utilizando dimensões \(28 \times 28 \times 1\), ou seja, com 1 de altura, 28 de largura e apenas 1 canal de cor.

# Redefine dimension of train/test inputs
x_train_cnn <- array_reshape(x_train, c(nrow(x_train), img_rows, img_cols, 1))
cnn_test <- array_reshape(test, c(nrow(test), img_rows, img_cols, 1))
input_shape <- c(img_rows, img_cols, 1)

Após isso, podemos introduzir o modelo 1 de redes neurais convolucionais, foi utilizado duas camadas de filtros, sendo a primeira camada com 64 filtros com matriz de dimensão \(3 \times 3\) utilizando a função de ativação “relu”, na segunda camada o número de filtros foi reduzido para 32, mantendo tanto a dimensão como a função de ativação. Vale dizer que em embas dessas camadas de filtro, foi utilizada uma subcamada denominada de “Pool”, no qual, a sua função é reduzir progressivamente o tamanho espacial dessa representação para reduzir a quantidade de parâmetros e computação no modelo e, portanto, controlar também o excesso de ajuste (overfitting). Nesse caso, foi aplicada essas duas subcamadas pool, reduzindo a dimensão para $ 22$.

Em relação às camadas regulares da rede neural, foi utilizada duas camadas, sendo a primeira com apenas 128 neurônios e na segunda e ultima camada com 10 neurônios, que tem que ser justamento o número de classificações possíveis no problema, ou seja, dígitos de 0 a 9. Nessa última camada vai ser utilizada a função softmax, no qual ela vai pegar o neurônio com maior valor obtido, assim transformando o valor em probabilidade. Utilizando a expressão: \(\dfrac{e^{x_i}} {\sum_{i=1}^{n}e^{x_{i}}}\), sendo \(n\) o número total de neurônios restantes.

model_cnn <- keras_model_sequential() %>%
  layer_conv_2d(
    filters = 64,
    kernel_size = c(3, 3),
    activation = 'relu',
    input_shape = input_shape
  ) %>%
  layer_conv_2d(filters = 32,
                kernel_size = c(3, 3),
                activation = 'relu') %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  layer_dropout(rate = 0.25) %>%
  layer_flatten() %>%
  # these are the embeddings (activations) we are going to visualize
  layer_dense(units = 128, activation = 'relu', name = 'features') %>%
  layer_dropout(rate = 0.25) %>%
  layer_dense(units = 10, activation = 'softmax')

# Compile model
model_cnn %>% compile(
  loss = "categorical_crossentropy",
  optimizer = optimizer_adadelta(),
  metrics = c('accuracy')
)

Foi utilizando no código abaixo 15 iterações no modelo, uma condição de parada no algoritmo, tal que, após as realizações dos resultados, se com isso for atingido o esperado, o programa vai parar com até 8 iterações.

history <- model_cnn %>% fit(
  x_train_cnn, y_train,
  epochs = 15, batch_size = 128,
  validation_split = 0.2,
  callbacks = list(
    callback_early_stopping(monitor = "val_acc", min_delta = 0.01,
                            patience =8,
                            verbose=0,
                            mode = "auto",
                            restore_best_weights = TRUE) )
)

Vizualizando as interações do modelo e a acurácia final.

plot(history)

model_cnn %>% evaluate(cnn_test, label)
## $loss
## [1] 0.05654933
## 
## $acc
## [1] 0.9831274

Rede Neural 2

Nesta seção será utilizada uma técnica comumente utilziada na aplicação de redes neurais, com o objetivo de aumentar a base de dados trabalhada atráves de realizações de bootstrap, visando por final aumentar a acurácia do modelo. A ideia principal é de replicar 1 vezes (no caso do códigos abaixo) a amostra de treinamento. Foi denominado de “new_data”, como a base de treinamento já era composta de 37792 observações, então “new_data” apresenta o mesmo número de observações, porém sorteadas aleatoriamente. Posteriormente, vai ser criada novas bases de treinamento, denominadas de “x_train_augmented” e “y_train_augmented”, que no mesmo caso anterior, corresponde a parte númerica do treinamento e a parte matricial representativa dos dígitos, respectivamente. Essas novas bases, é nada mais nada menos que as bases anteriores só que com o adicional de “new_data”. A ideia por trás dessas operações é de gerar novas informações e de uma forma que com isso “alimentar” a rede neural com mais dessas informações.

newdata<- train %>% 
  filter(Flag == 0) %>%
  sample_frac(1, replace = TRUE)

Unindo a antiga base de treinamento com a nova criada e padronizando posteriormente. Como já tinha sido divida a base de treinamento de em duas partes, a parte x_train foi adicionada apenas as partes representadas pelos pixels, a parte y_train, foi adicionado apenas os novos labels.

x_train_augmented<-train %>% 
  filter(Flag == 0) %>%
  bind_rows(newdata) %>% 
  select(-label, -Flag) %>% 
  mutate_all(function(x) x/255) %>%
  as.matrix()

y_train_augmented <- train %>%
  filter(Flag == 0) %>%
  bind_rows(newdata) %>% 
  select(label) %>%
  as.matrix() %>%
  to_categorical(num_classes = 10)

Refindindo as dimensões da base de treino e teste, utilizando dimensões \(28 \times 28 \times 1\), ou seja, com 1 de altura, 28 de largura e apenas 1 canal de cor.

x_train_cnn <- array_reshape(x_train_augmented, c(nrow(x_train_augmented), img_rows, img_cols, 1))
cnn_test <- array_reshape(test, c(nrow(test), img_rows, img_cols, 1))
input_shape <- c(img_rows, img_cols, 1)

Em relação ao modelo anterior, na parte das camadas de filtro, foi mantida a mesma configuração. Nas camadas regulares, houve um aumento no número de neurônios com 1024 deles na primeira camada, 512 na segunda camada e por final com 10 neurônios restantes para o resultado de classificação.

model_cnn <- keras_model_sequential() %>%
  layer_conv_2d(
    filters = 64,
    kernel_size = c(3, 3),
    activation = 'relu',
    input_shape = input_shape
  ) %>%
  layer_conv_2d(filters = 32,
                kernel_size = c(3, 3),
                activation = 'relu') %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  layer_dropout(rate = 0.25) %>%
  layer_flatten() %>%
  # these are the embeddings (activations) we are going to visualize
  layer_dense(units = 1024, activation = 'relu', name = 'features') %>%
  layer_dropout(rate = 0.4) %>%
  layer_dense(units = 512, activation = 'relu') %>% 
  layer_dropout(rate = 0.2) %>%
  layer_dense(units = 10, activation = "softmax")

# Compile model
model_cnn %>% compile(
  loss = "categorical_crossentropy",
  optimizer = optimizer_adadelta(),
  metrics = c('accuracy')
)
history <- model_cnn %>% fit( x_train_cnn, y_train_augmented,
                              epochs = 15, batch_size = 128,
                              validation_split = 0.2,
                              callbacks = list(
                                callback_early_stopping(monitor = "val_acc", min_delta = 0.01,
                                                        patience =8,
                                                        verbose=0,
                                                        mode = "auto",
                                                        restore_best_weights = TRUE) )
)

Vizualizando as interações do modelo e a acurácia final.

plot(history)

model_cnn %>% evaluate(cnn_test, label)
## $loss
## [1] 0.04036503
## 
## $acc
## [1] 0.990019

#Conclusão Em suma, as redes neurais convolucionais se tornaram superiores em relação as redes neurais regulares para detecção de imagem. O segundo modelo foi o que obteve melhor resultado, com uma acurácia superior ao primeiro modelo.