Redes Neurais Convolutivas – CNN

Neste post vamos abordar as Redes Neurais Convolutivas (Convolutional Neural Networks, CNNs). As CNNs foram primeiramente propostas em 1998 por LeCun et al. [1], na qual os autores desenvolveram uma arquitetura neural conhecida como LeNet5, utilizada para reconhecer dígitos escritos à mão. Na ocasião, tal arquitetura estabeleceu um novo estado da arte ao atingir 99.2% de acurácia na base de dados MNIST [2]. Anos mais tarde, a Krizhevsky et. al [3] estabeleceram um marco na área ao propor a AlexNet, arquitetura vencedora do desafio ImageNet [4]. Desde então, aplicação mais popular relacionada a CNNs vêm sendo reconhecer padrões em imagens, todavia, diversos trabalhos vêm aplicando CNNs em outros tipos de tarefas [5].

As CNNs são similares a redes neurais tradicionais: ambas são compostas por neurônios que possuem pesos e bias que necessitam ser treinados. Cada neurônio recebe algumas entradas, aplica o produto escalar das entradas e pesos além de uma função não-linear. Além disso, ambas possuem a última camada toda conectada e todos os artifícios utilizados para melhorar a rede neural tradicional também são aplicados nesta camada. Dessa forma, qual a vantagem de se utilizar uma CNN? Uma CNN assume que todas as entradas são imagens, o que permite codificar algumas propriedade na arquitetura. Redes neurais tradicionais não são escaláveis para imagens, uma vez que a mesma produz um número muito alto de pesos a serem treinados [6].

Uma CNN é composta por uma sequência de camadas. Além da camada de entrada, que normalmente é composta por uma imagem com largura, altura e profundidade (RGB), exitem três camadas principais: camada convolucional, camada de pooling e camada totalmente conectada. Além disso, após uma camada de convolução é comum uma camada de ativação (normalmente uma função ReLu). Essas camadas, quando colocadas em sequência (ou empilhadas), forma uma arquitetura de uma CNN, como ilustrada na Figura 1. Ao longo do post, vamos descrever as principais camadas, bem como suas respectivas funções.

Figura 1: exemplo de uma arquitetura de uma CNN

A camada convolutiva

A camada convolucional é a camada mais importante da rede. Nela é realizada a parte mais pesada do processamento computacional. Esta camada é composta por um conjunto de filtros (ou kernels) capazes de aprender de acordo com um treinamento. Os filtros são matrizes pequenas (por exemplo, 5 x 5 x 3) compostas por valores reais que podem ser interpretado como pesos. Esses filtros são convoluídos com os dados de entradas para obter um mapa de características. Estes mapas indicam regiões na qual características específicas em relação ao filtro, são encontradas na entrada. Os valores reais dos filtros se alteram ao longo do treinamento (assim como os pesos de uma rede neural tradicional) fazendo com que a rede aprenda a identificar regiões significantes para extrair características do conjunto de dados.

Figura 2: Exemplo de convolução entre a imagem e um filtro

A convolução entre um filtro e a imagem é ilustrado na Figura 2. Neste exemplo é apresentada uma imagem 4 x 4 x 3 e um filtro 2 x 2 x 3. A convolução é realizada através do produto escalar de uma região da imagem do tamanho do filtro pelo filtro propriamente dito. Na sequência o filtro é deslizado para outra região e o produto escalar é realizado novamente até que toda a imagem seja percorrida. Perceba que cada canal é convoluído por uma dimensão diferente do filtro, que neste exemplo esta representado pela mesma cor do canal (RGB). Neste exemplo o filtro desliza na imagem deslocando 1 pixel para lado ou para baixo. Este deslizamento é controlado pelo parâmetro conhecido como stride, que neste caso é 1. Este valor pode ser alterado, todavia deve respeitar os limites da imagem. Caso o tamanho do filtro e do stride desejado não seja possível para a imagem, pode-se utilizar zero-padding, que nada mais é do que adicionar zeros na borda da imagem para tornar o deslizamento do filtro possível. Tanto o stride quanto zero-padding são parâmetros de projetos que deve ser analisados pelo projetista. Por fim, vale a pena destacar que podem existir (e normalmente existem) mais de um filtro por camada de convolução. Dessa forma, cada filtro resulta em uma saída de três dimensões, como o da Figura 2.

Nas matrizes resultados da convolução é aplicado a função de ativação. A função mais utilizada é a ReLU (unidade de retificação linear), que é simplesmente aplicar a função max(0,x) em cada elemento do resultado da convolução. No exemplo da Figura 2, todos os elementos são maiores do que zero, sendo assim, o resultado da ReLU são os próprios valores. Por fim, como os pesos utilizados por cada filtro são os mesmos em todas as regiões, ele são conhecidos como pesos compartilhados. Essa característica reduz consideravelmente a quantidade de pesos da CNN quando comparadas a uma RNA.

 

A camada de pooling

É muito comum após uma camada de convolução existir uma camada de pooling. A técnica de pooling é utilizada com objetivo de reduzir o tamanho espacial das matrizes resultantes da convolução. Consequentemente, essa técnica reduz a quantidade de parâmetros a serem aprendidos na rede, contribuindo para o controle de overfitting. As camadas de pooling operam de maneira independente em cada um dos canais do resultado da convolução. Além disso, é necessário determinar previamente o tamanho do filtro e stride para realizar o pooling. Na Figura 3 é ilustrado a realização de pooling considerando que o resultado da convolução seja uma matriz 4 x 4 x 3, o filtro do pooling abrange regiões 2 x 2 em cada canal, com stride igual a 2. Além disso, a função de agregação é  igual a max (X), ou seja, escolhe o maior valor da região.

Figura 3: exemplo de max pooling the uma imagem 4 x 4

Como pode ser observado, a camada de pooling não reduz a quantidade de canais e sim a quantidade de elementos em cada canal. Além do maxpooling, pode ser utilizadas outras funções, como por exemplo a média dos valores. Todavia, a função max vem obtendo melhores resultados, uma vez que pixels vizinhos são altamente correlacionados.

A camada totalmente conectada

Diferentemente da camada convolucional, na qual os pesos são conectados apenas em uma região, a camada totalmente conectada, como o próprio nome já sugere, é completamente conectada com a camada anterior. Tipicamente são utilizadas como última camada da CNN e funciona da mesma maneira que as redes neurais tradicionais. Portanto, as mesmas técnicas para melhorar o desempenho de uma RNA, como dropout por exemplo, também são aplicáveis nesta camada.

Como a camada totalmente conectada vêm após uma camada convolucional ou de pooling, é necessário conectar cada elemento das matrizes de saída de convolução em um neurônio de entrada. A Figura 4 ilustra a conexão de uma camada convolucional com uma camada totalmente conectada. É possível observar que os 48 mapas de características 4 x 4 são colocados de forma linear formando 768 entradas para camada totalmente conectada, que por sua vez, possui 500 neurônios ocultos que resultam em 10 saídas para rede. Neste ponto, é possível observar visualmente um rede neural tradicional.

Figura 4: ilustração de uma camada totalmente conectada

Nas unidades de saída, que no exemplo da Figura 4 são 10, é utilizado uma função softmax para se obter a probabilidade de dada entrada pertencer a uma classe. Neste ponto é realizado o algoritmo de treinamento supervisionado backpropagation, assim como em uma rede neural tradicional. O erro obtido nesta camada é propagado para que os pesos dos filtros das camadas convolucionais sejam ajustados [1]. Dessa forma, os valores dos pesos compartilhados são aprendidos ao longo do treinamento. Neste post, não vamos nos aprofundar no treinamento da rede. A intenção aqui é apresentar a estrutura e funcionamento da rede. Em breve, vamos dedicar um outro post inteiramente sobre isso. Todavia, você poderá utilizar as bibliotecas linkadas no final do texto, no qual o treinamento é realizado como uma black box para o usuário.

A arquitetura de uma CNN

A arquitetura de uma CNN é relacionada com a maneira que as camadas descritas anteriormente são organizadas. De fato o projetista pode organizá-las da maneira que julgar adequado. A maior parte das arquiteturas utilizam uma camada de entrada, obviamente, seguida de um bloco de N camadas convolucionais com ativação ReLU conectada a uma camada de pooling. Esse bloco é repetido M vezes ao longo da rede que ao final é conectado a uma camada totalmente conectada para determinar a classificação final. Além disso, na montagem da arquitetura também são definidos parâmetros como tamanho do filtro, stride e zero-padding}. Todas essas escolhas impactam diretamente na quantidade de pesos que a rede deve treinar e por consequência o quanto de computação é necessário para que esses valores sejam bem ajustados.

Existem diversas arquiteturas bem conhecidas na área de redes convolucionais. Três das mais utilizadas são descritas na sequência:

  • LeNet-5: como já mencionado, foi desenvolvida por LeCun et al. [1] e foi a primeira aplicação de CNN que obteve sucesso de fato. Foi utilizada para classificar dígitos, por conta disso, muito utilizada em tarefas como leitura de códigos postais e afins. A Figura 5 ilustra a arquitetura de uma LeNet-5, que possui uma camada de entrada com imagens de 32 x 32 pixels e mais 7 camadas de pesos treináveis. As camadas convolucionais utilizam filtros 5 x 5 x 3 e 6 x 6 x 3 para computar os mapas de características e filtros 2 x 2 x 3 para realização de pooling. Por fim, além da camada de saída que possui conexão para 10 classes, a rede possui duas camadas totalmente conectadas de 120 e 84 neurônios.

Figura 5: a arquitetura de uma Lenet-5

  • AlexNet: a arquitetura AlexNet foi o trabalho que popularizou as CNNs para visão computacional. Proposta por Krizhevsky et al. [3], como já mencionado anteriormente, foi a metodologia vencedora do desafio ImageNet em 2012. Sua arquitetura é bastante similar à da LeNet-5, porém ela é mais profunda, com mais camadas convolucionais, e possui muito mais mapas de característica, como mostrado na Figura 6. A AlexNet recebe como entrada imagens de 224 x 224 pixels por canal. Na primeira camada de convolução utiliza um filtro de 11 x 11 x 3, na segunda 5 x 5 x 3 e na terceira a diante 3 x 3 x 3. Além disso, a terceira, quarta e quinta camada são conectadas sem utilização de pooling. Por fim, a a rede possui duas camadas totalmente conectadas com 2048 neurônios cada e uma camada de saída com 1000 neurônios, quantidade de classes existentes no problema. Vale a pena destacar que a AlexNet foi a primeira rede a utilizar dropout [7] para auxiliar no treinamento da camada totalmente conectada. Além disso, o treinamento de toda a rede foi realizado utilizando duas GPUs. Como pode ser observado na Figura 6, a rede é dividida em duas partes, uma GPU executou a parte de cima e a outra a parte de baixo da rede.

Figura 6: a arquitetura de uma AlexNet

  • VGGNet: a arquitetura VGGNet foi proposta por Simonyan e Zisserman [8] e teve como principal contribuição mostrar que a profundidade da rede é um componente crítico para uma boa performance. O modelo padrão da VGGNet possui diversas camadas de convolução aplicando filtros 3 x 3 x 3 e maxpooling com filtros 2 x 2 x 3. Na Figura 7 é ilustrado uma comparação entre uma AlexNet e uma VGGNet. É possível observar uma camada de pooling sempre após duas de convolução. Além disso, a rede possui três camadas totalmente conectadas além da camada de saída. Devido a sua profundidade, a VGGNet é bem cara computacionamente e necessita de muita memória para computar em cima de seus parâmetros (~140M).

Figura 7: comparação entre as arquiteturas AlexNet e VGGNet

Considerações finais e frameworks

Como você deve ter percebido até aqui, com os blocos principais da CNN você pode contruir a arquitetura que melhor te atende. Todavia, nem sempre é fácil encontrar um padrão e parâmetros que se encaixe perfeitamente no seu problema. A grande vantagem da CNN é que ela é capaz de extrair as características das imagens de entrada sem necessidade de um pré-processamento nas mesmas. Quanto mais camadas de convolução, mais características são extraídas. Todavia, assim como em redes neurais tradicionais, é preciso ter cuidado com overfiting e com características inúteis. Por exemplo, a Lenet é aplicada para problemas de identificação de caracteres, por isso ela é pequena e desempenha sua função quase de maneira ótima. Já a VGGnet é aplicada para imagens com mais de 1000 rótulos, portanto existem muito mais características a serem extraídas do que a os caracteres a mão. Se aplicarmos a VGGNet para MNIST estamos “matando uma barata com uma bazuca”, pois não há necessidade de uma rede tão grande para tal problema. Infelizmente não existe uma formula secreta para escolher todos esses parâmetros (stride, camadas, zero-padding etc). Essa habilidade só vem com a prática e com o uso da CNN.

Aproveitando o gancho da prática, você pode utilizar CNNs de maneira bem simples e rápida, por meio do uso de frameworks. Alguns de uso mais rápido, só escolher os parâmetros, inserir os dados de treinamento e executar, e outros que necessitam um pouco mais de elaboração. Além disso, você pode ou não utilizar GPUs de acordo com a ferramenta utilizada e a disponibilidade na máquina. Sugerimos três frameworks:

  • Keras: mais simples e de uso bem direto. Por conta disso, é menos maleável a modificações. Além disso, é necessário ter instalado o tensorflow na máquina. A linguagem utilizada é Python.
  • Tensorflow: por falar nele, essa é nossa segunda recomendação. Framework desenvolvido pela Google que massivamente utilizado na área de machine learning. Nela são implementadas os principais build blocks da CNN e você pode utilizá-los para montar sua arquitetura. Vai demandar um pouco mais de prática para dominá-las, mas é mais poderosa do que a Keras (na verdade a Keras é construída em cima da Tensorflow, ou seja, é como se fosse um facilitador para a mesma). Também utiliza Python (apesar de estar ampliando para novas linguagens).
  • Caffe: essa é para os amantes de C/C++, linguagem utilizadas pela biblioteca. Nela você pode implementar suas arquiteturas bem parecido com o Keras.

That’s all folks! Até o próximo post.

Referências

[1] Y. LeCun, L. Bottou, Y. Bengio, and P. Haffner, “Gradient-based learning applied to document recognition,” Proceedings of the IEEE, vol. 86, no. 11, pp. 2278–2324, 1998

[2] L. Yann, C. Corinna, and B. Christopher, “The MNIST database of handwritten digits,” disponível em: https://www.kaggle.com/c/thenature- conservancy-fisheries-monitoring/details/evaluation, visitado em 8 de dezembro de 2016.

[3] A. Krizhevsky, I. Sutskever, and G. E. Hinton, “Imagenet classification with deep convolutional neural networks,” in Advances in neural information processing systems, 2012, pp. 1097–1105.

[4] J. Deng, W. Dong, R. Socher, L.-J. Li, K. Li, and L. Fei-Fei, “Imagenet: A large-scale hierarchical image database,” in Computer Vision and Pattern Recognition, 2009. CVPR 2009. IEEE Conference on. IEEE, 2009, pp. 248–255.

[5] E. Gibney, “Google ai algorithm masters ancient game of go,” Nature, vol. 529, pp. 445–446, 2016.

[6] F.-F. Li, A. Karpathy, and J. Johnson, “Cs231n: Convolutional neural networks for visual recognition,” 2015

[7] N. Srivastava, G. E. Hinton, A. Krizhevsky, I. Sutskever, and R. Salakhutdinov, “Dropout: a simple way to prevent neural networks from overfitting.” Journal of Machine Learning Research, vol. 15, no. 1, pp. 1929–1958, 2014.

[8] K. Simonyan and A. Zisserman, “Very deep convolutional networks for large-scale image recognition,” arXiv preprint arXiv:1409.1556, 2014.

Gostou? Então compartilhe!